console: POC db connect select database draft design [GCU-107]
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7897 GitOrigin-RevId: 4da175532c5422bd8985b9134f5aba7b190d05e0
6
frontend/.vscode/settings.json
vendored
@ -2,8 +2,12 @@
|
|||||||
"eslint.validate": ["json"],
|
"eslint.validate": ["json"],
|
||||||
"cSpell.words": ["clsx", "hasura", "citus"],
|
"cSpell.words": ["clsx", "hasura", "citus"],
|
||||||
"tailwindCSS.experimental.classRegex": [
|
"tailwindCSS.experimental.classRegex": [
|
||||||
|
// detects in simple variables like const twFoo = `pt-2`;
|
||||||
"tw\\w+ ?= ?`([^`]*)`",
|
"tw\\w+ ?= ?`([^`]*)`",
|
||||||
"tw\\w+: ?`([^`]*)`"
|
// detects tw strings in clsx function calls like: clsx('pt-2', 'relative');
|
||||||
|
["clsx\\(([^)]*)\\)", "(?:'|\"|`)([^`]*)(?:'|\"|`)"],
|
||||||
|
// detects strings in objects and nested objects. Just prefix variable name with tw like so: const twStyleObject = {};
|
||||||
|
["tw\\w+ = {\\s+([^;]+)\\s+};", "(?:'|\"|`)([^`]*)(?:'|\"|`)"]
|
||||||
],
|
],
|
||||||
"tailwindCSS.rootFontSize": 14
|
"tailwindCSS.rootFontSize": 14
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
import { hasuraToast } from '@/new-components/Toasts';
|
||||||
|
import { useArgs } from '@storybook/client-api';
|
||||||
|
import { ComponentMeta, ComponentStory } from '@storybook/react';
|
||||||
|
import { ConnectDatabase } from './ConnectDatabase';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
component: ConnectDatabase,
|
||||||
|
argTypes: {
|
||||||
|
onEnableEnterpriseTrial: { action: 'Enable Enterprise Clicked' },
|
||||||
|
onContactSales: { action: 'Contact Sales Clicked' },
|
||||||
|
},
|
||||||
|
} as ComponentMeta<typeof ConnectDatabase>;
|
||||||
|
|
||||||
|
export const Primary: ComponentStory<typeof ConnectDatabase> = args => {
|
||||||
|
const [, updateArgs] = useArgs();
|
||||||
|
return (
|
||||||
|
<ConnectDatabase
|
||||||
|
{...args}
|
||||||
|
onEnableEnterpriseTrial={() => {
|
||||||
|
hasuraToast({
|
||||||
|
message:
|
||||||
|
'Missing EE Trial Forms here. Setting ee trial prop to active as a temporary measure.',
|
||||||
|
title: 'Sign Up Not Implemented',
|
||||||
|
toastOptions: {
|
||||||
|
duration: 3000,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
updateArgs({ ...args, eeState: 'active' });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Primary.args = {
|
||||||
|
eeState: 'inactive',
|
||||||
|
initialDb: 'snowflake',
|
||||||
|
};
|
@ -0,0 +1,23 @@
|
|||||||
|
import {
|
||||||
|
SelectDatabase,
|
||||||
|
SelectDatabaseProps,
|
||||||
|
} from '@/features/ConnectDBRedesign/components/SelectDatabase/SelectDatabase';
|
||||||
|
|
||||||
|
export const ConnectDatabase = (props: SelectDatabaseProps) => {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
<div className="py-lg border-b border-slate-300 w-full flex justify-center">
|
||||||
|
<div className="max-w-3xl w-full">
|
||||||
|
<div className="text-xl font-bold">Connect Your First Database</div>
|
||||||
|
<div className="text-muted">
|
||||||
|
Connect your first database to access your database objects in your
|
||||||
|
GraphQL API.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="max-w-3xl py-lg w-full">
|
||||||
|
<SelectDatabase {...props} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,40 @@
|
|||||||
|
import { SelectDatabase } from '@/features/ConnectDBRedesign/components/SelectDatabase';
|
||||||
|
import { hasuraToast } from '@/new-components/Toasts';
|
||||||
|
import { useArgs } from '@storybook/client-api';
|
||||||
|
import { ComponentMeta, ComponentStory } from '@storybook/react';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
component: SelectDatabase,
|
||||||
|
argTypes: {
|
||||||
|
onEnableEnterpriseTrial: { action: 'Enable Enterprise Clicked' },
|
||||||
|
onContactSales: { action: 'Contact Sales Clicked' },
|
||||||
|
},
|
||||||
|
} as ComponentMeta<typeof SelectDatabase>;
|
||||||
|
|
||||||
|
export const Primary: ComponentStory<typeof SelectDatabase> = args => {
|
||||||
|
const [, updateArgs] = useArgs();
|
||||||
|
return (
|
||||||
|
<div className="max-w-3xl">
|
||||||
|
Note: This container has a max width set. When rendering this component
|
||||||
|
keep width in mind to avoid it growing too large.
|
||||||
|
<SelectDatabase
|
||||||
|
{...args}
|
||||||
|
onEnableEnterpriseTrial={() => {
|
||||||
|
hasuraToast({
|
||||||
|
message:
|
||||||
|
'Missing EE Trial Forms here. Setting ee trial prop to active as a temporary measure.',
|
||||||
|
title: 'Sign Up Not Implemented',
|
||||||
|
toastOptions: {
|
||||||
|
duration: 3000,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
updateArgs({ ...args, eeState: 'active' });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
Primary.args = {
|
||||||
|
eeState: 'inactive',
|
||||||
|
initialDb: 'snowflake',
|
||||||
|
};
|
@ -0,0 +1,87 @@
|
|||||||
|
import { NeonBanner } from '@/features/CloudOnboarding/OnboardingWizard/components/NeonConnectBanner/NeonBanner';
|
||||||
|
import Globals from '@/Globals';
|
||||||
|
import { Button } from '@/new-components/Button';
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
EETrialActive,
|
||||||
|
EETrialExpired,
|
||||||
|
EETrialInactive,
|
||||||
|
FancyRadioCards,
|
||||||
|
} from './components';
|
||||||
|
import { databases } from './databases';
|
||||||
|
import DbConnectSVG from './graphics/database-connect.svg';
|
||||||
|
import { DatabaseKind, EEState } from '../../types';
|
||||||
|
|
||||||
|
const enterpriseDbs: DatabaseKind[] = ['snowflake', 'athena'];
|
||||||
|
|
||||||
|
export interface SelectDatabaseProps {
|
||||||
|
eeState: EEState;
|
||||||
|
initialDb?: DatabaseKind;
|
||||||
|
onEnableEnterpriseTrial: () => void;
|
||||||
|
onContactSales: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SelectDatabase = ({
|
||||||
|
eeState,
|
||||||
|
initialDb = 'postgres',
|
||||||
|
onEnableEnterpriseTrial,
|
||||||
|
onContactSales,
|
||||||
|
}: SelectDatabaseProps) => {
|
||||||
|
const [selectedDb, setSelectedDb] = React.useState<DatabaseKind>(
|
||||||
|
initialDb || 'postgres'
|
||||||
|
);
|
||||||
|
const displayNeonBanner =
|
||||||
|
Globals.consoleType === 'cloud' && !!Globals.hasuraCloudTenantId;
|
||||||
|
|
||||||
|
const showConnectDbButton =
|
||||||
|
(enterpriseDbs.includes(selectedDb) && eeState === 'active') ||
|
||||||
|
!enterpriseDbs.includes(selectedDb);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<img
|
||||||
|
src={DbConnectSVG}
|
||||||
|
className={`mb-md w-full`}
|
||||||
|
alt="Database Connection Diagram"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FancyRadioCards
|
||||||
|
items={databases}
|
||||||
|
value={selectedDb}
|
||||||
|
onChange={val => {
|
||||||
|
setSelectedDb(val);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{selectedDb === 'postgres' && displayNeonBanner && (
|
||||||
|
<div className="mt-3">
|
||||||
|
<NeonBanner
|
||||||
|
onClickConnect={() =>
|
||||||
|
window.alert('todo: implement Neon integration')
|
||||||
|
}
|
||||||
|
status={{ status: 'default' }}
|
||||||
|
buttonText="Create a Neon Database"
|
||||||
|
setStepperIndex={() => {}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{enterpriseDbs.includes(selectedDb) && eeState === 'inactive' && (
|
||||||
|
<EETrialInactive
|
||||||
|
selectedDb={selectedDb}
|
||||||
|
onEnableEnterpriseTrial={onEnableEnterpriseTrial}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{enterpriseDbs.includes(selectedDb) && eeState === 'active' && (
|
||||||
|
<EETrialActive selectedDb={selectedDb} />
|
||||||
|
)}
|
||||||
|
{enterpriseDbs.includes(selectedDb) && eeState === 'expired' && (
|
||||||
|
<EETrialExpired
|
||||||
|
selectedDb={selectedDb}
|
||||||
|
onContactSales={onContactSales}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{showConnectDbButton && (
|
||||||
|
<Button className="mt-6 self-end">Connect Existing Database</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,67 @@
|
|||||||
|
import { Button } from '@/new-components/Button';
|
||||||
|
import { InputField } from '@/new-components/Form';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import React from 'react';
|
||||||
|
import { useFormContext } from 'react-hook-form';
|
||||||
|
import { FaRegCopy } from 'react-icons/fa';
|
||||||
|
|
||||||
|
const twStyles = {
|
||||||
|
alignToTopOfInput: `top-[32px]`,
|
||||||
|
inputHeight: `h-[36px]`,
|
||||||
|
copyConfirm: {
|
||||||
|
base: `select-none transition-opacity duration-300 font-bold bg-slate-100/50 rounded backdrop-blur-sm absolute left-0 w-full flex items-center justify-center`,
|
||||||
|
invisible: `opacity-0 pointer-events-none`,
|
||||||
|
visible: `opacity-100 pointer-events-auto`,
|
||||||
|
},
|
||||||
|
copyButton: `active:opacity-50 border-none bg-transparent absolute right-0 shadow-none bg-none`,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CopyableInputField: typeof InputField = props => {
|
||||||
|
const { watch } = useFormContext();
|
||||||
|
const fieldValue = watch(props.name);
|
||||||
|
|
||||||
|
// state to control visibility of copy confirmation
|
||||||
|
const [showCopiedConfirmation, setShowCopiedConfirmation] =
|
||||||
|
React.useState(false);
|
||||||
|
|
||||||
|
const copyTimer = React.useRef<NodeJS.Timeout>();
|
||||||
|
|
||||||
|
const handleCopyButton = () => {
|
||||||
|
// clear timer if already going...
|
||||||
|
if (copyTimer.current) {
|
||||||
|
clearTimeout(copyTimer.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy text to clipboard
|
||||||
|
navigator.clipboard.writeText(fieldValue);
|
||||||
|
|
||||||
|
// show confirmation
|
||||||
|
setShowCopiedConfirmation(true);
|
||||||
|
|
||||||
|
// hide after 1.5s
|
||||||
|
copyTimer.current = setTimeout(() => {
|
||||||
|
setShowCopiedConfirmation(false);
|
||||||
|
}, 1500);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className="relative">
|
||||||
|
<InputField {...props} />
|
||||||
|
<Button
|
||||||
|
className={clsx(twStyles.copyButton, twStyles.alignToTopOfInput)}
|
||||||
|
icon={<FaRegCopy />}
|
||||||
|
onClick={handleCopyButton}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className={clsx(
|
||||||
|
twStyles.copyConfirm.base,
|
||||||
|
twStyles.alignToTopOfInput,
|
||||||
|
twStyles.inputHeight,
|
||||||
|
twStyles.copyConfirm.invisible,
|
||||||
|
showCopiedConfirmation && twStyles.copyConfirm.visible
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
Copied!
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,17 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export const DatabaseLogo: React.FC<{ title: string; image: string }> = ({
|
||||||
|
title,
|
||||||
|
image,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col mt-2 items-center">
|
||||||
|
<img
|
||||||
|
src={image}
|
||||||
|
className="h-[16px] w-[16px] mb-2"
|
||||||
|
alt={`${title} logo`}
|
||||||
|
/>
|
||||||
|
<div className="text-black text-base">{title}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,103 @@
|
|||||||
|
import {
|
||||||
|
CopyableInputField,
|
||||||
|
InformationCard,
|
||||||
|
} from '@/features/ConnectDBRedesign/components/SelectDatabase/components';
|
||||||
|
import { dbDisplayNames } from '@/features/ConnectDBRedesign/components/SelectDatabase/databases';
|
||||||
|
import { indefiniteArticle } from '@/features/ConnectDBRedesign/components/SelectDatabase/utils';
|
||||||
|
import { DatabaseKind } from '@/features/ConnectDBRedesign/types';
|
||||||
|
import { Button } from '@/new-components/Button';
|
||||||
|
import { InputField, SimpleForm } from '@/new-components/Form';
|
||||||
|
import { hasuraToast } from '@/new-components/Toasts';
|
||||||
|
import React from 'react';
|
||||||
|
import { FaExternalLinkAlt } from 'react-icons/fa';
|
||||||
|
import { GrDocker } from 'react-icons/gr';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
export const EETrialActive: React.VFC<{ selectedDb: DatabaseKind }> = ({
|
||||||
|
selectedDb,
|
||||||
|
}) => {
|
||||||
|
const dbWithArticle = `${indefiniteArticle(selectedDb)} ${
|
||||||
|
dbDisplayNames[selectedDb]
|
||||||
|
}`;
|
||||||
|
return (
|
||||||
|
<InformationCard blueLeftBorder>
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<div className="flex items-center pb-3 mb-3 border-b border-slate-300">
|
||||||
|
<div className="flex flex-col w-3/4">
|
||||||
|
<div className="font-bold">
|
||||||
|
{dbDisplayNames[selectedDb]} Connector Required
|
||||||
|
</div>
|
||||||
|
<div className="text-md text-gray-700">
|
||||||
|
{`The Hasura GraphQL Data Connector Service is required to connect to ${dbWithArticle} database.`}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex w-1/4 justify-end">
|
||||||
|
<Button
|
||||||
|
icon={<FaExternalLinkAlt />}
|
||||||
|
iconPosition="end"
|
||||||
|
onClick={() => {
|
||||||
|
alert('need link to docs here');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Deployment Methods
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="font-bold text-muted flex items-center">
|
||||||
|
<GrDocker />
|
||||||
|
<div className="ml-1">Docker Initialization</div>
|
||||||
|
</div>
|
||||||
|
<SimpleForm
|
||||||
|
schema={z.object({
|
||||||
|
docker_command: z.string(),
|
||||||
|
agent_path: z.string(),
|
||||||
|
})}
|
||||||
|
options={{
|
||||||
|
defaultValues: {
|
||||||
|
docker_command:
|
||||||
|
'docker run -p 127.0.0.1:1234:1234 hasura/graphql-data-connector',
|
||||||
|
agent_path: 'http://host.docker.internal:1234',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
onSubmit={values => {
|
||||||
|
console.log(values);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CopyableInputField
|
||||||
|
className="mt-1"
|
||||||
|
label="Run GraphQL Data Connector Service"
|
||||||
|
tooltip="This is a really great tooltip for this field"
|
||||||
|
disabled={true}
|
||||||
|
name="docker_command"
|
||||||
|
learnMoreLink="https://hasura.io/docs"
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
name="agent_path"
|
||||||
|
label="Connect to GraphQL Data Connector URI"
|
||||||
|
tooltip="This is a really great tooltip for this field"
|
||||||
|
/>
|
||||||
|
<div className="flex justify-end w-full">
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
mode="primary"
|
||||||
|
onClick={() => {
|
||||||
|
hasuraToast({
|
||||||
|
title: 'Not Implemented',
|
||||||
|
message:
|
||||||
|
'This feature will be implemented once the dc_add_agent check is merged.',
|
||||||
|
toastOptions: {
|
||||||
|
duration: 3000,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Validate And Connect Database
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</SimpleForm>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</InformationCard>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,31 @@
|
|||||||
|
import { Button } from '@/new-components/Button';
|
||||||
|
import React from 'react';
|
||||||
|
import { FiAlertTriangle } from 'react-icons/fi';
|
||||||
|
import { DatabaseKind } from '../../../types';
|
||||||
|
import { InformationCard } from './InformationCard';
|
||||||
|
|
||||||
|
export const EETrialExpired: React.VFC<{
|
||||||
|
onContactSales: () => void;
|
||||||
|
selectedDb: DatabaseKind;
|
||||||
|
}> = ({ onContactSales, selectedDb }) => {
|
||||||
|
return (
|
||||||
|
<InformationCard>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<div className="flex flex-col w-3/4">
|
||||||
|
<div className="text-[21px] flex items-center gap-2">
|
||||||
|
<FiAlertTriangle color="rgb(220 38 38)" /> Enterprise Trial Expired
|
||||||
|
</div>
|
||||||
|
<div className="text-md text-gray-700">
|
||||||
|
With an Enterprise Edition license you can add data sources such as
|
||||||
|
Snowflake, Amazon Athena, and more to your GraphQL API.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex w-1/4 justify-end">
|
||||||
|
<Button size="md" onClick={onContactSales}>
|
||||||
|
Contact Sales
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</InformationCard>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,35 @@
|
|||||||
|
import { Button } from '@/new-components/Button';
|
||||||
|
import React from 'react';
|
||||||
|
import { DatabaseKind } from '../../../types';
|
||||||
|
import { dbDisplayNames } from '../databases';
|
||||||
|
import { indefiniteArticle } from '../utils';
|
||||||
|
import { InformationCard } from './InformationCard';
|
||||||
|
|
||||||
|
export const EETrialInactive: React.VFC<{
|
||||||
|
onEnableEnterpriseTrial: () => void;
|
||||||
|
selectedDb: DatabaseKind;
|
||||||
|
}> = ({ onEnableEnterpriseTrial, selectedDb }) => {
|
||||||
|
const dbWithArticle = `${indefiniteArticle(selectedDb)} ${
|
||||||
|
dbDisplayNames[selectedDb]
|
||||||
|
}`;
|
||||||
|
return (
|
||||||
|
<InformationCard>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<div className="flex flex-col w-3/4">
|
||||||
|
<div className="text-[21px]">
|
||||||
|
{`Looking to connect to ${dbWithArticle} database?`}
|
||||||
|
</div>
|
||||||
|
<div className="text-md text-gray-700">
|
||||||
|
Deploy data connectors to add data sources such as Snowflake, Amazon
|
||||||
|
Athena, and more to your GraphQL API.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex w-1/4 justify-end">
|
||||||
|
<Button mode={'primary'} size="md" onClick={onEnableEnterpriseTrial}>
|
||||||
|
Enable Enterprise
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</InformationCard>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,59 @@
|
|||||||
|
import * as RadioGroup from '@radix-ui/react-radio-group';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import React from 'react';
|
||||||
|
import { DatabaseKind } from '../../../types';
|
||||||
|
|
||||||
|
const twRadioStyles = {
|
||||||
|
root: `grid grid-cols-4 gap-3`,
|
||||||
|
itemContainer: {
|
||||||
|
default: `flex items-center border bg-white shadow-sm rounded border-gray-300 cursor-pointer relative flex-[0_0_160px] h-[88px]`,
|
||||||
|
active: `ring-2 ring-blue-300 border-blue-400`,
|
||||||
|
disabled: ` cursor-not-allowed bg-gray-200`,
|
||||||
|
},
|
||||||
|
radioButton: `bg-white w-[20px] h-[20px] rounded-full shadow-eq shadow-blue-900 hover:bg-blue-100 flex-[2] absolute top-0 left-0 m-3`,
|
||||||
|
indicator: `flex items-center justify-center w-full h-full relative after:content[''] after:block after:w-[10px] after:h-[10px] after:rounded-[50%] after:bg-blue-600`,
|
||||||
|
label: `text-base whitespace-nowrap cursor-pointer flex-[1] h-full w-full flex justify-center items-center`,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const FancyRadioCards: React.VFC<{
|
||||||
|
value: string;
|
||||||
|
items: {
|
||||||
|
value: string;
|
||||||
|
content: React.ReactNode | string;
|
||||||
|
}[];
|
||||||
|
onChange: (value: DatabaseKind) => void;
|
||||||
|
}> = ({ value, items, onChange }) => {
|
||||||
|
return (
|
||||||
|
<RadioGroup.Root
|
||||||
|
className={twRadioStyles.root}
|
||||||
|
defaultValue={value}
|
||||||
|
aria-label="Radio cards"
|
||||||
|
onValueChange={onChange}
|
||||||
|
>
|
||||||
|
{items.map((item, i) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={clsx(
|
||||||
|
twRadioStyles.itemContainer.default,
|
||||||
|
value === item.value && twRadioStyles.itemContainer.active
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<RadioGroup.Item
|
||||||
|
className={twRadioStyles.radioButton}
|
||||||
|
value={item.value}
|
||||||
|
id={`radio-item-${item.value}`}
|
||||||
|
>
|
||||||
|
<RadioGroup.Indicator className={twRadioStyles.indicator} />
|
||||||
|
</RadioGroup.Item>
|
||||||
|
<label
|
||||||
|
className={twRadioStyles.label}
|
||||||
|
htmlFor={`radio-item-${item.value}`}
|
||||||
|
>
|
||||||
|
{item.content}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</RadioGroup.Root>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,25 @@
|
|||||||
|
import clsx from 'clsx';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const twStyles = {
|
||||||
|
container: `border border-gray-300 mt-3 shadow-md rounded bg-white p-6`,
|
||||||
|
blueBorder: `border-l-4 border-l-[#297393]`,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const InformationCard: React.FC<{
|
||||||
|
blueLeftBorder?: boolean;
|
||||||
|
className?: string;
|
||||||
|
innerContainerClassName?: string;
|
||||||
|
}> = ({ children, blueLeftBorder, className, innerContainerClassName }) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={clsx(
|
||||||
|
twStyles.container,
|
||||||
|
blueLeftBorder && twStyles.blueBorder,
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,7 @@
|
|||||||
|
export { CopyableInputField } from './CopyableInputField';
|
||||||
|
export { DatabaseLogo } from './DatabaseLogo';
|
||||||
|
export { EETrialActive } from './EETrialActive';
|
||||||
|
export { EETrialExpired } from './EETrialExpired';
|
||||||
|
export { EETrialInactive } from './EETrialInactive';
|
||||||
|
export { FancyRadioCards } from './FancyRadioCards';
|
||||||
|
export { InformationCard } from './InformationCard';
|
@ -0,0 +1,66 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { DatabaseLogo } from './components';
|
||||||
|
import postgresLogo from './graphics/db-logos/postgres.svg';
|
||||||
|
import googleLogo from './graphics/db-logos/google.svg';
|
||||||
|
import microsoftLogo from './graphics/db-logos/microsoft.svg';
|
||||||
|
import citusLogo from './graphics/db-logos/citus.svg';
|
||||||
|
import cockroachLogo from './graphics/db-logos/cockroach.svg';
|
||||||
|
import amazonLogo from './graphics/db-logos/amazon.svg';
|
||||||
|
import snowflakeLogo from './graphics/db-logos/snowflake.svg';
|
||||||
|
import { DatabaseKind } from '../../types';
|
||||||
|
|
||||||
|
export const dbDisplayNames: Record<DatabaseKind, string> = {
|
||||||
|
postgres: 'PostgresSQL',
|
||||||
|
citus: 'Citus',
|
||||||
|
cockroach: 'CockroachDB',
|
||||||
|
alloydb: 'AlloyDB',
|
||||||
|
mssql: 'MSSQL',
|
||||||
|
bigquery: 'BigQuery',
|
||||||
|
snowflake: 'Snowflake',
|
||||||
|
athena: 'Amazon Athena',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const databases: { value: DatabaseKind; content: React.ReactNode }[] = [
|
||||||
|
{
|
||||||
|
value: 'postgres',
|
||||||
|
content: (
|
||||||
|
<DatabaseLogo title={dbDisplayNames.postgres} image={postgresLogo} />
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'citus',
|
||||||
|
content: <DatabaseLogo title={dbDisplayNames.citus} image={citusLogo} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'cockroach',
|
||||||
|
content: (
|
||||||
|
<DatabaseLogo title={dbDisplayNames.cockroach} image={cockroachLogo} />
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'alloydb',
|
||||||
|
content: <DatabaseLogo title={dbDisplayNames.alloydb} image={googleLogo} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'mssql',
|
||||||
|
content: (
|
||||||
|
<DatabaseLogo title={dbDisplayNames.mssql} image={microsoftLogo} />
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'bigquery',
|
||||||
|
content: (
|
||||||
|
<DatabaseLogo title={dbDisplayNames.bigquery} image={googleLogo} />
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'snowflake',
|
||||||
|
content: (
|
||||||
|
<DatabaseLogo title={dbDisplayNames.snowflake} image={snowflakeLogo} />
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'athena',
|
||||||
|
content: <DatabaseLogo title={dbDisplayNames.athena} image={amazonLogo} />,
|
||||||
|
},
|
||||||
|
];
|
After Width: | Height: | Size: 52 KiB |
@ -0,0 +1,9 @@
|
|||||||
|
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<rect x="0.9375" width="16" height="16" fill="url(#pattern0)"/>
|
||||||
|
<defs>
|
||||||
|
<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
|
||||||
|
<use xlink:href="#image0_44_21233" transform="scale(0.0625)"/>
|
||||||
|
</pattern>
|
||||||
|
<image id="image0_44_21233" width="16" height="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABdUlEQVQ4jc2TO04jQRCGv+rxjDDaFZiAERkSsNqQG7BH4ABIiARENjEiMBIHmAzYZM0NOALcYEMEC7KEQJqAh7HxGM90FwEv29gWZPuH1fV/XV1dJQxQvvdjUZAYQNGosHZy0C9PegP6e27eWhOLsNAVV448z0Wyevq3L0D/TI+7VhAjsjyoqhfSvhlpR7JSvXsD2J2fZUQjYGyo+V01VGJv/bgs9c3ZX2L0ICgVfK/I6Gfcj9eu2TjPMvHNUgFAHWOP1znGlySYMKHxP7QGgPxBqZ9liX3QEMBa1yh0JrhMw1Zi8YqSBCUvFPPy7BzqZ1nSvnEhEHZ6ugCvsqmGaStP/W+m3a450isboN3GoYDnaylmdVdML+3AFAAz9PQT+g8A37f/HYJsAbUv+GoIW1OV6uHbh9+Wp8e93IsFuka5edHTRGE/gKhU6RjlTjU25ubVuBiel+kVoMKRgWiyUu2/TL2635xZFGW3eWFbGKKwUu27zk/aOpGGPDxYiQAAAABJRU5ErkJggg=="/>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.0 KiB |
@ -0,0 +1,9 @@
|
|||||||
|
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<rect x="0.6875" width="16" height="16" fill="url(#pattern0)"/>
|
||||||
|
<defs>
|
||||||
|
<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
|
||||||
|
<use xlink:href="#image0_44_21195" transform="scale(0.03125)"/>
|
||||||
|
</pattern>
|
||||||
|
<image id="image0_44_21195" width="32" height="32" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAE5UlEQVR42rVXa2yUVRDdbh87QkstaNMqz9m2KIVWo9TSat3t2HY02hASKkT9oZhoZov4iI9UoiBGbRSJ6A+MJoOloikhEBNMTKMI0ag8FB8oMYKoiIGgUq0EoVBzm1ny+fnttsWyyfzZvXfOmblnzr0bCo3QB0gygGQUkFwEJJcAyQwgmQYk4933oXPxAZIcICkDkluBZCWQdAPJbiD5EUh+AZKfgOQbIHkHSJ4EklogiYwE8DggaQGSLiA5ACR9QNI/hDgKJGuAZPrZAhcAyQIg+QhI/h4iaFC4rsSHA5wFJAwk7wHJCU8iR+IwkOwBkp1Ash1IvgaSQ0BychASu5xWhgJeCCTt1r5kG98HkmVA0gwk5UBSBCTnA0m+rXffzQOSTiA5koLAaSBZPhh4hQnLLd4PJM8DSU1O7cLRQ+xcNpDEgGRLChJfpNscs7NyLX4mEkuUhkIrMyq21IajHU0Xo3Icle9A5ftReREq34bKMVQej8qZvlwTbBL8BA6lAm8Eku+AZBPEE1Wh0PKMkrUN41B5Hip3ovJWVO5C5UdReQ4qV6FyGSpPQOWxfgKW043grz4C3weBX2OCeiz7qkV5pV3XuYStqLwTlb9C5WWofDkqwzAnKDfgKN72L5oKJBuhXuYXL27JxtVNjMofovJvqLwClTGFA55nInROmJFmkjZ4wN00tXoXOAW3R+KJ60vfaBiDyktRuQeVv0XlZlTO8iXMA5IbgeQlINkMJDtsOp4CkokpOrDVN4aTvFXMjcQTTdHOxiJUfh2VT6Hyp6h8ZUCy6gF9kBwLENZfQLIkYM9l5g/95hGt07rrcpI/TorEE/WTV93g1L0Rlfut8qqARLOB5IcAYCewp4FkFpAU+/aEgeRZz9q38m+5vTD6WlO1+zEzEkuUFbW1uMrXGHivU3wAeE0K8ONAclea82/2GNKXkbrW8mhHUw0qzw7lXL0wK3fOnaNQeTEq9xmBDlSO+JIAkKxPYShuasYGALvKbwKSfbZubySeuLaks7EYlV9A5ckDC1G5DpUPG7gTXiwgmbt2f07j60WetZlAUmqCTFa+G+olVvpmQwSVX0TltiS4q36dgbv4AJXHBBAoN1cMIuBEtc5uylYgWW3W7Sz81IAL1ktF5bbqMCo/gMqfo3I0ScDN+u8eAi+nOMe8FHaaLpzqn4B6uXDmgcoMVF5gnvLgmcSo/IoH3EV7GjertRfPYMBH7OExK+uKe8PRzsYsVL4blY9ahwu9BPb4CLw6iKVeCiQrnJpt9HqBpMeeYc6QlgLJTPdcs/z5Zmq9Vj3/KyEqH/MR2IXKRYOQCNu9X2ldcYAIJKN9uWeg8npUPmkT9jgqh/0ETvsIuIUP/2fhMD6uxah8Hyrv8+Rd67oRtLjHR6DfWnUPKucOA9QpfCIqCypvs6qT+brdVZ1q4ycBBFwcR+VN9gaYYuMa9uzLsvOdispzUXmV2XefL8+7qFySjnlbwCZvnEDl/ai82dropkbtznCVHvRVmwx3mW0443ZpCEyxW69/BONPVH4OlS8Y6vm5Nv8xAsBO0J/ZkeQMR7XZqPyQMT9bYKf4JSnFNkQSN6Py9hRnGhTOXD5G5UdQuRSVM/73/z6b4fnOES35XhPaQatyh11ebfYMLzgn/3xtrgvcQxSVp1tEUdk9z7NHCucflO7Q/CFSv7QAAAAASUVORK5CYII="/>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
@ -0,0 +1,9 @@
|
|||||||
|
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<rect x="0.3125" width="16" height="16" fill="url(#pattern0)"/>
|
||||||
|
<defs>
|
||||||
|
<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
|
||||||
|
<use xlink:href="#image0_44_21201" transform="scale(0.03125)"/>
|
||||||
|
</pattern>
|
||||||
|
<image id="image0_44_21201" width="32" height="32" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAAXNSR0IArs4c6QAAAKhQTFRFR3BMaDL/aTP/aDP/aTP/ajP/aTL/aDD/cDD/aTP/ajP/aDT/aTL/ajL/aTP/aDL/aDL/aDP/fU3/aDH/ajT/vaX/s5b/aTP/////2cz/9vL/xrL/7OX/j2b/s5n/ckD/mHP/vaX/tZn/qov/ooD/0L//jmb/q43/4tn/x7P/l3L/hVn/fEz/fE3/7Ob/e0z/vKX/s5j/0MD/vab/oH7/hln/4tj/qoz/OmmteQAAADh0Uk5TAGDfoM+f3yAQ78+A739fgJCQ76DP+vr////////////////////////////////////////////R1fvCAAABX0lEQVQ4y31T53rCMAx0ICEDKKND8iJh7+7x/m9Wm2EpoV/1I/l0Ovt0li1EiCxKihwgL5K7TNxGOnLFEEnaKGd9aES/vvwBbqLFNklbAP8xfH1srd1fSy+2qsaM4ddLtdkopS3A6kOhekbpwOLshvr72hotUVblFRicBLjuFHHKcy/SZvkEZ2ucMGDoToClC5z5jyUkz0RE2cHok4wqCYu4wgQr/9vhGztzEVNi8NP/VqgIiwWNyBW8edgq1kUuiDxX1jtwQmZOKCNMJTiPzim8a0YgCS29R+9UL5lEzHdwMzFQI8Tinnowl21AvjKbdFAWywtBVQG8E1loolTzM2GHdJRu4MNaE54gNVPg4z6qH09Y4LE2bjEI6VrttTyYWQC65ytPTpdGGvMd0s710nZCn0tEGTrs0LUODHh6hNt6jRGiqL++brPebT7glF/e3ij9431nUTvuuWKcRGz1L1LVS43OWNCRAAAAAElFTkSuQmCC"/>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 10 KiB |
@ -0,0 +1,9 @@
|
|||||||
|
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<rect x="0.0625" width="16" height="16" fill="url(#pattern0)"/>
|
||||||
|
<defs>
|
||||||
|
<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
|
||||||
|
<use xlink:href="#image0_44_21215" transform="scale(0.0078125)"/>
|
||||||
|
</pattern>
|
||||||
|
<image id="image0_44_21215" width="128" height="128" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAABcUlEQVR4nO3YMQ1CQRBAwTsEkGABRQjAC2YQQAtisECCgcPAr/nFmym32mxetfN7Oa8Rc3y859b89hq5Wxz2XoB9CSBOAHECiBNAnADiBBAngDgBxAkgTgBxAogTQJwA4gQQJ4A4AcQJIE4AcQKIE0CcAOIEECeAOAHECSBOAHECiBNAnADiBBAngDgBxAkgTgBxAogTQJwA4gQQJ4A4AcQJIE4AcQKIE0CcAOIEECeAOAHECSBOAHECiBNAnADiBBAngDgBxAkgTgBxAgAAAEiZ4/5Zey/xd9fT3Bqv58jdwh8gTgBxAogTQJwA4gQQJ4A4AcQJIE4AcQKIE0CcAOIEECeAOAHECSBOAHECiBNAnADiBBAngDgBxAkgTgBxAogTQJwA4gQQJ4A4AcQJIE4AcQKIE0CcAOIEECeAOAHECSBOAHECiBNAnADiBBAngDgBxAkgTgBxAogTQJwA4gQQJ4A4AcQJIE4AcQKIE0DcD7bzDOLQOL8WAAAAAElFTkSuQmCC"/>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.0 KiB |
@ -0,0 +1,4 @@
|
|||||||
|
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect width="16" height="16" fill="white"/>
|
||||||
|
<path d="M15 2.28572V3.71428C15 4.97322 11.8646 6 8 6C4.13541 6 1 4.97322 1 3.71428V2.28572C1 1.02678 4.13541 0 8 0C11.8646 0 15 1.02678 15 2.28572ZM15 5.5V8.71428C15 9.97322 11.8646 11 8 11C4.13541 11 1 9.97322 1 8.71428V5.5C2.50391 6.53572 5.2565 7.01788 8 7.01788C10.7435 7.01788 13.4961 6.53572 15 5.5ZM15 10.5V13.7143C15 14.9732 11.8646 16 8 16C4.13541 16 1 14.9732 1 13.7143V10.5C2.50391 11.5357 5.2565 12.0179 8 12.0179C10.7435 12.0179 13.4961 11.5357 15 10.5Z" fill="#64748B"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 616 B |
After Width: | Height: | Size: 13 KiB |
@ -0,0 +1,9 @@
|
|||||||
|
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<rect x="0.3125" width="16" height="16" fill="url(#pattern0)"/>
|
||||||
|
<defs>
|
||||||
|
<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
|
||||||
|
<use xlink:href="#image0_44_21227" transform="scale(0.03125)"/>
|
||||||
|
</pattern>
|
||||||
|
<image id="image0_44_21227" width="32" height="32" xlink:href="data:image/png;base64,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"/>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.0 KiB |
@ -0,0 +1 @@
|
|||||||
|
export { SelectDatabase } from './SelectDatabase';
|
@ -0,0 +1 @@
|
|||||||
|
export const twLayoutWidth = `w-[672px]`;
|
@ -0,0 +1,5 @@
|
|||||||
|
// returns the correct indefinite article based on the first character of the input string
|
||||||
|
export const indefiniteArticle = (word: string): string => {
|
||||||
|
const vowels = ['a', 'e', 'i', 'o', 'u'];
|
||||||
|
return vowels.includes(word.charAt(0)) ? 'an' : 'a';
|
||||||
|
};
|
@ -0,0 +1,2 @@
|
|||||||
|
export { SelectDatabase } from './components/SelectDatabase';
|
||||||
|
export type { EEState } from './components/SelectDatabase';
|
11
frontend/libs/console/legacy-ce/src/lib/features/ConnectDBRedesign/types.d.ts
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
export type DatabaseKind =
|
||||||
|
| 'postgres'
|
||||||
|
| 'mssql'
|
||||||
|
| 'bigquery'
|
||||||
|
| 'citus'
|
||||||
|
| 'alloydb'
|
||||||
|
| 'snowflake'
|
||||||
|
| 'athena'
|
||||||
|
| 'cockroach';
|
||||||
|
|
||||||
|
export type EEState = 'active' | 'inactive' | 'expired';
|
@ -1,3 +1,4 @@
|
|||||||
|
import { Badge } from '@/new-components/Badge';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FaDatabase } from 'react-icons/fa';
|
import { FaDatabase } from 'react-icons/fa';
|
||||||
import { GDCTable } from '..';
|
import { GDCTable } from '..';
|
||||||
@ -28,9 +29,9 @@ export const getTablesListAsTree = async ({
|
|||||||
title: (
|
title: (
|
||||||
<div className="inline-block">
|
<div className="inline-block">
|
||||||
<span className="font-bold text-lg">{source.name}</span>
|
<span className="font-bold text-lg">{source.name}</span>
|
||||||
<span className="items-center ml-sm px-sm py-0.5 rounded-full text-sm tracking-wide font-semibold bg-indigo-100 text-indigo-800">
|
<Badge color="indigo" className="ml-sm">
|
||||||
Beta
|
Beta
|
||||||
</span>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
key: JSON.stringify({ database: source.name }),
|
key: JSON.stringify({ database: source.name }),
|
||||||
|
111
frontend/package-lock.json
generated
@ -20,6 +20,7 @@
|
|||||||
"@radix-ui/react-collapsible": "^1.0.0",
|
"@radix-ui/react-collapsible": "^1.0.0",
|
||||||
"@radix-ui/react-dialog": "^1.0.0",
|
"@radix-ui/react-dialog": "^1.0.0",
|
||||||
"@radix-ui/react-dropdown-menu": "^1.0.0",
|
"@radix-ui/react-dropdown-menu": "^1.0.0",
|
||||||
|
"@radix-ui/react-radio-group": "^1.1.1",
|
||||||
"@radix-ui/react-switch": "^1.0.0",
|
"@radix-ui/react-switch": "^1.0.0",
|
||||||
"@radix-ui/react-tabs": "^1.0.0",
|
"@radix-ui/react-tabs": "^1.0.0",
|
||||||
"@radix-ui/react-tooltip": "^1.0.0",
|
"@radix-ui/react-tooltip": "^1.0.0",
|
||||||
@ -12300,6 +12301,65 @@
|
|||||||
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-radio-group": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-fmg1CuDKt3GAkL3YnHekmdOicyrXlbp/s/D0MrHa+YB2Un+umpJGheiRowlQtxSpb1eeehKNTINgNESi8WK5rA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.13.10",
|
||||||
|
"@radix-ui/primitive": "1.0.0",
|
||||||
|
"@radix-ui/react-compose-refs": "1.0.0",
|
||||||
|
"@radix-ui/react-context": "1.0.0",
|
||||||
|
"@radix-ui/react-direction": "1.0.0",
|
||||||
|
"@radix-ui/react-presence": "1.0.0",
|
||||||
|
"@radix-ui/react-primitive": "1.0.1",
|
||||||
|
"@radix-ui/react-roving-focus": "1.0.2",
|
||||||
|
"@radix-ui/react-use-controllable-state": "1.0.0",
|
||||||
|
"@radix-ui/react-use-previous": "1.0.0",
|
||||||
|
"@radix-ui/react-use-size": "1.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-collection": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-uuiFbs+YCKjn3X1DTSx9G7BHApu4GHbi3kgiwsnFUbOKCrwejAJv4eE4Vc8C0Oaxt9T0aV4ox0WCOdx+39Xo+g==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.13.10",
|
||||||
|
"@radix-ui/react-compose-refs": "1.0.0",
|
||||||
|
"@radix-ui/react-context": "1.0.0",
|
||||||
|
"@radix-ui/react-primitive": "1.0.1",
|
||||||
|
"@radix-ui/react-slot": "1.0.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-roving-focus": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-HLK+CqD/8pN6GfJm3U+cqpqhSKYAWiOJDe+A+8MfxBnOue39QEeMa43csUn2CXCHQT0/mewh1LrrG4tfkM9DMA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.13.10",
|
||||||
|
"@radix-ui/primitive": "1.0.0",
|
||||||
|
"@radix-ui/react-collection": "1.0.1",
|
||||||
|
"@radix-ui/react-compose-refs": "1.0.0",
|
||||||
|
"@radix-ui/react-context": "1.0.0",
|
||||||
|
"@radix-ui/react-direction": "1.0.0",
|
||||||
|
"@radix-ui/react-id": "1.0.0",
|
||||||
|
"@radix-ui/react-primitive": "1.0.1",
|
||||||
|
"@radix-ui/react-use-callback-ref": "1.0.0",
|
||||||
|
"@radix-ui/react-use-controllable-state": "1.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-roving-focus": {
|
"node_modules/@radix-ui/react-roving-focus": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.0.tgz",
|
||||||
@ -73121,6 +73181,55 @@
|
|||||||
"@radix-ui/react-slot": "1.0.1"
|
"@radix-ui/react-slot": "1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@radix-ui/react-radio-group": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-fmg1CuDKt3GAkL3YnHekmdOicyrXlbp/s/D0MrHa+YB2Un+umpJGheiRowlQtxSpb1eeehKNTINgNESi8WK5rA==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.13.10",
|
||||||
|
"@radix-ui/primitive": "1.0.0",
|
||||||
|
"@radix-ui/react-compose-refs": "1.0.0",
|
||||||
|
"@radix-ui/react-context": "1.0.0",
|
||||||
|
"@radix-ui/react-direction": "1.0.0",
|
||||||
|
"@radix-ui/react-presence": "1.0.0",
|
||||||
|
"@radix-ui/react-primitive": "1.0.1",
|
||||||
|
"@radix-ui/react-roving-focus": "1.0.2",
|
||||||
|
"@radix-ui/react-use-controllable-state": "1.0.0",
|
||||||
|
"@radix-ui/react-use-previous": "1.0.0",
|
||||||
|
"@radix-ui/react-use-size": "1.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-collection": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-uuiFbs+YCKjn3X1DTSx9G7BHApu4GHbi3kgiwsnFUbOKCrwejAJv4eE4Vc8C0Oaxt9T0aV4ox0WCOdx+39Xo+g==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.13.10",
|
||||||
|
"@radix-ui/react-compose-refs": "1.0.0",
|
||||||
|
"@radix-ui/react-context": "1.0.0",
|
||||||
|
"@radix-ui/react-primitive": "1.0.1",
|
||||||
|
"@radix-ui/react-slot": "1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@radix-ui/react-roving-focus": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-HLK+CqD/8pN6GfJm3U+cqpqhSKYAWiOJDe+A+8MfxBnOue39QEeMa43csUn2CXCHQT0/mewh1LrrG4tfkM9DMA==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.13.10",
|
||||||
|
"@radix-ui/primitive": "1.0.0",
|
||||||
|
"@radix-ui/react-collection": "1.0.1",
|
||||||
|
"@radix-ui/react-compose-refs": "1.0.0",
|
||||||
|
"@radix-ui/react-context": "1.0.0",
|
||||||
|
"@radix-ui/react-direction": "1.0.0",
|
||||||
|
"@radix-ui/react-id": "1.0.0",
|
||||||
|
"@radix-ui/react-primitive": "1.0.1",
|
||||||
|
"@radix-ui/react-use-callback-ref": "1.0.0",
|
||||||
|
"@radix-ui/react-use-controllable-state": "1.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@radix-ui/react-roving-focus": {
|
"@radix-ui/react-roving-focus": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.0.tgz",
|
||||||
@ -95198,7 +95307,7 @@
|
|||||||
"@emotion/core": "^10.0.22",
|
"@emotion/core": "^10.0.22",
|
||||||
"@mdx-js/react": "^1.5.2",
|
"@mdx-js/react": "^1.5.2",
|
||||||
"codemirror": "5.51.0",
|
"codemirror": "5.51.0",
|
||||||
"codemirror-graphql": "0.12.2",
|
"codemirror-graphql": "^0.12.0-alpha.0",
|
||||||
"copy-to-clipboard": "^3.2.0",
|
"copy-to-clipboard": "^3.2.0",
|
||||||
"entities": "^2.0.0",
|
"entities": "^2.0.0",
|
||||||
"markdown-it": "^10.0.0",
|
"markdown-it": "^10.0.0",
|
||||||
|
@ -55,6 +55,7 @@
|
|||||||
"@radix-ui/react-collapsible": "^1.0.0",
|
"@radix-ui/react-collapsible": "^1.0.0",
|
||||||
"@radix-ui/react-dialog": "^1.0.0",
|
"@radix-ui/react-dialog": "^1.0.0",
|
||||||
"@radix-ui/react-dropdown-menu": "^1.0.0",
|
"@radix-ui/react-dropdown-menu": "^1.0.0",
|
||||||
|
"@radix-ui/react-radio-group": "^1.1.1",
|
||||||
"@radix-ui/react-switch": "^1.0.0",
|
"@radix-ui/react-switch": "^1.0.0",
|
||||||
"@radix-ui/react-tabs": "^1.0.0",
|
"@radix-ui/react-tabs": "^1.0.0",
|
||||||
"@radix-ui/react-tooltip": "^1.0.0",
|
"@radix-ui/react-tooltip": "^1.0.0",
|
||||||
|
@ -11,6 +11,9 @@ module.exports = {
|
|||||||
mono: ['"Overpass Mono"', 'ui-monospace', 'monospace'],
|
mono: ['"Overpass Mono"', 'ui-monospace', 'monospace'],
|
||||||
},
|
},
|
||||||
extend: {
|
extend: {
|
||||||
|
boxShadow: {
|
||||||
|
eq: 'rgb(0 0 0) 0px 0px 2px',
|
||||||
|
},
|
||||||
colors: {
|
colors: {
|
||||||
current: 'currentColor',
|
current: 'currentColor',
|
||||||
yellow: colors.amber,
|
yellow: colors.amber,
|
||||||
|