diff --git a/apps/docs/components/JwtGenerator/JwtGenerator.tsx b/apps/docs/components/JwtGenerator/JwtGenerator.tsx deleted file mode 100644 index 314c1663f54..00000000000 --- a/apps/docs/components/JwtGenerator/JwtGenerator.tsx +++ /dev/null @@ -1,142 +0,0 @@ -import { KJUR } from 'jsrsasign' -import { ChangeEvent, useState } from 'react' -import { Button, Input, Select } from 'ui' -import { CodeBlock } from 'ui-patterns/CodeBlock' - -const JWT_HEADER = { alg: 'HS256', typ: 'JWT' } -const now = new Date() -const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()) -const fiveYears = new Date(now.getFullYear() + 5, now.getMonth(), now.getDate()) - -const anonToken = { - role: 'anon', - iss: 'supabase', - iat: Math.floor(today.valueOf() / 1000), - exp: Math.floor(fiveYears.valueOf() / 1000), -} -const serviceToken = { - role: 'service_role', - iss: 'supabase', - iat: Math.floor(today.valueOf() / 1000), - exp: Math.floor(fiveYears.valueOf() / 1000), -} - -const generateRandomString = (length: number) => { - const CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' - let result = '' - - /** - * The number of possible Uint8 integers is 256. Since the length of `CHARS` - * doesn't fit exactly into 256, simply taking the modulus would create an - * uneven distribution that favors the earlier characters. To make a truly - * uniform distribution, we have to discard everything above the last full - * cycle, and pick again. - * - * The minus 1 is to account for 0-indexing. - */ - const MAX = Math.floor(256 / CHARS.length) * CHARS.length - 1 - - const randomUInt8Array = new Uint8Array(1) - - for (let i = 0; i < length; i++) { - let randomNumber: number - do { - crypto.getRandomValues(randomUInt8Array) - randomNumber = randomUInt8Array[0] - /** - * Keep picking until we get a number in the valid range. - */ - } while (randomNumber > MAX) - - result += CHARS[randomNumber % CHARS.length] - } - - return result -} - -export default function JwtGenerator() { - const secret = generateRandomString(40) - - const [jwtSecret, setJwtSecret] = useState(secret) - const [token, setToken] = useState(anonToken) - const [signedToken, setSignedToken] = useState('') - const [err, setErr] = useState('') - - const handleKeySelection = (e: ChangeEvent) => { - const val = e.target.value - if (val == 'service') setToken(serviceToken) - else setToken(anonToken) - } - - const handleClaimsChange = (e: ChangeEvent) => { - try { - const newTok = JSON.parse(e.target.value) - setToken(newTok) - setErr('') - } catch (err) { - const errMessage = - !!err && typeof err === 'object' && 'message' in err && typeof err.message === 'string' - ? err.message - : '' - setErr('Not a valid JSON body' + (errMessage ? `: ${errMessage}` : '')) - } - } - - const generate = () => { - const signedJWT = KJUR.jws.JWS.sign(null, JWT_HEADER, token, jwtSecret) - setSignedToken(signedJWT) - } - - return ( -
-
- - setJwtSecret(e.target.value)} - /> -
-
- - -
- -
- - - {err && ( - Input must be valid JSON. {err} - )} -
- - - - {signedToken && ( -
-

Generated Token:

- - {signedToken} - -
- )} -
- ) -} diff --git a/apps/docs/components/JwtGenerator/index.tsx b/apps/docs/components/JwtGenerator/index.tsx index 92729296195..27a49cc41cb 100644 --- a/apps/docs/components/JwtGenerator/index.tsx +++ b/apps/docs/components/JwtGenerator/index.tsx @@ -3,17 +3,8 @@ import dynamic from 'next/dynamic' import { Suspense } from 'react' -const DynamicJwtGenerator = dynamic(() => import('./JwtGenerator'), { ssr: false }) const DynamicJwtGeneratorSimple = dynamic(() => import('./JwtGeneratorSimple'), { ssr: false }) -const JwtGenerator = () => { - return ( - Loading...}> - - - ) -} - const JwtGeneratorSimple = () => { return ( Loading...}> @@ -22,4 +13,4 @@ const JwtGeneratorSimple = () => { ) } -export { JwtGenerator, JwtGeneratorSimple } +export { JwtGeneratorSimple } diff --git a/apps/docs/components/RealtimeLimitsEstimator/RealtimeLimitsEstimator.tsx b/apps/docs/components/RealtimeLimitsEstimator/RealtimeLimitsEstimator.tsx index de07c73bdf0..7da99cf94c6 100644 --- a/apps/docs/components/RealtimeLimitsEstimator/RealtimeLimitsEstimator.tsx +++ b/apps/docs/components/RealtimeLimitsEstimator/RealtimeLimitsEstimator.tsx @@ -1,7 +1,16 @@ +import throughputTable from '~/data/realtime/throughput.json' import { ChevronDown } from 'lucide-react' import { useState } from 'react' -import { Button, Collapsible, Select } from 'ui' -import throughputTable from '~/data/realtime/throughput.json' +import { + Button, + Collapsible, + Label_Shadcn_, + Select_Shadcn_, + SelectContent_Shadcn_, + SelectItem_Shadcn_, + SelectTrigger_Shadcn_, + SelectValue_Shadcn_, +} from 'ui' export default function RealtimeLimitsEstimater({}) { const findTableValue = ({ computeAddOn, filters, rls, concurrency }) => { @@ -23,29 +32,28 @@ export default function RealtimeLimitsEstimater({}) { const [expandPreview, setExpandPreview] = useState(false) - const handleComputeAddOnSelection = (e) => { - const val = e.target.value + const handleComputeAddOnSelection = (val) => { setComputeAddOn(val) setConcurrency(500) setLimits(findTableValue({ computeAddOn: val, filters, rls, concurrency: 500 })) } - const handleFiltersSelection = (e) => { - const val = e.target.value.toLowerCase() === 'true' + const handleFiltersSelection = (value) => { + const val = value.toLowerCase() === 'true' setFilters(val) setConcurrency(500) setLimits(findTableValue({ computeAddOn, filters: val, rls, concurrency: 500 })) } - const handleRLSSelection = (e) => { - const val = e.target.value.toLowerCase() === 'true' + const handleRLSSelection = (value) => { + const val = value.toLowerCase() === 'true' setRLS(val) setConcurrency(500) setLimits(findTableValue({ computeAddOn, filters, rls: val, concurrency: 500 })) } - const handleConcurrencySelection = (e) => { - const val = parseInt(e.target.value) + const handleConcurrencySelection = (value) => { + const val = parseInt(value) setConcurrency(val) setLimits(findTableValue({ computeAddOn, filters, rls, concurrency: val })) } @@ -55,51 +63,64 @@ export default function RealtimeLimitsEstimater({}) {

Set your expected parameters

- - + Compute: + + + + + + Micro + Small to medium + Large to 16XL + +
-
- - + + + + + No + Yes + +
-
- - + RLS: + + + + + + No + Yes + +
-
- - + Connected clients: + + + + + + {throughputTable + .filter( + (l) => l.computeAddOn === computeAddOn && l.filters === filters && l.rls === rls + ) + .map((l) => ( + + {Intl.NumberFormat().format(l.concurrency)} + + ))} + +
diff --git a/apps/docs/features/docs/MdxBase.shared.tsx b/apps/docs/features/docs/MdxBase.shared.tsx index 3a1484efc4f..73896e331dd 100644 --- a/apps/docs/features/docs/MdxBase.shared.tsx +++ b/apps/docs/features/docs/MdxBase.shared.tsx @@ -1,11 +1,3 @@ -import { ArrowDown, Check, X } from 'lucide-react' -import Link from 'next/link' -import { Badge, Button } from 'ui' -import { Admonition, type AdmonitionProps } from 'ui-patterns/admonition' -import { GlassPanel } from 'ui-patterns/GlassPanel' -import { IconPanel } from 'ui-patterns/IconPanel' -import SqlToRest from 'ui-patterns/SqlToRest' -import { Heading } from 'ui/src/components/CustomHTMLElements' import { AiPromptsIndex } from '~/app/guides/getting-started/ai-prompts/[slug]/AiPromptsIndex' import { AiSkillsIndex } from '~/app/guides/getting-started/ai-skills/AiSkillsIndex' import { AppleSecretGenerator } from '~/components/AppleSecretGenerator' @@ -13,15 +5,15 @@ import AuthProviders from '~/components/AuthProviders' import { AuthSmsProviderConfig } from '~/components/AuthSmsProviderConfig' import { CostWarning } from '~/components/AuthSmsProviderConfig/AuthSmsProviderConfig.Warnings' import ButtonCard from '~/components/ButtonCard' +import { ComputeDiskLimitsTable } from '~/components/ComputeDiskLimitsTable' import { Extensions } from '~/components/Extensions' import Image, { type ImageProps } from '~/components/Image' -import { JwtGenerator, JwtGeneratorSimple } from '~/components/JwtGenerator' +import { JwtGeneratorSimple } from '~/components/JwtGenerator' import { MetricsStackCards } from '~/components/MetricsStackCards' import { NavData } from '~/components/NavData' import { Price } from '~/components/Price' import { ProjectConfigVariables } from '~/components/ProjectConfigVariables' import { RealtimeLimitsEstimator } from '~/components/RealtimeLimitsEstimator' -import { ComputeDiskLimitsTable } from '~/components/ComputeDiskLimitsTable' import { RegionsList, SmartRegionsList } from '~/components/RegionsList' import { SharedData } from '~/components/SharedData' import StepHikeCompact from '~/components/StepHikeCompact' @@ -32,6 +24,15 @@ import { CodeBlock } from '~/features/ui/CodeBlock/CodeBlock' import InfoTooltip from '~/features/ui/InfoTooltip' import { ShowUntil } from '~/features/ui/ShowUntil' import { TabPanel, Tabs } from '~/features/ui/Tabs' +import { ArrowDown, Check, X } from 'lucide-react' +import Link from 'next/link' +import { Badge, Button } from 'ui' +import { Admonition, type AdmonitionProps } from 'ui-patterns/admonition' +import { GlassPanel } from 'ui-patterns/GlassPanel' +import { IconPanel } from 'ui-patterns/IconPanel' +import SqlToRest from 'ui-patterns/SqlToRest' +import { Heading } from 'ui/src/components/CustomHTMLElements' + import { ErrorCodes } from '../ui/ErrorCodes' import { McpConfigPanel } from '../ui/McpConfigPanel' @@ -64,7 +65,6 @@ const components = { IconPanel, IconX: X, Image: (props: ImageProps) => , - JwtGenerator, JwtGeneratorSimple, Link, McpConfigPanel, diff --git a/apps/studio/components/grid/components/editor/BooleanEditor.tsx b/apps/studio/components/grid/components/editor/BooleanEditor.tsx index 8d8387ba855..72d88e5b3b2 100644 --- a/apps/studio/components/grid/components/editor/BooleanEditor.tsx +++ b/apps/studio/components/grid/components/editor/BooleanEditor.tsx @@ -1,5 +1,12 @@ import type { RenderEditCellProps } from 'react-data-grid' -import { Select } from 'ui' +import { + Select_Shadcn_, + SelectContent_Shadcn_, + SelectGroup_Shadcn_, + SelectItem_Shadcn_, + SelectTrigger_Shadcn_, + SelectValue_Shadcn_, +} from 'ui' interface Props extends RenderEditCellProps { isNullable?: boolean @@ -15,8 +22,7 @@ export const BooleanEditor = ({ const value = row[column.key as keyof TRow] as unknown as string const onBlur = () => onClose(false) - const onChange = (event: any) => { - const value = event.target.value + const onChange = (value: string) => { if (value === 'null') { onRowChange({ ...row, [column.key]: null }, true) } else { @@ -25,19 +31,21 @@ export const BooleanEditor = ({ } return ( - + + + + + + TRUE + FALSE + {isNullable ? NULL : null} + + + ) } diff --git a/apps/studio/components/grid/components/editor/SelectEditor.tsx b/apps/studio/components/grid/components/editor/SelectEditor.tsx index f217efa7383..6fcd2b6db7c 100644 --- a/apps/studio/components/grid/components/editor/SelectEditor.tsx +++ b/apps/studio/components/grid/components/editor/SelectEditor.tsx @@ -1,12 +1,19 @@ import type { RenderEditCellProps } from 'react-data-grid' -import { Select } from 'ui' +import { + Select_Shadcn_, + SelectContent_Shadcn_, + SelectGroup_Shadcn_, + SelectItem_Shadcn_, + SelectTrigger_Shadcn_, + SelectValue_Shadcn_, +} from 'ui' interface SelectEditorProps extends RenderEditCellProps< TRow, TSummaryRow > { isNullable?: boolean - options: { label: string; _value: string }[] + options: { label: string; value: string }[] } export function SelectEditor({ @@ -19,11 +26,11 @@ export function SelectEditor({ }: SelectEditorProps) { const value = row[column.key as keyof TRow] as unknown as string - function onChange(event: any) { - if (!event.target.value || event.target.value == '') { + function onChange(value: string) { + if (!value || value == '') { onRowChange({ ...row, [column.key]: null }, true) } else { - onRowChange({ ...row, [column.key]: event.target.value }, true) + onRowChange({ ...row, [column.key]: value }, true) } } @@ -32,24 +39,20 @@ export function SelectEditor({ } return ( - + + + + + + + {isNullable ? NULL : null} + {options.map(({ label, value }) => ( + + {label} + + ))} + + + ) } diff --git a/apps/studio/components/interfaces/Reports/ReportFilterBar.tsx b/apps/studio/components/interfaces/Reports/ReportFilterBar.tsx index 2b151e9af0d..8036f39944f 100644 --- a/apps/studio/components/interfaces/Reports/ReportFilterBar.tsx +++ b/apps/studio/components/interfaces/Reports/ReportFilterBar.tsx @@ -13,8 +13,15 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, Input, - Select, + Input_Shadcn_, + Select_Shadcn_, + SelectContent_Shadcn_, + SelectGroup_Shadcn_, + SelectItem_Shadcn_, + SelectTrigger_Shadcn_, + SelectValue_Shadcn_, } from 'ui' +import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' import { DatePickerValue, LogsDatePicker } from '../Settings/Logs/Logs.DatePickers' import { REPORTS_DATEPICKER_HELPERS } from './Reports.constants' @@ -291,52 +298,82 @@ const ReportFilterBar = ({ 0 ? 'end' : 'start'} className="p-0 w-60">
- - - + + setAddFilterValues((prev) => ({ + ...prev, + compare: value as ReportFilterItem['compare'], + })) + } + > + + + + + + {['is', 'matches'].map((value) => ( + + {value} + + ))} + + + + + { - setAddFilterValues((prev) => ({ ...prev, value: e.target.value })) - }} - /> + size="tiny" + > + { + setAddFilterValues((prev) => ({ ...prev, value: e.target.value })) + }} + /> +
diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnDefaultValue.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnDefaultValue.tsx index 6cd2ffecc4d..1212ade34ae 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnDefaultValue.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnDefaultValue.tsx @@ -1,5 +1,12 @@ import { noop } from 'lodash' -import { Select } from 'ui' +import { + Select_Shadcn_, + SelectContent_Shadcn_, + SelectGroup_Shadcn_, + SelectItem_Shadcn_, + SelectTrigger_Shadcn_, + SelectValue_Shadcn_, +} from 'ui' import { POSTGRES_DATA_TYPES } from '../SidePanelEditor.constants' import type { ColumnField } from '../SidePanelEditor.types' @@ -36,21 +43,28 @@ const ColumnDefaultValue = ({ if (enumType !== undefined) { return ( - + <> + + onUpdateField({ defaultValue: value })} + > + + + + + + NULL + {enumValues.map((value) => ( + + {value} + + ))} + + + + ) } } diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx index aeecd1677c9..c1c0289d9be 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx @@ -8,7 +8,6 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, Input, - Select, Select_Shadcn_, SelectContent_Shadcn_, SelectGroup_Shadcn_, @@ -76,24 +75,34 @@ export const InputField = ({ ) } else { return ( - + onUpdateField({ [field.name]: value })} + disabled={!isEditable} + > + + + + + + --- + {field.enums.map((value) => ( + + {value} + + ))} + + + + ) } } diff --git a/apps/www/components/Pricing/PricingComparisonTable.tsx b/apps/www/components/Pricing/PricingComparisonTable.tsx index 7927185388e..62dfeaeae3f 100644 --- a/apps/www/components/Pricing/PricingComparisonTable.tsx +++ b/apps/www/components/Pricing/PricingComparisonTable.tsx @@ -1,15 +1,24 @@ 'use client' -import Link from 'next/link' -import { useState } from 'react' - -import { plans } from 'shared-data/plans' -import { pricing } from 'shared-data/pricing' -import { Button, Select, cn } from 'ui' import { PricingTableRowDesktop, PricingTableRowMobile } from '~/components/Pricing/PricingTableRow' import Solutions from '~/data/MainProducts' import { Organization } from '~/data/organizations' import { useSendTelemetryEvent } from '~/lib/telemetry' +import Link from 'next/link' +import { useState } from 'react' +import { plans } from 'shared-data/plans' +import { pricing } from 'shared-data/pricing' +import { + Button, + cn, + Select_Shadcn_, + SelectContent_Shadcn_, + SelectGroup_Shadcn_, + SelectItem_Shadcn_, + SelectTrigger_Shadcn_, + SelectValue_Shadcn_, +} from 'ui' + import UpgradePlan from './UpgradePlan' const MobileHeader = ({ @@ -117,20 +126,24 @@ const PricingComparisonTable = ({ {/* Free - Mobile */}
- - + + + + + + Free + Pro + Team + Enterprise + + +
{activeMobilePlan === 'Free' && ( diff --git a/e2e/studio/features/table-editor.spec.ts b/e2e/studio/features/table-editor.spec.ts index 71c7af36492..e85d9f46ac4 100644 --- a/e2e/studio/features/table-editor.spec.ts +++ b/e2e/studio/features/table-editor.spec.ts @@ -244,7 +244,8 @@ testRunner('table editor', () => { // insert row with enum value await page.getByTestId('table-editor-insert-new-row').click() await page.getByText('Insert a new row into').click() - await page.getByRole('combobox').selectOption('value1') + await page.getByRole('combobox').click() + await page.getByRole('option', { name: 'value1' }).click() await page.getByTestId('action-bar-save-row').click() await expect(page.getByTestId('side-panel-row-editor')).not.toBeVisible() await expect(page.getByRole('gridcell', { name: 'value1' })).toBeVisible() @@ -252,7 +253,8 @@ testRunner('table editor', () => { // insert row with another enum value await page.getByTestId('table-editor-insert-new-row').click() await page.getByText('Insert a new row into').click() - await page.getByRole('combobox').selectOption('value2') + await page.getByRole('combobox').click() + await page.getByRole('option', { name: 'value2' }).click() await page.getByTestId('action-bar-save-row').click() await expect(page.getByRole('gridcell', { name: 'value2' })).toBeVisible({ timeout: 10_000 }) @@ -903,7 +905,8 @@ testRunner('table editor', () => { const updateTrueResponse = waitForApiResponse(page, 'pg-meta', ref, 'query?key=', { method: 'POST', }) - await booleanEditor.selectOption('true') + await booleanEditor.click() + await page.getByRole('option', { name: 'true' }).click() await page.getByRole('columnheader', { name: 'id' }).click() await updateTrueResponse @@ -922,7 +925,8 @@ testRunner('table editor', () => { const updateFalseResponse = waitForApiResponse(page, 'pg-meta', ref, 'query?key=', { method: 'POST', }) - await booleanEditor.selectOption('false') + await booleanEditor.click() + await page.getByRole('option', { name: 'false' }).click() await page.getByRole('columnheader', { name: 'id' }).click() await updateFalseResponse @@ -1019,7 +1023,8 @@ testRunner('table editor', () => { const updateNullResponse = waitForApiResponse(page, 'pg-meta', ref, 'query?key=', { method: 'POST', }) - await booleanEditor.selectOption('null') + await booleanEditor.click() + await page.getByRole('option', { name: 'null' }).click() await page.getByRole('columnheader', { name: 'id' }).click() await updateNullResponse @@ -1034,7 +1039,8 @@ testRunner('table editor', () => { const updateFalseResponse = waitForApiResponse(page, 'pg-meta', ref, 'query?key=', { method: 'POST', }) - await booleanEditor.selectOption('false') + await booleanEditor.click() + await page.getByRole('option', { name: 'false' }).click() await page.getByRole('columnheader', { name: 'id' }).click() await updateFalseResponse diff --git a/packages/ui/index.tsx b/packages/ui/index.tsx index b5093481526..5fa82d80ca5 100644 --- a/packages/ui/index.tsx +++ b/packages/ui/index.tsx @@ -36,7 +36,6 @@ export * from './src/lib/utils' // DATA ENTRY -export * from './src/components/Select' export * from './src/components/Listbox' export * from './src/components/Input' export * from './src/components/Toggle' diff --git a/packages/ui/src/components/Select/Select.module.css b/packages/ui/src/components/Select/Select.module.css deleted file mode 100644 index 26c8aa29f50..00000000000 --- a/packages/ui/src/components/Select/Select.module.css +++ /dev/null @@ -1,86 +0,0 @@ -.sbui-select-container { - @apply relative; -} - -.sbui-select { - @apply block w-full bg-white pl-3 pr-10 py-2 text-sm rounded-md shadow-sm transition-all; - - @apply text-input-value-light border border-solid border-input-border-light; - @apply focus:ring-input-border-focus-light focus:border-input-border-focus-light focus:outline-none; - - @apply dark:bg-transparent dark:text-input-value-dark dark:border-input-border-dark; - @apply dark:focus:border-input-border-focus-dark dark:focus:ring-input-border-focus-dark; - -webkit-appearance: none; - -moz-appearance: none; - text-overflow: ''; - /* box-shadow: 0 0 0 2px rgba(255, 255, 255, 0); */ - transition: box-shadow 0.3s ease-in-out; - - /* // temporary fix - // - // temporary fix for supabase apps - // tailwind @base styles adds a dropdown chevron - // using background image as default - // */ - background-image: none; -} - -.sbui-select option { - @apply bg-white text-gray-800; -} - -.sbui-select:focus { - box-shadow: 0 0 0 2px rgba(62, 207, 142, 0.1); -} - -.sbui-select--error { - @apply border-red-500; -} - -.sbui-select--borderless { - @apply border-transparent shadow-none; -} - -/* - Select sizes -*/ - -.sbui-select--tiny { - @apply px-2.5 py-1.5 text-xs; -} -.sbui-select--small { - @apply px-3 py-2 text-sm leading-4; -} -.sbui-select--medium { - @apply px-4 py-2 text-sm; -} -.sbui-select--large { - @apply px-4 py-2 text-base; -} -.sbui-select--xlarge { - @apply px-6 py-3 text-base; -} - -.sbui-select-actions-container { - @apply absolute inset-y-0 right-0 pl-3 pr-1 mr-5 flex items-center; -} - -/* - Select icon -*/ - -.sbui-select--with-icon { - @apply pl-7; -} - -/* - Select Chevron -*/ - -.sbui-select-chevron-container { - @apply absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none; -} - -.sbui-select-chevron { - @apply h-5 w-5 text-gray-400; -} diff --git a/packages/ui/src/components/Select/Select.test.jsx b/packages/ui/src/components/Select/Select.test.jsx deleted file mode 100644 index 6a0113ba306..00000000000 --- a/packages/ui/src/components/Select/Select.test.jsx +++ /dev/null @@ -1,29 +0,0 @@ -import { render, screen } from '@testing-library/react' -import React from 'react' -import { describe, expect, it } from 'vitest' - -import Select from './Select' - -describe('#Select', () => { - it('should render select correctly', async () => { - render( - - ) - expect(screen.queryByTestId('form-select')).toBeInTheDocument() - }) - - it('should have "form-select--error" class', () => { - render( - - ) - expect(screen.queryByTestId('form-select')).toHaveClass( - 'block box-border w-full rounded-md shadow-sm transition-all text-foreground border focus-visible:shadow-md outline-none focus:ring-current focus:ring-2 focus-visible:border-foreground-muted focus-visible:ring-background-control placeholder-foreground-muted appearance-none bg-none bg-destructive-200 border border-destructive-500 focus:ring-destructive-400 placeholder:text-destructive-400 text-base md:text-sm px-4 py-2' - ) - }) -}) diff --git a/packages/ui/src/components/Select/Select.tsx b/packages/ui/src/components/Select/Select.tsx deleted file mode 100644 index 8ce9d5cb1a1..00000000000 --- a/packages/ui/src/components/Select/Select.tsx +++ /dev/null @@ -1,164 +0,0 @@ -'use client' - -import React from 'react' - -import { FormLayout } from '../../lib/Layout/FormLayout/FormLayout' -import InputErrorIcon from '../../lib/Layout/InputErrorIcon' -import InputIconContainer from '../../lib/Layout/InputIconContainer' -import styleHandler from '../../lib/theme/styleHandler' - -interface OptionProps { - value: string - children: React.ReactNode - selected?: boolean -} - -interface OptGroupProps { - label: string - children: React.ReactNode -} - -export interface Props extends Omit, 'size'> { - autofocus?: boolean - children: React.ReactNode - descriptionText?: string - error?: string - icon?: any - inputRef?: string - label?: string - afterLabel?: string - beforeLabel?: string - labelOptional?: string - layout?: 'horizontal' | 'vertical' - reveal?: boolean - actions?: React.ReactNode - size?: 'tiny' | 'small' | 'medium' | 'large' | 'xlarge' - borderless?: boolean - validation?: (x: any) => void -} - -export const ColLayout = (props: any) =>
{props.children}
- -/** - * @deprecated Use `import { Select_shadcn_ } from "ui"` instead - */ -function Select({ - autoComplete, - autofocus, - children, - className, - descriptionText, - disabled, - error, - icon, - id = '', - inputRef, - label, - afterLabel, - beforeLabel, - labelOptional, - layout, - name = '', - placeholder, - required, - value = undefined, - defaultValue = undefined, - style, - size = 'medium', - borderless = false, - validation, - ...props -}: Props) { - const __styles = styleHandler('select') - - let classesContainer = [__styles.container] - if (className) classesContainer.push(className) - - let classes = [__styles.base] - if (error) classes.push(__styles.variants.error) - if (!error) classes.push(__styles.variants.standard) - if (icon) classes.push(__styles.with_icon[size]) - if (size) classes.push(__styles.size[size]) - if (disabled) classes.push(__styles.disabled) - - return ( - -
- - {icon && } - {error && ( -
- {error && } -
- )} - - - -
-
- ) -} - -/** - * @deprecated Use ./SelectItem_Shadcn_ instead - */ -export function Option({ value, children, selected }: OptionProps) { - return ( - - ) -} - -/** - * @deprecated Use ./SelectGroup_Shadcn_ instead - */ -export function OptGroup({ label, children }: OptGroupProps) { - return {children} -} - -Select.Option = Option -Select.OptGroup = OptGroup - -export default Select diff --git a/packages/ui/src/components/Select/index.tsx b/packages/ui/src/components/Select/index.tsx deleted file mode 100644 index f177e1402d3..00000000000 --- a/packages/ui/src/components/Select/index.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import Select from './Select' - -export default Select -export { default as Select } from './Select' diff --git a/packages/ui/src/lib/theme/defaultTheme.ts b/packages/ui/src/lib/theme/defaultTheme.ts index 777b0e17039..b72e07ca1ef 100644 --- a/packages/ui/src/lib/theme/defaultTheme.ts +++ b/packages/ui/src/lib/theme/defaultTheme.ts @@ -458,52 +458,6 @@ export default { textarea_actions_container_items: 'flex items-center', }, - /* - * Select - */ - - select: { - base: ` - block - box-border - w-full - rounded-md - shadow-sm - transition-all - text-foreground - border - focus-visible:shadow-md - ${defaults.focus} - focus-visible:border-foreground-muted - focus-visible:ring-background-control - ${defaults.placeholder} - - appearance-none - bg-none - `, - variants: { - standard: ` - bg-background - border border-strong - `, - error: ` - bg-destructive-200 - border border-destructive-500 - focus:ring-destructive-400 - placeholder:text-destructive-400 - `, - }, - container: 'relative', - with_icon: with_icon_spacing_sizes, - size: { - ...default__padding_and_text, - }, - disabled: 'opacity-50', - actions_container: 'absolute inset-y-0 right-0 pl-3 pr-1 mr-5 flex items-center', - chevron_container: 'absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none', - chevron: 'h-5 w-5 text-foreground-lighter', - }, - sidepanel: { base: ` z-50