diff --git a/.changeset/fast-drinks-argue.md b/.changeset/fast-drinks-argue.md new file mode 100644 index 000000000..abb92c5d5 --- /dev/null +++ b/.changeset/fast-drinks-argue.md @@ -0,0 +1,38 @@ +--- +'@clickhouse/click-ui': minor +--- + +The Click-UI source code has several circular dependencies that must be resolved. + +During the resolution of component path redundancies and public API encapsulation in #798, several circular dependencies were exposed. There, some quick basic fixes were applied to allow to progress, but it was found that a separate PR was needed to resolve them. + +**What changed?** + +The `InitCUIThemeScript` component and `InitCUIThemeScriptProps` type were previously exported via `src/theme/index.ts` (which has been removed). They are now explicitly exported from the main entry point (`src/index.ts`). Consumers using SSR theme injection must update their imports: + +```tsx +// Before +import { InitCUIThemeScript } from '@clickhouse/click-ui/theme'; + +// After +import { InitCUIThemeScript } from '@clickhouse/click-ui'; +``` + + +**Additional cleanup:** + +Removed orphaned subpath exports for `CrossButton`, `EmptyButton`, and `GridCenter`. These components were moved to `@/components/Common` in a previous refactor but duplicate directories were left behind. They are now exclusively available via the Common module: + +```tsx +// Before +import { CrossButton } from '@clickhouse/click-ui/CrossButton'; + +// After +import { CrossButton } from '@clickhouse/click-ui'; +// or for internal use: +import { CrossButton } from '@/components/Common'; +``` + +**Bug fix:** + +Fixed a broken type export in `src/components/Common/index.ts` that was referencing a deleted file (`Common.types.ts`). The `TextSize`, `TextWeight`, and `CursorOptions` types are now correctly exported from their respective source files (`Typography` and `Panel`). diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index c41c943ab..2c2bda34e 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -1,15 +1,15 @@ -import { useState, useEffect, ReactNode } from "react"; -import type { Preview } from "@storybook/react-vite"; -import { Decorator } from "@storybook/react-vite"; -import { styled } from "styled-components"; -import { themes } from "storybook/theming"; -import ClickUIProvider from "../src/theme/ClickUIProvider/ClickUIProvider"; +import { useState, useEffect, ReactNode } from 'react'; +import type { Preview } from '@storybook/react-vite'; +import { Decorator } from '@storybook/react-vite'; +import { styled } from 'styled-components'; +import { themes } from 'storybook/theming'; +import { ClickUIProvider } from '@/providers'; const ThemeBlock = styled.div<{ $left?: boolean; $bfill?: boolean }>( ({ $left, $bfill: fill, theme }) => ` position: absolute; top: 0.5rem; - left: ${$left || fill ? 0 : "50vw"}; + left: ${$left || fill ? 0 : '50vw'}; right: 0; height: fit-content; bottom: 0; @@ -22,28 +22,26 @@ const ThemeBlock = styled.div<{ $left?: boolean; $bfill?: boolean }>( export const globalTypes = { theme: { - name: "Theme", - description: "Global theme for components", - defaultValue: "system", + name: 'Theme', + description: 'Global theme for components', + defaultValue: 'system', toolbar: { - icon: "circlehollow", + icon: 'circlehollow', items: [ - { value: "system", icon: "browser", title: "system" }, - { value: "dark", icon: "moon", title: "dark" }, - { value: "light", icon: "sun", title: "light" }, + { value: 'system', icon: 'browser', title: 'system' }, + { value: 'dark', icon: 'moon', title: 'dark' }, + { value: 'light', icon: 'sun', title: 'light' }, ], showName: true, }, }, }; -const getSystemTheme = (): "dark" | "light" => { - if (typeof window !== "undefined" && window.matchMedia) { - return window.matchMedia("(prefers-color-scheme: dark)").matches - ? "dark" - : "light"; +const getSystemTheme = (): 'dark' | 'light' => { + if (typeof window !== 'undefined' && window.matchMedia) { + return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; } - return "dark"; + return 'dark'; }; interface ThemeWrapperProps { @@ -52,24 +50,27 @@ interface ThemeWrapperProps { } const ThemeWrapper = ({ themeSelection, children }: ThemeWrapperProps) => { - const [systemTheme, setSystemTheme] = useState<"dark" | "light">(getSystemTheme); + const [systemTheme, setSystemTheme] = useState<'dark' | 'light'>(getSystemTheme); // Listen for system theme changes useEffect(() => { - const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); const handleChange = () => { - setSystemTheme(mediaQuery.matches ? "dark" : "light"); + setSystemTheme(mediaQuery.matches ? 'dark' : 'light'); }; - mediaQuery.addEventListener("change", handleChange); - return () => mediaQuery.removeEventListener("change", handleChange); + mediaQuery.addEventListener('change', handleChange); + return () => mediaQuery.removeEventListener('change', handleChange); }, []); // Resolve the actual theme: handle "system" and fallback for undefined/null const theme = - themeSelection === "system" || !themeSelection ? systemTheme : themeSelection; + themeSelection === 'system' || !themeSelection ? systemTheme : themeSelection; return ( - + {children} ); @@ -90,22 +91,22 @@ const preview: Preview = { parameters: { options: { storySort: { - method: "alphabetical", + method: 'alphabetical', order: [ - "Introduction", - "Buttons", - "Cards", - "Layout", - "Forms", - "Display", - "Sidebar", - "Typography", - "Colors", - ["Title", "Text", "Link"], + 'Introduction', + 'Buttons', + 'Cards', + 'Layout', + 'Forms', + 'Display', + 'Sidebar', + 'Typography', + 'Colors', + ['Title', 'Text', 'Link'], ], }, }, - actions: { argTypesRegex: "^on[A-Z].*" }, + actions: { argTypesRegex: '^on[A-Z].*' }, controls: { matchers: { color: /(background|color)$/i, diff --git a/package.json b/package.json index 158dc9150..ecb010057 100644 --- a/package.json +++ b/package.json @@ -157,6 +157,11 @@ "import": "./dist/esm/components/GenericLabel/index.js", "require": "./dist/cjs/components/GenericLabel/index.cjs" }, + "./GenericMenu": { + "types": "./dist/types/components/GenericMenu/index.d.ts", + "import": "./dist/esm/components/GenericMenu/index.js", + "require": "./dist/cjs/components/GenericMenu/index.cjs" + }, "./Grid": { "types": "./dist/types/components/Grid/index.d.ts", "import": "./dist/esm/components/Grid/index.js", diff --git a/src/components/Accordion/Accordion.stories.tsx b/src/components/Accordion/Accordion.stories.tsx index 478f3fa98..62ba3b9c0 100644 --- a/src/components/Accordion/Accordion.stories.tsx +++ b/src/components/Accordion/Accordion.stories.tsx @@ -1,9 +1,9 @@ import { Meta, StoryObj } from '@storybook/react-vite'; -import { Panel } from '..'; +import { Panel } from '@/components/Panel'; import { Accordion } from '@/components/Accordion'; -import { Spacer } from '../Spacer'; -import { Text } from '../Typography/Text/Text'; -import { Title } from '../Typography/Title/Title'; +import { Spacer } from '@/components/Spacer'; +import { Text } from '@/components/Typography/Text'; +import { Title } from '@/components/Typography/Title'; const meta: Meta = { component: Accordion, diff --git a/src/components/Accordion/Accordion.types.ts b/src/components/Accordion/Accordion.types.ts index e45f93727..a511e590c 100644 --- a/src/components/Accordion/Accordion.types.ts +++ b/src/components/Accordion/Accordion.types.ts @@ -1,7 +1,7 @@ import * as RadixAccordion from '@radix-ui/react-accordion'; import { ReactNode } from 'react'; -import { IconName } from '@/components/Icon'; -import { IconSize } from '@/types'; +import type { AssetSize } from '@/types'; +import type { IconName } from '@/components/Icon'; export type Size = 'sm' | 'md' | 'lg'; export type Gap = 'sm' | 'md' | 'lg'; @@ -18,7 +18,7 @@ export interface AccordionProps title: ReactNode; color?: Color; icon?: IconName; - iconSize?: IconSize; + iconSize?: AssetSize; gap?: Gap; children: React.ReactNode; fillWidth?: boolean; diff --git a/src/components/Alert/Alert.tsx b/src/components/Alert/Alert.tsx index 21fb7ba00..0886374dd 100644 --- a/src/components/Alert/Alert.tsx +++ b/src/components/Alert/Alert.tsx @@ -1,4 +1,4 @@ -import { Icon, IconName } from '@/components/Icon'; +import { Icon, type IconName } from '@/components/Icon'; import { useState, useCallback } from 'react'; import { styled } from 'styled-components'; import { AlertProps } from './Alert.types'; diff --git a/src/components/Alert/Alert.types.ts b/src/components/Alert/Alert.types.ts index 19d1bf6e3..d6fb43aa3 100644 --- a/src/components/Alert/Alert.types.ts +++ b/src/components/Alert/Alert.types.ts @@ -1,4 +1,4 @@ -import { IconName } from '@/components/Icon'; +import type { IconName } from '@/components/Icon'; import { ReactNode } from 'react'; type AlertType = 'default' | 'banner'; diff --git a/src/components/Assets/Flags/Australia.tsx b/src/components/Assets/Flags/Australia.tsx index 9dc4ce717..c76cd0b33 100644 --- a/src/components/Assets/Flags/Australia.tsx +++ b/src/components/Assets/Flags/Australia.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { SVGAssetProps } from './system/types'; +import type { SVGAssetProps } from '@/types'; const Australia = (props: SVGAssetProps): React.ReactElement => ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( > = { diff --git a/src/components/Assets/Flags/system/FlagsLight.ts b/src/components/Assets/Flags/system/FlagsLight.ts index 60de12931..415465102 100644 --- a/src/components/Assets/Flags/system/FlagsLight.ts +++ b/src/components/Assets/Flags/system/FlagsLight.ts @@ -27,7 +27,7 @@ import United_Arab_Emirates from '../United-Arab-Emirates'; import United_Kingdom from '../United-Kingdom'; import United_States from '../United-States'; import { FlagName } from './types'; -import type { SVGAssetProps } from '../../types'; +import type { SVGAssetProps } from '@/types'; import type { ComponentType } from 'react'; const FlagsLight: Record> = { diff --git a/src/components/Assets/Flags/system/types.ts b/src/components/Assets/Flags/system/types.ts index 43901de8a..b876d8d0c 100644 --- a/src/components/Assets/Flags/system/types.ts +++ b/src/components/Assets/Flags/system/types.ts @@ -1,7 +1,6 @@ import type { SVGAttributes } from 'react'; -import type { IconSize } from '@/types'; +import type { AssetSize } from '@/types'; import type { ThemeName } from '@/theme/theme.types'; -import type { SVGAssetProps } from '../../types'; export type FlagName = | 'australia' @@ -29,7 +28,5 @@ export type FlagName = export interface FlagProps extends SVGAttributes { name: FlagName; theme?: ThemeName; - size?: IconSize; + size?: AssetSize; } - -export type { SVGAssetProps }; diff --git a/src/components/Assets/Icons/Activity.tsx b/src/components/Assets/Icons/Activity.tsx index 50d1a58be..de7eb7d59 100644 --- a/src/components/Assets/Icons/Activity.tsx +++ b/src/components/Assets/Icons/Activity.tsx @@ -1,4 +1,4 @@ -import { SVGAssetProps } from './system/types'; +import type { SVGAssetProps } from '@/types'; const Activity = (props: SVGAssetProps) => ( { return ( diff --git a/src/components/Assets/Icons/Arrow-Directions.tsx b/src/components/Assets/Icons/Arrow-Directions.tsx index 6543dc5aa..380a876d3 100644 --- a/src/components/Assets/Icons/Arrow-Directions.tsx +++ b/src/components/Assets/Icons/Arrow-Directions.tsx @@ -1,4 +1,4 @@ -import { SVGAssetProps } from './system/types'; +import type { SVGAssetProps } from '@/types'; const Arrow_Directions = (props: SVGAssetProps) => ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( { return ( diff --git a/src/components/Assets/Icons/Gift.tsx b/src/components/Assets/Icons/Gift.tsx index fc553ebb9..21c4ed59b 100644 --- a/src/components/Assets/Icons/Gift.tsx +++ b/src/components/Assets/Icons/Gift.tsx @@ -1,4 +1,4 @@ -import { SVGAssetProps } from './system/types'; +import type { SVGAssetProps } from '@/types'; const Gift = (props: SVGAssetProps) => ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( { return ( diff --git a/src/components/Assets/Icons/List-Bulleted.tsx b/src/components/Assets/Icons/List-Bulleted.tsx index 6dea8aeda..477183729 100644 --- a/src/components/Assets/Icons/List-Bulleted.tsx +++ b/src/components/Assets/Icons/List-Bulleted.tsx @@ -1,4 +1,4 @@ -import { SVGAssetProps } from './system/types'; +import type { SVGAssetProps } from '@/types'; const List_Bulleted = (props: SVGAssetProps) => ( ( ( diff --git a/src/components/Assets/Icons/Lock.tsx b/src/components/Assets/Icons/Lock.tsx index f5e6e9c37..f57be22f9 100644 --- a/src/components/Assets/Icons/Lock.tsx +++ b/src/components/Assets/Icons/Lock.tsx @@ -1,4 +1,4 @@ -import { SVGAssetProps } from './system/types'; +import type { SVGAssetProps } from '@/types'; const Lock = (props: SVGAssetProps) => ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( { return ( diff --git a/src/components/Assets/Icons/Puzzle-Piece.tsx b/src/components/Assets/Icons/Puzzle-Piece.tsx index 037e5af2a..f300037ec 100644 --- a/src/components/Assets/Icons/Puzzle-Piece.tsx +++ b/src/components/Assets/Icons/Puzzle-Piece.tsx @@ -1,4 +1,4 @@ -import { SVGAssetProps } from './system/types'; +import type { SVGAssetProps } from '@/types'; const Puzzle_Piece = (props: SVGAssetProps) => { return ( diff --git a/src/components/Assets/Icons/Query.tsx b/src/components/Assets/Icons/Query.tsx index cb420e0ab..8260b8b81 100644 --- a/src/components/Assets/Icons/Query.tsx +++ b/src/components/Assets/Icons/Query.tsx @@ -1,4 +1,4 @@ -import { SVGAssetProps } from './system/types'; +import type { SVGAssetProps } from '@/types'; const Query = (props: SVGAssetProps) => ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( { return ( diff --git a/src/components/Assets/Icons/Sparkle.tsx b/src/components/Assets/Icons/Sparkle.tsx index e05754d2e..23544d029 100644 --- a/src/components/Assets/Icons/Sparkle.tsx +++ b/src/components/Assets/Icons/Sparkle.tsx @@ -1,4 +1,4 @@ -import { SVGAssetProps } from './system/types'; +import type { SVGAssetProps } from '@/types'; const Sparkle = (props: SVGAssetProps) => ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( > = { diff --git a/src/components/Assets/Icons/system/IconsLight.ts b/src/components/Assets/Icons/system/IconsLight.ts index 551e8869b..6cf5044c0 100644 --- a/src/components/Assets/Icons/system/IconsLight.ts +++ b/src/components/Assets/Icons/system/IconsLight.ts @@ -173,8 +173,8 @@ import User from '../User'; import Users from '../Users'; import Warning from '../Warning'; import Waves from '../Waves'; -import { IconName } from './types'; -import type { SVGAssetProps } from '../../types'; +import type { IconName } from './types'; +import type { SVGAssetProps } from '@/types'; import type { ComponentType } from 'react'; const IconsLight: Record> = { diff --git a/src/components/Assets/Icons/system/retroactiveNames.ts b/src/components/Assets/Icons/system/retroactiveNames.ts index 8aa1e65cf..e772a2196 100644 --- a/src/components/Assets/Icons/system/retroactiveNames.ts +++ b/src/components/Assets/Icons/system/retroactiveNames.ts @@ -1,174 +1,4 @@ -import { IconName } from './types'; - -export type DeprecatedIconName = - | 'Activity' - | 'Alarm' - | 'ArrowDirections' - | 'ArrowDown' - | 'ArrowLeft' - | 'ArrowRight' - | 'ArrowTriangle' - | 'ArrowUp' - | 'AuthApp' - | 'AuthSms' - | 'Backups' - | 'BarChart' - | 'Bell' - | 'Beta' - | 'Blog' - | 'Bold' - | 'Book' - | 'Brackets' - | 'Briefcase' - | 'Building' - | 'BurgerMenu' - | 'Calendar' - | 'CalendarWithTime' - | 'Cards' - | 'CellTower' - | 'ChartArea' - | 'ChartBarHorizontal' - | 'ChartCloud' - | 'ChartDonut' - | 'ChartHeatmap' - | 'ChartScatter' - | 'ChartSquare' - | 'ChartStackedHorizontal' - | 'ChartStackedVertical' - | 'ChatIcon' - | 'CheckIcon' - | 'CheckInCircle' - | 'ChevronDown' - | 'ChevronLeft' - | 'ChevronRight' - | 'ChevronUp' - | 'Circle' - | 'Clock' - | 'Cloud' - | 'CloudKeys' - | 'Code' - | 'CodeInSquare' - | 'Connect' - | 'ConnectAlt' - | 'Console' - | 'Copy' - | 'Cpu' - | 'CreditCard' - | 'CrossIcon' - | 'Data' - | 'DataLakes' - | 'DatabaseIcon' - | 'Disk' - | 'Display' - | 'Document' - | 'Dot' - | 'DotsHorizontal' - | 'DotsTriangle' - | 'DotsVertical' - | 'DotsVerticalDouble' - | 'DoubleCheckIcon' - | 'Download' - | 'DownloadInCircle' - | 'Email' - | 'Empty' - | 'Enter' - | 'Eye' - | 'EyeClosed' - | 'FilterIcon' - | 'Fire' - | 'Flag' - | 'Flash' - | 'Flask' - | 'FolderClosed' - | 'FolderOpen' - | 'Gear' - | 'Gift' - | 'GitMerge' - | 'Globe' - | 'Hexagon' - | 'HistoryIcon' - | 'Home' - | 'HorizontalLoading' - | 'Http' - | 'HttpMonitoring' - | 'InfoInCircleIcon' - | 'InformationIcon' - | 'InsertRowIcon' - | 'Integrations' - | 'Italic' - | 'Key' - | 'Keys' - | 'Lifebuoy' - | 'LightBulb' - | 'LightBulbOn' - | 'Lightening' - | 'LineInCircle' - | 'ListBulleted' - | 'ListNumbered' - | 'Loading' - | 'LoadingAnimated' - | 'Lock' - | 'MapPin' - | 'Mcp' - | 'Metrics' - | 'MetricsAlt' - | 'Minus' - | 'Moon' - | 'NoCloud' - | 'Pause' - | 'Payment' - | 'Pencil' - | 'PieChart' - | 'Pipe' - | 'Play' - | 'PlayInCircle' - | 'Plug' - | 'Plus' - | 'Popout' - | 'PopoverArrow' - | 'PuzzlePiece' - | 'Query' - | 'Question' - | 'Refresh' - | 'ResizeArrowsHorizontal' - | 'ResizeArrowsVertical' - | 'Rocket' - | 'SandGlass' - | 'Search' - | 'Secure' - | 'Server' - | 'Services' - | 'Settings' - | 'Share' - | 'ShareArrow' - | 'ShareNetwork' - | 'Sleep' - | 'SlideIn' - | 'SlideOut' - | 'SortAltIcon' - | 'SortIcon' - | 'Sparkle' - | 'Speaker' - | 'Speed' - | 'Square' - | 'Star' - | 'Stop' - | 'Support' - | 'Table' - | 'Taxi' - | 'TextSlash' - | 'ThumbsDown' - | 'ThumbsUp' - | 'Trash' - | 'TreeStructure' - | 'Underline' - | 'Upgrade' - | 'Upload' - | 'Url' - | 'UserIcon' - | 'UsersIcon' - | 'WarningIcon' - | 'Waves'; +import type { IconName, DeprecatedIconName } from './types'; export const ICON_NAME_RETRO_MAP: Record = { Activity: 'activity', diff --git a/src/components/Assets/Icons/system/types.ts b/src/components/Assets/Icons/system/types.ts index aebd4502c..54b16ec47 100644 --- a/src/components/Assets/Icons/system/types.ts +++ b/src/components/Assets/Icons/system/types.ts @@ -1,8 +1,6 @@ import type { SVGAttributes } from 'react'; -import type { SVGAssetProps } from '../../types'; -import { ThemeName } from '@/theme/theme.types'; -import { type DeprecatedIconName } from './retroactiveNames'; -import type { IconSize } from '@/types'; +import type { AssetSize } from '@/types'; +import type { ThemeName } from '@/theme/theme.types'; export type IconName = | 'activity' @@ -174,10 +172,178 @@ export type IconName = | 'warning' | 'waves'; +export type DeprecatedIconName = + | 'Activity' + | 'Alarm' + | 'ArrowDirections' + | 'ArrowDown' + | 'ArrowLeft' + | 'ArrowRight' + | 'ArrowTriangle' + | 'ArrowUp' + | 'AuthApp' + | 'AuthSms' + | 'Backups' + | 'BarChart' + | 'Bell' + | 'Beta' + | 'Blog' + | 'Bold' + | 'Book' + | 'Brackets' + | 'Briefcase' + | 'Building' + | 'BurgerMenu' + | 'Calendar' + | 'CalendarWithTime' + | 'Cards' + | 'CellTower' + | 'ChartArea' + | 'ChartBarHorizontal' + | 'ChartCloud' + | 'ChartDonut' + | 'ChartHeatmap' + | 'ChartScatter' + | 'ChartSquare' + | 'ChartStackedHorizontal' + | 'ChartStackedVertical' + | 'ChatIcon' + | 'CheckIcon' + | 'CheckInCircle' + | 'ChevronDown' + | 'ChevronLeft' + | 'ChevronRight' + | 'ChevronUp' + | 'Circle' + | 'Clock' + | 'Cloud' + | 'CloudKeys' + | 'Code' + | 'CodeInSquare' + | 'Connect' + | 'ConnectAlt' + | 'Console' + | 'Copy' + | 'Cpu' + | 'CreditCard' + | 'CrossIcon' + | 'Data' + | 'DataLakes' + | 'DatabaseIcon' + | 'Disk' + | 'Display' + | 'Document' + | 'Dot' + | 'DotsHorizontal' + | 'DotsTriangle' + | 'DotsVertical' + | 'DotsVerticalDouble' + | 'DoubleCheckIcon' + | 'Download' + | 'DownloadInCircle' + | 'Email' + | 'Empty' + | 'Enter' + | 'Eye' + | 'EyeClosed' + | 'FilterIcon' + | 'Fire' + | 'Flag' + | 'Flash' + | 'Flask' + | 'FolderClosed' + | 'FolderOpen' + | 'Gear' + | 'Gift' + | 'GitMerge' + | 'Globe' + | 'Hexagon' + | 'HistoryIcon' + | 'Home' + | 'HorizontalLoading' + | 'Http' + | 'HttpMonitoring' + | 'InfoInCircleIcon' + | 'InformationIcon' + | 'InsertRowIcon' + | 'Integrations' + | 'Italic' + | 'Key' + | 'Keys' + | 'Lifebuoy' + | 'LightBulb' + | 'LightBulbOn' + | 'Lightening' + | 'LineInCircle' + | 'ListBulleted' + | 'ListNumbered' + | 'Loading' + | 'LoadingAnimated' + | 'Lock' + | 'MapPin' + | 'Mcp' + | 'Metrics' + | 'MetricsAlt' + | 'Minus' + | 'Moon' + | 'NoCloud' + | 'Pause' + | 'Payment' + | 'Pencil' + | 'PieChart' + | 'Pipe' + | 'Play' + | 'PlayInCircle' + | 'Plug' + | 'Plus' + | 'Popout' + | 'PopoverArrow' + | 'PuzzlePiece' + | 'Query' + | 'Question' + | 'Refresh' + | 'ResizeArrowsHorizontal' + | 'ResizeArrowsVertical' + | 'Rocket' + | 'SandGlass' + | 'Search' + | 'Secure' + | 'Server' + | 'Services' + | 'Settings' + | 'Share' + | 'ShareArrow' + | 'ShareNetwork' + | 'Sleep' + | 'SlideIn' + | 'SlideOut' + | 'SortAltIcon' + | 'SortIcon' + | 'Sparkle' + | 'Speaker' + | 'Speed' + | 'Square' + | 'Star' + | 'Stop' + | 'Support' + | 'Table' + | 'Taxi' + | 'TextSlash' + | 'ThumbsDown' + | 'ThumbsUp' + | 'Trash' + | 'TreeStructure' + | 'Underline' + | 'Upgrade' + | 'Upload' + | 'Url' + | 'UserIcon' + | 'UsersIcon' + | 'WarningIcon' + | 'Waves'; + export interface IconProps extends SVGAttributes { name: IconName | DeprecatedIconName; theme?: ThemeName; - size?: IconSize; + size?: AssetSize; } - -export type { SVGAssetProps }; diff --git a/src/components/Assets/Logos/AWS.tsx b/src/components/Assets/Logos/AWS.tsx index 4586593ab..8f29f54a0 100644 --- a/src/components/Assets/Logos/AWS.tsx +++ b/src/components/Assets/Logos/AWS.tsx @@ -1,6 +1,6 @@ /* eslint-disable react-refresh/only-export-components */ -import { SVGAssetProps } from './system/types'; +import type { SVGAssetProps } from '@/types'; // TODO: Can this logo have a base and extend it? // Check this separately, see OVH.tsx diff --git a/src/components/Assets/Logos/AWS_ATHENA.tsx b/src/components/Assets/Logos/AWS_ATHENA.tsx index ac00516be..0c7a9ee3c 100644 --- a/src/components/Assets/Logos/AWS_ATHENA.tsx +++ b/src/components/Assets/Logos/AWS_ATHENA.tsx @@ -1,4 +1,4 @@ -import { SVGAssetProps } from './system/types'; +import type { SVGAssetProps } from '@/types'; const AWS_ATHENA = (props: SVGAssetProps) => ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( diff --git a/src/components/Assets/Logos/OneLake.tsx b/src/components/Assets/Logos/OneLake.tsx index b179b4adb..4aa88d064 100644 --- a/src/components/Assets/Logos/OneLake.tsx +++ b/src/components/Assets/Logos/OneLake.tsx @@ -1,4 +1,4 @@ -import { SVGAssetProps } from './system/types'; +import type { SVGAssetProps } from '@/types'; const NodeJs = (props: SVGAssetProps) => ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( > = { diff --git a/src/components/Assets/Logos/system/LogosLight.ts b/src/components/Assets/Logos/system/LogosLight.ts index 7a20acfac..75129f663 100644 --- a/src/components/Assets/Logos/system/LogosLight.ts +++ b/src/components/Assets/Logos/system/LogosLight.ts @@ -80,7 +80,7 @@ import Upstash from '../Upstash'; import Vector from '../Vector'; import WarpStream from '../WarpStream'; import { LogoName } from './types'; -import type { SVGAssetProps } from '../../types'; +import type { SVGAssetProps } from '@/types'; import type { ComponentType } from 'react'; const LogosLight: Record> = { diff --git a/src/components/Assets/Logos/system/types.ts b/src/components/Assets/Logos/system/types.ts index a01b84ddd..afb4ad234 100644 --- a/src/components/Assets/Logos/system/types.ts +++ b/src/components/Assets/Logos/system/types.ts @@ -1,7 +1,6 @@ import type { SVGAttributes } from 'react'; -import type { IconSize } from '@/types'; +import type { AssetSize } from '@/types'; import type { ThemeName } from '@/theme/theme.types'; -import type { SVGAssetProps } from '../../types'; export type LogoName = | 'airbyte' @@ -82,7 +81,5 @@ export type LogoName = export interface LogoProps extends SVGAttributes { name: LogoName; theme?: ThemeName; - size?: IconSize; + size?: AssetSize; } - -export type { SVGAssetProps }; diff --git a/src/components/Assets/Payments/Amex.tsx b/src/components/Assets/Payments/Amex.tsx index 05e82a598..3da94042d 100644 --- a/src/components/Assets/Payments/Amex.tsx +++ b/src/components/Assets/Payments/Amex.tsx @@ -1,4 +1,4 @@ -import { SVGAssetProps } from './system/types'; +import type { SVGAssetProps } from '@/types'; const Amex = (props: SVGAssetProps) => ( ( ( ( > = { diff --git a/src/components/Assets/Payments/system/PaymentsLight.ts b/src/components/Assets/Payments/system/PaymentsLight.ts index f9b1491a0..f6eb94763 100644 --- a/src/components/Assets/Payments/system/PaymentsLight.ts +++ b/src/components/Assets/Payments/system/PaymentsLight.ts @@ -10,7 +10,7 @@ import MasterCard from '../MasterCard'; import Paypal from '../Paypal'; import Visa from '../Visa'; import { PaymentName } from './types'; -import type { SVGAssetProps } from '../../types'; +import type { SVGAssetProps } from '@/types'; import type { ComponentType } from 'react'; const PaymentsLight: Record> = { diff --git a/src/components/Assets/Payments/system/types.ts b/src/components/Assets/Payments/system/types.ts index 98552b6f5..080a63b92 100644 --- a/src/components/Assets/Payments/system/types.ts +++ b/src/components/Assets/Payments/system/types.ts @@ -1,14 +1,11 @@ import type { SVGAttributes } from 'react'; -import type { IconSize } from '@/types'; +import type { AssetSize } from '@/types'; import type { ThemeName } from '@/theme/theme.types'; -import type { SVGAssetProps } from '../../types'; export type PaymentName = 'amex' | 'mastercard' | 'paypal' | 'visa'; export interface PaymentProps extends SVGAttributes { name: PaymentName; theme?: ThemeName; - size?: IconSize; + size?: AssetSize; } - -export type { SVGAssetProps }; diff --git a/src/components/Assets/types.ts b/src/components/Assets/types.ts index 6d882962d..6dc61c07c 100644 --- a/src/components/Assets/types.ts +++ b/src/components/Assets/types.ts @@ -1,8 +1,8 @@ import type { SVGAttributes } from 'react'; -import type { IconSize } from '@/types'; +import type { AssetSize } from '@/types'; import type { ThemeName } from '@/theme/theme.types'; export type SVGAssetProps = SVGAttributes & { theme?: ThemeName; - size?: IconSize; + size?: AssetSize; }; diff --git a/src/components/AutoComplete/AutoComplete.tsx b/src/components/AutoComplete/AutoComplete.tsx index d2bcdfe32..fc51b98b9 100644 --- a/src/components/AutoComplete/AutoComplete.tsx +++ b/src/components/AutoComplete/AutoComplete.tsx @@ -26,7 +26,6 @@ import { IconWrapper } from '@/components/IconWrapper'; import { getTextFromNodes } from '@/lib/getTextFromNodes'; import { mergeRefs } from '@/utils/mergeRefs'; -import AutoCompleteOptionList from './AutoCompleteOptionList'; import { useOption, useSearch } from './useOption'; import { OptionContext } from './OptionContext'; @@ -528,14 +527,37 @@ export const AutoComplete = ({ - {options && options.length > 0 ? ( - - ) : ( - children - )} + {options && options.length > 0 + ? options.map((optionProps, index) => { + if ('options' in optionProps) { + const { options: itemList = [], ...groupProps } = optionProps; + return ( + + {itemList.map( + ({ label, ...itemProps }, itemIndex: number) => ( + + {label} + + ) + )} + + ); + } else { + return ( + + ); + } + }) + : children} {visibleList.current.length === 0 && ( diff --git a/src/components/AutoComplete/AutoCompleteOptionList.tsx b/src/components/AutoComplete/AutoCompleteOptionList.tsx deleted file mode 100644 index dd866983e..000000000 --- a/src/components/AutoComplete/AutoCompleteOptionList.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { ReactNode } from 'react'; -import { Group, Item, AutoCompleteOptionListItem } from './AutoComplete'; - -interface Props { - options: AutoCompleteOptionListItem[]; - id: string; -} -const AutoCompleteOptionList = ({ options, id }: Props): ReactNode => - options.map((props, index) => { - if ('options' in props) { - const { options: itemList = [], ...groupProps } = props; - return ( - - {itemList.map(({ label, ...itemProps }, itemIndex: number) => ( - - {label} - - ))} - - ); - } else { - return ( - - ); - } - }); - -export default AutoCompleteOptionList; diff --git a/src/components/Button/BaseButton.tsx b/src/components/Button/BaseButton.tsx new file mode 100644 index 000000000..73510d0d8 --- /dev/null +++ b/src/components/Button/BaseButton.tsx @@ -0,0 +1,31 @@ +import { styled } from 'styled-components'; + +export const BaseButton = styled.button` + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + cursor: pointer; + ${({ theme }) => ` + padding: ${theme.click.button.basic.space.y} ${theme.click.button.basic.space.x}; + border-radius: ${theme.click.button.radii.all}; + gap: ${theme.click.button.basic.space.gap}; + font: ${theme.click.button.basic.typography.label.default}; + &:hover { + font: ${theme.click.button.basic.typography.label.hover}; + } + + &:active, + &:focus { + outline: none; + font: ${theme.click.button.basic.typography.label.active}; + } + + &:disabled, + &:disabled:hover, + &:disabled:active { + font: ${theme.click.button.basic.typography.label.disabled}; + cursor: not-allowed; + } + `} +`; diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx index 8203a1f3f..aabdfe63a 100644 --- a/src/components/Button/Button.tsx +++ b/src/components/Button/Button.tsx @@ -1,7 +1,6 @@ import { Icon } from '@/components/Icon'; - import { styled, keyframes } from 'styled-components'; -import { BaseButton } from '@/components/Common'; +import { BaseButton } from './BaseButton'; import { Alignment, ButtonProps, ButtonType } from './Button.types'; export const Button = ({ @@ -175,7 +174,12 @@ const StyledButton = styled(BaseButton)<{ }} `; -const ButtonIcon = styled(Icon)` +// Lazy wrapper to avoid circular dependency issues at module load time +const ButtonIconWrapper = (props: React.ComponentProps) => ( + +); + +const ButtonIcon = styled(ButtonIconWrapper)` height: ${({ theme }) => theme.click.button.basic.size.icon.all}; width: ${({ theme }) => theme.click.button.basic.size.icon.all}; svg { diff --git a/src/components/Button/Button.types.ts b/src/components/Button/Button.types.ts index 6ec0ec6da..79717d029 100644 --- a/src/components/Button/Button.types.ts +++ b/src/components/Button/Button.types.ts @@ -1,4 +1,4 @@ -import { IconName } from '@/components/Icon'; +import type { IconName } from '@/components/Icon'; export type ButtonType = 'primary' | 'secondary' | 'empty' | 'danger'; export type Alignment = 'center' | 'left'; diff --git a/src/components/CardSecondary/CardSecondary.tsx b/src/components/CardSecondary/CardSecondary.tsx index df3a08a99..9b0def8ca 100644 --- a/src/components/CardSecondary/CardSecondary.tsx +++ b/src/components/CardSecondary/CardSecondary.tsx @@ -107,7 +107,7 @@ export const CardSecondary = ({ infoUrl, infoText, infoIcon = 'chevron-right', - infoIconSize = 'md', + infoAssetSize = 'md', ...props }: CardSecondaryProps) => { return ( @@ -154,7 +154,7 @@ export const CardSecondary = ({ > {infoText} diff --git a/src/components/CardSecondary/CardSecondary.types.ts b/src/components/CardSecondary/CardSecondary.types.ts index 77ac86f7e..6a0818be2 100644 --- a/src/components/CardSecondary/CardSecondary.types.ts +++ b/src/components/CardSecondary/CardSecondary.types.ts @@ -1,6 +1,6 @@ import { HTMLAttributes, ReactNode } from 'react'; -import type { IconName } from '@/components/Icon'; -import type { IconSize } from '@/types'; +import type { AssetSize } from '@/types'; +import type { IconName } from '@/components/Icon/Icon.types'; export type BadgeState = | 'default' @@ -23,5 +23,5 @@ export interface CardSecondaryProps extends HTMLAttributes { infoUrl?: string; infoText?: string; infoIcon?: IconName; - infoIconSize?: IconSize; + infoAssetSize?: AssetSize; } diff --git a/src/components/CodeBlock/useColorStyle.ts b/src/components/CodeBlock/useColorStyle.ts index c571ca506..e85232dc5 100644 --- a/src/components/CodeBlock/useColorStyle.ts +++ b/src/components/CodeBlock/useColorStyle.ts @@ -1,5 +1,5 @@ import { useTheme } from 'styled-components'; -import { CodeThemeType } from '@/components/CodeBlock'; +import { CodeThemeType } from './CodeBlock.types'; const useColorStyle = (defaultTheme?: CodeThemeType) => { const theme = useTheme(); diff --git a/src/components/Common/Common.types.ts b/src/components/Common/Common.types.ts deleted file mode 100644 index 59be08037..000000000 --- a/src/components/Common/Common.types.ts +++ /dev/null @@ -1,40 +0,0 @@ -export type TextSize = 'xs' | 'sm' | 'md' | 'lg'; -export type TextWeight = 'normal' | 'medium' | 'semibold' | 'bold' | 'mono'; - -export type CursorOptions = - | 'auto' - | 'default' - | 'none' - | 'context-menu' - | 'help' - | 'pointer' - | 'progress' - | 'wait' - | 'cell' - | 'crosshair' - | 'text' - | 'vertical-text' - | 'alias' - | 'copy' - | 'move' - | 'no-drop' - | 'not-allowed' - | 'grab' - | 'grabbing' - | 'e-resize' - | 'n-resize' - | 'ne-resize' - | 'nw-resize' - | 's-resize' - | 'se-resize' - | 'sw-resize' - | 'w-resize' - | 'ew-resize' - | 'ns-resize' - | 'nesw-resize' - | 'nwse-resize' - | 'col-resize' - | 'row-resize' - | 'all-scroll' - | 'zoom-in' - | 'zoom-out'; diff --git a/src/components/Common/index.ts b/src/components/Common/index.ts index 570b9b64a..1fedbb1ea 100644 --- a/src/components/Common/index.ts +++ b/src/components/Common/index.ts @@ -6,4 +6,5 @@ export { GridCenter } from './GridCenter'; export { BaseButton } from './BaseButton'; export { FormElementContainer } from './FormElementContainer'; export { EllipsisContainer } from './EllipsisContainer'; -export type { TextSize, TextWeight, CursorOptions } from './Common.types'; +export type { TextSize, TextWeight } from '@/components/Typography'; +export type { CursorOptions } from '@/components/Panel/Panel.types'; diff --git a/src/components/Container/Container.stories.tsx b/src/components/Container/Container.stories.tsx index 78f0495a5..76b337665 100644 --- a/src/components/Container/Container.stories.tsx +++ b/src/components/Container/Container.stories.tsx @@ -1,6 +1,6 @@ import { Meta, StoryObj } from '@storybook/react-vite'; import { Container } from '@/components/Container'; -import { Text } from '..'; +import { Text } from '@/components/Typography/Text'; import { styled } from 'styled-components'; const GridCenter = styled.div` diff --git a/src/components/ContextMenu/ContextMenu.tsx b/src/components/ContextMenu/ContextMenu.tsx index d497bb24c..a79bfce19 100644 --- a/src/components/ContextMenu/ContextMenu.tsx +++ b/src/components/ContextMenu/ContextMenu.tsx @@ -2,8 +2,8 @@ import * as RightMenu from '@radix-ui/react-context-menu'; import { styled } from 'styled-components'; import { forwardRef } from 'react'; import type { HorizontalDirection } from '@/types'; -import { Icon } from '@/components/Icon/Icon'; -import type { IconName } from '@/components/Icon/Icon.types'; +import { Icon } from '@/components/Icon'; +import type { IconName } from '@/components/Icon'; import { Arrow, GenericMenuItem, GenericMenuPanel } from '@/components/GenericMenu'; import Popover_Arrow from '@/components/Assets/Icons/Popover-Arrow'; import { IconWrapper } from '@/components/IconWrapper/IconWrapper'; diff --git a/src/components/DateDetails/DateDetails.types.ts b/src/components/DateDetails/DateDetails.types.ts index 312520644..6e9a46493 100644 --- a/src/components/DateDetails/DateDetails.types.ts +++ b/src/components/DateDetails/DateDetails.types.ts @@ -1,5 +1,5 @@ import { Dayjs } from 'dayjs'; -import type { TextSize, TextWeight } from '@/components/Common'; +import type { TextSize, TextWeight } from '@/components/Typography'; export type ArrowPosition = 'top' | 'right' | 'bottom' | 'left'; diff --git a/src/components/Dropdown/Dropdown.tsx b/src/components/Dropdown/Dropdown.tsx index bbcbcf942..28fb0fc8c 100644 --- a/src/components/Dropdown/Dropdown.tsx +++ b/src/components/Dropdown/Dropdown.tsx @@ -4,8 +4,8 @@ import { styled } from 'styled-components'; import { Arrow, GenericMenuItem, GenericMenuPanel } from '@/components/GenericMenu'; import Popover_Arrow from '@/components/Assets/Icons/Popover-Arrow'; import { IconWrapper } from '@/components/IconWrapper'; -import { Icon } from '@/components/Icon/Icon'; -import type { IconName } from '@/components/Icon/Icon.types'; +import { Icon } from '@/components/Icon'; +import type { IconName } from '@/components/Icon'; import type { HorizontalDirection } from '@/types'; export const Dropdown = (props: DropdownMenu.DropdownMenuProps) => ( diff --git a/src/components/FileTabs/FileTabs.tsx b/src/components/FileTabs/FileTabs.tsx index f1ed98ff0..1fb644b15 100644 --- a/src/components/FileTabs/FileTabs.tsx +++ b/src/components/FileTabs/FileTabs.tsx @@ -14,8 +14,7 @@ import { import { styled } from 'styled-components'; import { Icon } from '@/components/Icon'; import { IconButton } from '@/components/IconButton'; - -import { IconName } from '../Icon/Icon.types'; +import type { IconName } from '@/components/Icon/Icon.types'; // TODO: Check if react-sortablejs has ESM version import ReactSortableModule from 'react-sortablejs/dist/index.js'; diff --git a/src/components/Flyout/Flyout.stories.tsx b/src/components/Flyout/Flyout.stories.tsx index fd7efde25..8cd76040e 100644 --- a/src/components/Flyout/Flyout.stories.tsx +++ b/src/components/Flyout/Flyout.stories.tsx @@ -1,6 +1,8 @@ import React from 'react'; import { Meta, StoryObj } from '@storybook/react-vite'; -import { Button, Link, Text } from '..'; +import { Button } from '@/components/Button'; +import { Link } from '@/components/Link'; +import { Text } from '@/components/Typography/Text'; import { Flyout, FlyoutProps } from '@/components/Flyout'; interface FlyoutExampleProps extends FlyoutProps { diff --git a/src/components/Flyout/Flyout.test.tsx b/src/components/Flyout/Flyout.test.tsx index b30c68e7d..df01b8f4a 100644 --- a/src/components/Flyout/Flyout.test.tsx +++ b/src/components/Flyout/Flyout.test.tsx @@ -1,7 +1,7 @@ import { fireEvent } from '@testing-library/react'; import { Flyout } from '@/components/Flyout'; import { renderCUI } from '@/utils/test-utils'; -import { Button } from '..'; +import { Button } from '@/components/Button'; import { DialogProps } from '@radix-ui/react-dialog'; interface Props extends DialogProps { diff --git a/src/components/Flyout/Flyout.tsx b/src/components/Flyout/Flyout.tsx index 002e76ac8..969aca253 100644 --- a/src/components/Flyout/Flyout.tsx +++ b/src/components/Flyout/Flyout.tsx @@ -19,7 +19,6 @@ import { Icon } from '@/components/Icon'; import { Separator } from '@/components/Separator'; import { Spacer } from '@/components/Spacer'; import { styled } from 'styled-components'; -// TODO: Improve api for Common components, types, etc import { CrossButton } from '@/components/Common'; import { keyframes } from 'styled-components'; import type { diff --git a/src/components/FormContainer/Error.tsx b/src/components/FormContainer/Error.tsx new file mode 100644 index 000000000..ad19e40c0 --- /dev/null +++ b/src/components/FormContainer/Error.tsx @@ -0,0 +1,8 @@ +import { styled } from 'styled-components'; + +export const Error = styled.div` + ${({ theme }) => ` + font: ${theme.click.field.typography.label.error}; + color: ${theme.click.field.color.label.error}; +`}; +`; diff --git a/src/components/FormContainer/FormElementContainer.tsx b/src/components/FormContainer/FormElementContainer.tsx new file mode 100644 index 000000000..4883a3f1d --- /dev/null +++ b/src/components/FormContainer/FormElementContainer.tsx @@ -0,0 +1,12 @@ +import { styled } from 'styled-components'; + +export const FormElementContainer = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + width: 100%; + width: -webkit-fill-available; + width: fill-available; + width: stretch; + gap: ${({ theme }) => theme.click.field.space.gap}; +`; diff --git a/src/components/FormContainer/FormRoot.tsx b/src/components/FormContainer/FormRoot.tsx new file mode 100644 index 000000000..b8236ca69 --- /dev/null +++ b/src/components/FormContainer/FormRoot.tsx @@ -0,0 +1,37 @@ +import { styled } from 'styled-components'; + +export const FormRoot = styled.div<{ + $orientation?: 'horizontal' | 'vertical'; + $dir?: 'start' | 'end'; + $addLabelPadding?: boolean; +}>` + display: flex; + width: 100%; + gap: ${({ theme }) => theme.click.field.space.gap}; + ${({ theme, $orientation = 'vertical', $dir = 'start', $addLabelPadding = false }) => ` + flex-direction: ${ + $orientation === 'horizontal' + ? $dir === 'start' + ? 'row-reverse' + : 'row' + : $dir === 'start' + ? 'column-reverse' + : 'column' + }; + align-items: flex-start; + ${ + $addLabelPadding && $orientation === 'horizontal' + ? ` + label { + padding-top: calc(${theme.click.field.space.y} + 1px); + line-height: 1lh; + } + ` + : '' + } + `} + * { + box-shadow: none; + outline: none; + } +`; diff --git a/src/components/GenericMenu/GenericMenu.test.tsx b/src/components/GenericMenu/GenericMenu.test.tsx index c972d8f9a..86b7ea7bc 100644 --- a/src/components/GenericMenu/GenericMenu.test.tsx +++ b/src/components/GenericMenu/GenericMenu.test.tsx @@ -6,7 +6,7 @@ import { GenericPopoverMenuPanel, GenericMenuItem, } from './GenericMenu'; -import { themes } from '@/theme'; +import { themes } from '@/theme/theme.core'; const renderWithTheme = (component: React.ReactNode) => { return render({component}); diff --git a/src/components/Grid/Grid.stories.tsx b/src/components/Grid/Grid.stories.tsx index db7026bbd..1acf4b900 100644 --- a/src/components/Grid/Grid.stories.tsx +++ b/src/components/Grid/Grid.stories.tsx @@ -1,5 +1,10 @@ import { useCallback, useEffect, useState } from 'react'; -import { CellProps, GridContextMenuItemProps, SelectedRegion, SelectionFocus } from '..'; +import { + CellProps, + GridContextMenuItemProps, + SelectedRegion, + SelectionFocus, +} from './types'; import { Grid as CUIGrid } from '@/components/Grid'; const Cell: CellProps = ({ diff --git a/src/components/GridContainer/GridContainer.stories.tsx b/src/components/GridContainer/GridContainer.stories.tsx index 4c155cd6c..93a92f431 100644 --- a/src/components/GridContainer/GridContainer.stories.tsx +++ b/src/components/GridContainer/GridContainer.stories.tsx @@ -1,6 +1,6 @@ import { Meta, StoryObj } from '@storybook/react-vite'; import { GridContainer } from '@/components/GridContainer'; -import { Text } from '..'; +import { Text } from '@/components/Typography/Text'; import { styled } from 'styled-components'; const GridCenter = styled.div` diff --git a/src/components/HoverCard/HoverCard.stories.tsx b/src/components/HoverCard/HoverCard.stories.tsx index 8be2e497f..49ed893ec 100644 --- a/src/components/HoverCard/HoverCard.stories.tsx +++ b/src/components/HoverCard/HoverCard.stories.tsx @@ -1,9 +1,9 @@ import React from 'react'; import { Meta, StoryObj } from '@storybook/react-vite'; -import { Checkbox } from '../Checkbox'; -import { Spacer } from '../Spacer'; -import { Text } from '../Typography/Text/Text'; -import { Title } from '../Typography/Title/Title'; +import { Checkbox } from '@/components/Checkbox'; +import { Spacer } from '@/components/Spacer'; +import { Text } from '@/components/Typography/Text'; +import { Title } from '@/components/Typography/Title'; import { HoverCard } from '@/components/HoverCard'; interface HoverCardExampleProps { diff --git a/src/components/HoverCard/HoverCard.tsx b/src/components/HoverCard/HoverCard.tsx index a20da384e..77d27d7d1 100644 --- a/src/components/HoverCard/HoverCard.tsx +++ b/src/components/HoverCard/HoverCard.tsx @@ -1,6 +1,6 @@ import * as RadixHoverCard from '@radix-ui/react-hover-card'; import { ReactNode } from 'react'; -import { Arrow, GenericPopoverMenuPanel } from '../GenericMenu'; +import { Arrow, GenericPopoverMenuPanel } from '@/components/GenericMenu'; import { styled } from 'styled-components'; import Popover_Arrow from '@/components/Assets/Icons/Popover-Arrow'; diff --git a/src/components/Icon/Icon.stories.tsx b/src/components/Icon/Icon.stories.tsx index be9f666b8..6eb885bc0 100644 --- a/src/components/Icon/Icon.stories.tsx +++ b/src/components/Icon/Icon.stories.tsx @@ -3,17 +3,16 @@ import LogosLight from '@/components/Assets/Logos/system/LogosLight'; import FlagsLight from '@/components/Assets/Flags/system/FlagsLight'; import PaymentsLight from '@/components/Assets/Payments/system/PaymentsLight'; import { Icon } from '@/components/Icon'; -import { IconName } from '@/components/Icon/Icon.types'; +import { IconName, IconProps } from '@/components/Icon/Icon.types'; import { ICONS_MAP } from '@/components/Icon/IconCommon'; -import { IconProps } from '@/components/Icon/Icon.types'; import { Container } from '@/components/Container'; import { styled } from 'styled-components'; import { useState } from 'react'; import { SearchField } from '@/components/Input/SearchField'; -import { Title } from '@/components/Typography/Title/Title'; +import { Title } from '@/components/Typography/Title'; import { Panel } from '@/components/Panel'; -import { Text } from '@/components/Typography/Text/Text'; -import { GridContainer } from '../GridContainer/'; +import { Text } from '@/components/Typography/Text'; +import { GridContainer } from '@/components/GridContainer'; import { Spacer } from '@/components/Spacer'; const IconNames = Object.keys(ICONS_MAP); diff --git a/src/components/Icon/Icon.tsx b/src/components/Icon/Icon.tsx index e787962bb..d1f9e008b 100644 --- a/src/components/Icon/Icon.tsx +++ b/src/components/Icon/Icon.tsx @@ -1,6 +1,6 @@ import { styled } from 'styled-components'; +import type { AssetSize } from '@/types'; import { IconName, IconProps, IconState, ImageType } from './Icon.types'; -import { IconSize } from '@/types'; import { ICONS_MAP } from '@/components/Icon/IconCommon'; import { Flag } from '@/components/Assets/Flags/system/Flag'; import FlagsLight from '@/components/Assets/Flags/system/FlagsLight'; @@ -46,7 +46,7 @@ const SvgWrapper = styled.div<{ $color?: string; $width?: number | string; $height?: number | string; - $size?: IconSize; + $size?: AssetSize; state?: IconState; }>` display: flex; diff --git a/src/components/Icon/Icon.types.ts b/src/components/Icon/Icon.types.ts index cd4a361f4..d46652845 100644 --- a/src/components/Icon/Icon.types.ts +++ b/src/components/Icon/Icon.types.ts @@ -2,7 +2,7 @@ import { SVGAttributes } from 'react'; import { LogoProps, LogoName } from '@/components/Assets/Logos/system/types'; import { FlagName, FlagProps } from '@/components/Assets/Flags/system/types'; import { PaymentProps, PaymentName } from '@/components/Assets/Payments/system/types'; -import { IconSize } from '@/types'; +import type { AssetSize } from '@/types'; import { ICON_NAMES } from './IconCommon'; export type IconState = 'default' | 'success' | 'warning' | 'danger' | 'info'; @@ -16,7 +16,7 @@ export interface IconProps extends SVGAttributes { /** The color of the icon */ color?: string; /** The size of the icon */ - size?: IconSize; + size?: AssetSize; /** The visual state of the icon */ state?: IconState; } diff --git a/src/components/Icon/SvgImageElement.tsx b/src/components/Icon/SvgImageElement.tsx index d8c1494c3..0937172a3 100644 --- a/src/components/Icon/SvgImageElement.tsx +++ b/src/components/Icon/SvgImageElement.tsx @@ -1,8 +1,8 @@ import { styled } from 'styled-components'; -import type { IconSize } from '@/types'; +import type { AssetSize } from '@/types'; export const SvgImageElement = styled.svg<{ - $size?: IconSize; + $size?: AssetSize; }>` display: flex; align-items: center; diff --git a/src/components/IconButton/IconButton.types.ts b/src/components/IconButton/IconButton.types.ts index 81145c265..0eb574d9c 100644 --- a/src/components/IconButton/IconButton.types.ts +++ b/src/components/IconButton/IconButton.types.ts @@ -1,5 +1,5 @@ import { HTMLAttributes } from 'react'; -import { IconName } from '@/components/Icon'; +import type { IconName } from '@/components/Icon'; export type IconButtonSize = 'default' | 'sm' | 'xs'; diff --git a/src/components/IconWrapper/IconWrapper.types.ts b/src/components/IconWrapper/IconWrapper.types.ts index 91e4b1e97..d112a631c 100644 --- a/src/components/IconWrapper/IconWrapper.types.ts +++ b/src/components/IconWrapper/IconWrapper.types.ts @@ -1,14 +1,12 @@ import { ReactNode } from 'react'; - -import type { HorizontalDirection } from '@/types'; +import type { HorizontalDirection, AssetSize } from '@/types'; import type { ImageName } from '@/components/Icon/Icon.types'; -import type { IconSize } from '@/types'; import type { GapOptions } from '@/components/Container'; export interface IconWrapperProps { icon?: ImageName; iconDir?: HorizontalDirection; - size?: IconSize; + size?: AssetSize; width?: number | string; height?: number | string; children: ReactNode; diff --git a/src/components/Input/InputWrapper.tsx b/src/components/Input/InputWrapper.tsx index 7cb330086..14eb03685 100644 --- a/src/components/Input/InputWrapper.tsx +++ b/src/components/Input/InputWrapper.tsx @@ -1,4 +1,3 @@ -// TODO: Improve api for Common components, types, etc import { Error, FormElementContainer, FormRoot } from '@/components/Common'; import { Label } from '@/components/Label'; import { styled } from 'styled-components'; diff --git a/src/components/Input/NumberField.stories.tsx b/src/components/Input/NumberField.stories.tsx index bb1025df9..4da17911a 100644 --- a/src/components/Input/NumberField.stories.tsx +++ b/src/components/Input/NumberField.stories.tsx @@ -1,7 +1,7 @@ import { Meta, StoryObj } from '@storybook/react-vite'; import { useEffect, useState } from 'react'; import { NumberField, NumberFieldProps } from './NumberField'; -import { Container } from '../Container'; +import { Container } from '@/components/Container'; const meta: Meta = { component: NumberField, diff --git a/src/components/Input/SearchField.stories.tsx b/src/components/Input/SearchField.stories.tsx index 6e35d988a..5298b9b53 100644 --- a/src/components/Input/SearchField.stories.tsx +++ b/src/components/Input/SearchField.stories.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react'; import { Meta, StoryObj } from '@storybook/react-vite'; -import { Container } from '../Container'; +import { Container } from '@/components/Container'; import { SearchField } from './SearchField'; diff --git a/src/components/Input/TextArea.stories.tsx b/src/components/Input/TextArea.stories.tsx index f8ebc4577..ddef71c6a 100644 --- a/src/components/Input/TextArea.stories.tsx +++ b/src/components/Input/TextArea.stories.tsx @@ -1,7 +1,7 @@ import { Meta, StoryObj } from '@storybook/react-vite'; import { ChangeEvent, useEffect, useState } from 'react'; import { TextAreaField, TextAreaFieldProps } from './TextArea'; -import { Container } from '../Container'; +import { Container } from '@/components/Container'; const meta: Meta = { component: TextAreaField, diff --git a/src/components/Link/Link.tsx b/src/components/Link/Link.tsx index b6ba696b0..8da73c4dc 100644 --- a/src/components/Link/Link.tsx +++ b/src/components/Link/Link.tsx @@ -10,7 +10,7 @@ import { Icon } from '@/components/Icon'; import type { IconName } from '@/components/Icon/Icon.types'; import { styled } from 'styled-components'; import { linkStyles } from './common'; -import { TextSize, TextWeight } from '@/components/Common'; +import type { TextSize, TextWeight } from '@/components/Typography'; export interface LinkProps { /** The font size of the link text */ diff --git a/src/components/Link/Link.types.ts b/src/components/Link/Link.types.ts index 1bce5fce8..3ab4082c9 100644 --- a/src/components/Link/Link.types.ts +++ b/src/components/Link/Link.types.ts @@ -1,6 +1,6 @@ import { ElementType, ReactEventHandler } from 'react'; import type { IconName } from '@/components/Icon/Icon.types'; -import type { TextSize, TextWeight } from '@/components/Common'; +import type { TextSize, TextWeight } from '@/components/Typography'; export interface LinkProps { size?: TextSize; diff --git a/src/components/Link/common.ts b/src/components/Link/common.ts index eff1678b0..dab8de843 100644 --- a/src/components/Link/common.ts +++ b/src/components/Link/common.ts @@ -1,5 +1,5 @@ import { css } from 'styled-components'; -import { TextSize, TextWeight } from '../Common'; +import type { TextSize, TextWeight } from '@/components/Typography'; export type StyledLinkProps = { $size: TextSize; $weight: TextWeight }; diff --git a/src/components/MultiAccordion/MultiAccordion.tsx b/src/components/MultiAccordion/MultiAccordion.tsx index 37fc1d2e8..a5bf375d8 100644 --- a/src/components/MultiAccordion/MultiAccordion.tsx +++ b/src/components/MultiAccordion/MultiAccordion.tsx @@ -1,7 +1,7 @@ import * as RadixAccordion from '@radix-ui/react-accordion'; import { styled } from 'styled-components'; +import type { AssetSize } from '@/types'; import { Icon, type IconName } from '@/components/Icon'; -import type { IconSize } from '@/types'; import { Container } from '@/components/Container'; import { Spacer } from '@/components/Spacer'; @@ -100,7 +100,7 @@ interface MultiAccordionItemProps extends Omit< /** Optional icon to display next to the title */ icon?: IconName; /** Size of the optional icon */ - iconSize?: IconSize; + iconSize?: AssetSize; /** Gap size between the header and content */ gap?: SpacerSizeType; /** Whether this item is marked as completed */ diff --git a/src/components/Pagination/Pagination.tsx b/src/components/Pagination/Pagination.tsx index 2d1a82779..fb3507159 100644 --- a/src/components/Pagination/Pagination.tsx +++ b/src/components/Pagination/Pagination.tsx @@ -5,7 +5,7 @@ import { useCallback, useRef, } from 'react'; -import { Container, ContainerProps } from '@/components/Container'; +import { Container, type ContainerProps } from '@/components/Container'; import { IconButton } from '@/components/IconButton'; import { NumberField } from '@/components/Input'; import { Select } from '@/components/Select'; diff --git a/src/components/Pagination/Pagination.types.ts b/src/components/Pagination/Pagination.types.ts index c5cbe3318..7f6d6d56e 100644 --- a/src/components/Pagination/Pagination.types.ts +++ b/src/components/Pagination/Pagination.types.ts @@ -1,5 +1,5 @@ import { FocusEventHandler, MouseEventHandler } from 'react'; -import { ContainerProps } from '@/components/Container'; +import type { ContainerProps } from '@/components/Container'; export interface PaginationProps extends Omit< ContainerProps<'div'>, diff --git a/src/components/Panel/Panel.stories.tsx b/src/components/Panel/Panel.stories.tsx index ebcce20db..2e9db90ef 100644 --- a/src/components/Panel/Panel.stories.tsx +++ b/src/components/Panel/Panel.stories.tsx @@ -1,7 +1,7 @@ import { Meta, StoryObj } from '@storybook/react-vite'; import { Panel } from '@/components/Panel'; -import { Text } from '../Typography/Text/Text'; -import { Title } from '../Typography/Title/Title'; +import { Text } from '@/components/Typography/Text'; +import { Title } from '@/components/Typography/Title'; const meta: Meta = { component: Panel, diff --git a/src/components/Panel/Panel.tsx b/src/components/Panel/Panel.tsx index 457a31953..6da031f1d 100644 --- a/src/components/Panel/Panel.tsx +++ b/src/components/Panel/Panel.tsx @@ -1,5 +1,5 @@ -import type { CursorOptions } from '@/components/Common'; import type { Orientation } from '@/types'; +import type { CursorOptions } from './Panel.types'; import { HTMLAttributes } from 'react'; import { styled } from 'styled-components'; diff --git a/src/components/Panel/Panel.types.ts b/src/components/Panel/Panel.types.ts index 283807bf5..533c0c900 100644 --- a/src/components/Panel/Panel.types.ts +++ b/src/components/Panel/Panel.types.ts @@ -1,4 +1,3 @@ -import type { CursorOptions } from '@/components/Common'; import type { Orientation } from '@/types'; import { HTMLAttributes, ReactNode } from 'react'; @@ -6,6 +5,44 @@ export type PanelPadding = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'; export type PanelColor = 'default' | 'muted' | 'transparent'; export type PanelRadii = 'none' | 'sm' | 'md' | 'lg'; +export type CursorOptions = + | 'auto' + | 'default' + | 'none' + | 'context-menu' + | 'help' + | 'pointer' + | 'progress' + | 'wait' + | 'cell' + | 'crosshair' + | 'text' + | 'vertical-text' + | 'alias' + | 'copy' + | 'move' + | 'no-drop' + | 'not-allowed' + | 'grab' + | 'grabbing' + | 'e-resize' + | 'n-resize' + | 'ne-resize' + | 'nw-resize' + | 's-resize' + | 'se-resize' + | 'sw-resize' + | 'w-resize' + | 'ew-resize' + | 'ns-resize' + | 'nesw-resize' + | 'nwse-resize' + | 'col-resize' + | 'row-resize' + | 'all-scroll' + | 'zoom-in' + | 'zoom-out'; + export interface PanelProps extends HTMLAttributes { alignItems?: 'start' | 'center' | 'end'; children?: ReactNode; diff --git a/src/components/Popover/Popover.stories.tsx b/src/components/Popover/Popover.stories.tsx index f925cb98f..a08080e6a 100644 --- a/src/components/Popover/Popover.stories.tsx +++ b/src/components/Popover/Popover.stories.tsx @@ -1,7 +1,8 @@ import React from 'react'; import { Meta, StoryObj } from '@storybook/react-vite'; -import { Button, Checkbox } from '..'; -import { GridCenter } from '../Common'; +import { Button } from '@/components/Button'; +import { Checkbox } from '@/components/Checkbox'; +import { GridCenter } from '@/components/Common'; import { Text, Title } from '@/components/Typography'; import { Popover } from '@/components/Popover'; diff --git a/src/components/Popover/Popover.tsx b/src/components/Popover/Popover.tsx index 6bf84b503..caa1b39c6 100644 --- a/src/components/Popover/Popover.tsx +++ b/src/components/Popover/Popover.tsx @@ -3,7 +3,6 @@ import { Arrow, GenericMenuPanel } from '@/components/GenericMenu'; import { styled } from 'styled-components'; import { ReactNode } from 'react'; import { Icon } from '@/components/Icon'; -// TODO: Improve api for Common components, types, etc import { EmptyButton } from '@/components/Common'; import Popover_Arrow from '@/components/Assets/Icons/Popover-Arrow'; diff --git a/src/components/RadioGroup/RadioGroup.tsx b/src/components/RadioGroup/RadioGroup.tsx index 770d2d536..7c0fa8202 100644 --- a/src/components/RadioGroup/RadioGroup.tsx +++ b/src/components/RadioGroup/RadioGroup.tsx @@ -3,7 +3,6 @@ import { HTMLAttributes, ReactNode, useId } from 'react'; import { styled } from 'styled-components'; import { GenericLabel } from '@/components/GenericLabel'; import { Label } from '@/components/Label'; -// TODO: Improve api for Common components, types, etc import { Error, FormElementContainer, FormRoot } from '@/components/Common'; export interface RadioGroupProps extends Omit { diff --git a/src/components/Select/CheckboxMultiSelect.stories.tsx b/src/components/Select/CheckboxMultiSelect.stories.tsx index d1aa0aa40..8dc9f4647 100644 --- a/src/components/Select/CheckboxMultiSelect.stories.tsx +++ b/src/components/Select/CheckboxMultiSelect.stories.tsx @@ -2,12 +2,12 @@ import { useEffect, useState } from 'react'; import { Meta, StoryObj } from '@storybook/react-vite'; -import { Panel } from '../Panel'; -import { Text } from '../Typography/Text/Text'; +import { Panel } from '@/components/Panel'; +import { Text } from '@/components/Typography/Text'; import { CheckboxMultiSelect } from './CheckboxMultiSelect'; import { selectOptions, selectOptionsLong } from './selectOptions'; -import { Spacer } from '../Spacer'; +import { Spacer } from '@/components/Spacer'; const meta: Meta = { component: CheckboxMultiSelect, diff --git a/src/components/Select/MultiSelect.stories.tsx b/src/components/Select/MultiSelect.stories.tsx index 2a2cc1071..492c0f831 100644 --- a/src/components/Select/MultiSelect.stories.tsx +++ b/src/components/Select/MultiSelect.stories.tsx @@ -2,8 +2,8 @@ import { Meta, StoryObj } from '@storybook/react-vite'; import { MultiSelect } from './MultiSelect'; import { selectOptions } from './selectOptions'; import { useEffect, useState } from 'react'; -import { Container } from '../Container'; -import { Panel } from '../Panel'; +import { Container } from '@/components/Container'; +import { Panel } from '@/components/Panel'; const meta: Meta = { component: MultiSelect, diff --git a/src/components/Select/common/InternalSelect.tsx b/src/components/Select/common/InternalSelect.tsx index ac566b083..7682f2f18 100644 --- a/src/components/Select/common/InternalSelect.tsx +++ b/src/components/Select/common/InternalSelect.tsx @@ -15,6 +15,7 @@ import { useState, } from 'react'; import { + NoAvailableOptionsFactoryProps, SelectContainerProps, SelectGroupProps, SelectItemObject, @@ -64,11 +65,6 @@ type CallbackProps = SelectItemObject & { nodeProps: SelectItemProps; }; -export interface NoAvailableOptionsFactoryProps { - search: string; - close: () => void; -} - interface NoOptionsDisplayProps { allowCreateOption: boolean; search: string; diff --git a/src/components/Select/common/types.ts b/src/components/Select/common/types.ts index 4a613a556..ae66e5f2c 100644 --- a/src/components/Select/common/types.ts +++ b/src/components/Select/common/types.ts @@ -2,7 +2,11 @@ import { HTMLAttributes, KeyboardEvent, MouseEvent, ReactNode } from 'react'; import type { HorizontalDirection } from '@/types'; import type { ImageName } from '@/components/Icon/Icon.types'; import { PopoverProps } from '@radix-ui/react-popover'; -import { NoAvailableOptionsFactoryProps } from '@/components/Select/common/InternalSelect'; + +export interface NoAvailableOptionsFactoryProps { + search: string; + close: () => void; +} declare type DivProps = HTMLAttributes; diff --git a/src/components/Switch/Switch.tsx b/src/components/Switch/Switch.tsx index 740b7b954..3fcf4014e 100644 --- a/src/components/Switch/Switch.tsx +++ b/src/components/Switch/Switch.tsx @@ -4,7 +4,7 @@ import { styled } from 'styled-components'; import { FormRoot } from '@/components/Common'; import { GenericLabel } from '@/components/GenericLabel'; import { SwitchProps } from './Switch.types'; -import { Theme } from '@/theme'; +import type { Theme } from '@/theme/theme.types'; interface ThumbProps { $checked: boolean; diff --git a/src/components/Tabs/FullWidthTabs.stories.tsx b/src/components/Tabs/FullWidthTabs.stories.tsx index c1d60b4e6..f47c04c9f 100644 --- a/src/components/Tabs/FullWidthTabs.stories.tsx +++ b/src/components/Tabs/FullWidthTabs.stories.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { Meta, StoryObj } from '@storybook/react-vite'; import { Spacer } from '@/components/Spacer'; import { FullWidthTabs } from '@/components/Tabs'; -import { Text } from '@/components/Typography/Text/Text'; +import { Text } from '@/components/Typography/Text'; const meta: Meta = { component: FullWidthTabs, diff --git a/src/components/Tabs/Tabs.stories.tsx b/src/components/Tabs/Tabs.stories.tsx index 1487d6b95..26c44580d 100644 --- a/src/components/Tabs/Tabs.stories.tsx +++ b/src/components/Tabs/Tabs.stories.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { Meta, StoryObj } from '@storybook/react-vite'; import { Spacer } from '@/components/Spacer'; import { Tabs } from '@/components/Tabs'; -import { Text } from '@/components/Typography/Text/Text'; +import { Text } from '@/components/Typography/Text'; const meta: Meta = { component: Tabs, diff --git a/src/components/Toast/Toast.tsx b/src/components/Toast/Toast.tsx index 5fc8c4b3f..f732b65c6 100644 --- a/src/components/Toast/Toast.tsx +++ b/src/components/Toast/Toast.tsx @@ -2,7 +2,7 @@ import { createContext, useEffect, useState } from 'react'; import * as RadixUIToast from '@radix-ui/react-toast'; import { keyframes, styled } from 'styled-components'; import { toastsEventEmitter } from './toastEmitter'; -import { Icon, IconName } from '@/components/Icon'; +import { Icon, type IconName, type IconProps } from '@/components/Icon'; import { IconButton } from '@/components/IconButton'; import { Button } from '@/components/Button'; import { ToastContextProps, ToastProps, ToastAlignment, ToastType } from './Toast.types'; @@ -11,7 +11,12 @@ export const ToastContext = createContext({ createToast: () => null, }); -const ToastIcon = styled(Icon)<{ $type?: ToastType }>` +// Lazy wrapper to avoid circular dependency issues at module load time +const ToastIconWrapper = (props: IconProps & { $type?: ToastType }) => ( + +); + +const ToastIcon = styled(ToastIconWrapper)<{ $type?: ToastType }>` ${({ theme, $type = 'default' }) => ` width: ${theme.click.toast.icon.size.width}; height: ${theme.click.toast.icon.size.height}; diff --git a/src/components/Toast/Toast.types.ts b/src/components/Toast/Toast.types.ts index d17f899c2..8b6b8b06d 100644 --- a/src/components/Toast/Toast.types.ts +++ b/src/components/Toast/Toast.types.ts @@ -1,6 +1,6 @@ import { ReactNode } from 'react'; import * as RadixUIToast from '@radix-ui/react-toast'; -import { ButtonProps } from '@/components/Button'; +import type { ButtonProps } from '@/components/Button/Button.types'; export interface ToastContextProps { createToast: (toast: ToastProps, align?: ToastAlignment) => void; diff --git a/src/components/Tooltip/Tooltip.stories.tsx b/src/components/Tooltip/Tooltip.stories.tsx index 59a1cfabf..8ab11a133 100644 --- a/src/components/Tooltip/Tooltip.stories.tsx +++ b/src/components/Tooltip/Tooltip.stories.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Meta, StoryObj } from '@storybook/react-vite'; import { Tooltip } from '@/components/Tooltip'; -import { Text } from '..'; +import { Text } from '@/components/Typography/Text'; const meta: Meta = { component: Tooltip, diff --git a/src/components/Tooltip/Tooltip.test.tsx b/src/components/Tooltip/Tooltip.test.tsx index 828bbf1fe..386d9fb3d 100644 --- a/src/components/Tooltip/Tooltip.test.tsx +++ b/src/components/Tooltip/Tooltip.test.tsx @@ -1,5 +1,5 @@ import { TooltipProps } from '@/components/Tooltip'; -import { Tooltip } from '..'; +import { Tooltip } from './Tooltip'; import { waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { renderCUI } from '@/utils/test-utils'; diff --git a/src/components/Typography/Text/Text.tsx b/src/components/Typography/Text/Text.tsx index 7fb8acff7..35fc854b0 100644 --- a/src/components/Typography/Text/Text.tsx +++ b/src/components/Typography/Text/Text.tsx @@ -6,8 +6,9 @@ import { forwardRef, } from 'react'; import { styled } from 'styled-components'; -import { TextSize, TextWeight } from '@/components/Common'; +export type TextSize = 'xs' | 'sm' | 'md' | 'lg'; +export type TextWeight = 'normal' | 'medium' | 'semibold' | 'bold' | 'mono'; export type TextAlignment = 'left' | 'center' | 'right'; export type TextColor = 'default' | 'muted' | 'danger' | 'disabled'; diff --git a/src/components/Typography/Text/index.ts b/src/components/Typography/Text/index.ts index 90a130d87..3f9660567 100644 --- a/src/components/Typography/Text/index.ts +++ b/src/components/Typography/Text/index.ts @@ -1,2 +1,2 @@ export { Text } from './Text'; -export type { TextProps, TextAlignment, TextColor } from './Text'; +export type { TextProps, TextAlignment, TextColor, TextSize, TextWeight } from './Text'; diff --git a/src/components/Typography/index.ts b/src/components/Typography/index.ts index fba1f1282..1f93dc7aa 100644 --- a/src/components/Typography/index.ts +++ b/src/components/Typography/index.ts @@ -1,4 +1,4 @@ export { Text } from './Text'; export { Title } from './Title'; -export type { TextAlignment, TextColor, TextProps } from './Text'; +export type { TextAlignment, TextColor, TextProps, TextSize, TextWeight } from './Text'; diff --git a/src/components/VerticalStepper/VerticalStepper.stories.tsx b/src/components/VerticalStepper/VerticalStepper.stories.tsx index f8f2b0391..7835ad695 100644 --- a/src/components/VerticalStepper/VerticalStepper.stories.tsx +++ b/src/components/VerticalStepper/VerticalStepper.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Meta, StoryObj } from '@storybook/react-vite'; -import { Text } from '..'; +import { Text } from '@/components/Typography/Text'; import { VerticalStepper } from '@/components/VerticalStepper'; const meta: Meta = { diff --git a/src/components/index.ts b/src/components/index.ts deleted file mode 100644 index 5c14f1f52..000000000 --- a/src/components/index.ts +++ /dev/null @@ -1,83 +0,0 @@ -export * from '@/components/types'; - -export { Icon } from '@/components/Icon'; -export { IconButton } from '@/components/IconButton'; -export { Label } from '@/components/Label'; -export { GenericLabel } from '@/components/GenericLabel'; -export { Dropdown } from '@/components/Dropdown'; - -export { Accordion } from '@/components/Accordion'; -export { - Alert, - DangerAlert, - InfoAlert, - WarningAlert, - SuccessAlert, -} from '@/components/Alert'; -export { AutoComplete } from '@/components/AutoComplete'; -export { Avatar } from '@/components/Avatar'; -export { Badge } from '@/components/Badge'; -export { BigStat } from '@/components/BigStat'; -export { ButtonGroup } from '@/components/ButtonGroup'; -export { Button } from '@/components/Button'; -export { CardHorizontal } from '@/components/CardHorizontal'; -export { CardPrimary } from '@/components/CardPrimary'; -export { CardPromotion } from '@/components/CardPromotion'; -export { CardSecondary } from '@/components/CardSecondary'; -export { Checkbox } from '@/components/Checkbox'; -export { CodeBlock } from '@/components/CodeBlock'; -export { ConfirmationDialog } from '@/components/ConfirmationDialog'; -export { ContextMenu } from '@/components/ContextMenu'; -export { Container } from '@/components/Container'; -export { DateDetails } from '@/components/DateDetails'; -export { DatePicker } from '@/components/DatePicker'; -export { DateRangePicker } from '@/components/DatePicker/DateRangePicker'; -export { getPredefinedMonthsForDateRangePicker } from '@/components/DatePicker/utils'; -export { Dialog } from '@/components/Dialog'; -export { EllipsisContent } from '@/components/EllipsisContent'; -export { FileUpload } from '@/components/FileUpload'; -export { FileMultiUpload } from '@/components/FileUpload'; -export { Flyout } from '@/components/Flyout'; -export { FormContainer } from '@/components/FormContainer'; -export { GridContainer } from '@/components/GridContainer'; -export { InlineCodeBlock } from '@/components/CodeBlock/InlineCodeBlock'; -export { Flag as Flags } from '@/components/Assets/Flags/system/Flag'; -export { Grid } from '@/components/Grid'; -export { HoverCard } from '@/components/HoverCard'; -export { Link } from '@/components/Link/Link'; -export { linkStyles } from '@/components/Link/common'; -export { Logo } from '@/components/Assets/Logos/system/Logo'; -export { NumberField } from '@/components/Input/NumberField'; -export { PasswordField } from '@/components/Input/PasswordField'; -export { Popover } from '@/components/Popover'; -export { Pagination } from '@/components/Pagination'; -export { Panel } from '@/components/Panel'; -export { ProgressBar } from '@/components/ProgressBar'; -export { RadioGroup } from '@/components/RadioGroup/RadioGroup'; -export { SearchField } from '@/components/Input/SearchField'; -export { Select } from '@/components/Select/SingleSelect'; -export { MultiSelect } from '@/components/Select/MultiSelect'; -export { CheckboxMultiSelect } from '@/components/Select/CheckboxMultiSelect'; -export { Separator } from '@/components/Separator/Separator'; -// TODO: Sidebar elements can be in the ns Sidebar -// there's no need to keep it separate -export { SidebarNavigationItem } from '@/components/SidebarNavigationItem'; -export { SidebarCollapsibleItem } from '@/components/SidebarCollapsibleItem'; -export { SidebarNavigationTitle } from '@/components/SidebarNavigationTitle'; -export { SidebarCollapsibleTitle } from '@/components/SidebarCollapsibleTitle'; -export { Spacer } from '@/components/Spacer'; -export { SplitButton } from '@/components/SplitButton'; -export { Switch } from '@/components/Switch'; -export { Tabs, FullWidthTabs } from '@/components/Tabs'; -export { FileTabs, FileTabElement } from '@/components/FileTabs'; -export { Table } from '@/components/Table/Table'; -export { Text, Title } from '@/components/Typography'; -export { TextAreaField } from '@/components/Input/TextArea'; -export { TextField } from '@/components/Input/TextField'; -export { Tooltip } from '@/components/Tooltip/Tooltip'; -export { useToast } from '@/components/Toast/useToast'; -export { createToast } from '@/components/Toast/toastEmitter'; -export { User as ProfileIcon } from '@/components/Assets/Icons/User'; -export { VerticalStepper } from '@/components/VerticalStepper'; -export { MultiAccordion } from '@/components/MultiAccordion'; -export { ToastProvider, Toast } from '@/components/Toast'; diff --git a/src/components/types.ts b/src/components/types.ts deleted file mode 100644 index 75b848ed6..000000000 --- a/src/components/types.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { TooltipProps } from './Tooltip'; -import { TitleProps } from './Typography/Title/Title'; -import { TextProps } from './Typography/Text/Text'; -import { TabsProps } from './Tabs'; -import { SpacerProps } from './Spacer'; -import { SidebarNavigationItemProps } from './SidebarNavigationItem'; -import { SelectProps } from './Select/SingleSelect'; -import { SearchFieldProps } from './Input/SearchField'; -import { RadioGroupProps, RadioGroupItemProps } from './RadioGroup'; -import { PopoverProps } from '@radix-ui/react-popover'; -import { PasswordFieldProps } from './Input/PasswordField'; -import { NumberFieldProps } from './Input/NumberField'; -import { LabelProps } from './Label'; -import { HoverCardProps } from '@radix-ui/react-hover-card'; -import { ContainerProps } from './Container'; -import { GridContainerProps } from './GridContainer'; -import { ContextMenuProps } from '@radix-ui/react-context-menu'; -import { CheckboxProps } from './Checkbox'; -import { CardPrimaryProps } from './CardPrimary'; -import { CardSecondaryProps, BadgeState } from './CardSecondary'; -import { ButtonProps, ButtonType } from './Button'; -import { ButtonGroupProps } from './ButtonGroup'; -import { BadgeProps } from './Badge'; -import { AvatarProps } from './Avatar'; -import { AlertProps } from './Alert'; -import { IconButtonProps } from './IconButton'; -export type { IconName, ImageName } from './Icon/Icon.types'; -import { SidebarNavigationTitleProps } from './SidebarNavigationTitle'; -import { SidebarCollapsibleItemProps } from './SidebarCollapsibleItem'; -import { SidebarCollapsibleTitleProps } from './SidebarCollapsibleTitle'; -export type { Menu, SplitButtonProps } from './SplitButton'; -export type { ToastProps } from './Toast'; -export type { SelectOptionListItem } from './Select/common/types'; -export type { MultiSelectProps } from './Select/MultiSelect'; -export type { CheckboxMultiSelectProps } from './Select/CheckboxMultiSelect'; -export type { PanelProps } from './Panel'; -export type { FlyoutProps, FlyoutFooterProps, FlyoutHeaderProps } from './Flyout'; -export type { DialogContentProps } from './Dialog'; -export type { DialogProps, DialogTriggerProps } from '@radix-ui/react-dialog'; -export type { ConfirmationDialogProps } from './ConfirmationDialog'; -export type { FileTabStatusType } from './FileTabs'; -export type { - TableHeaderType, - TableRowType, - TableProps, - TableColumnConfigProps, -} from './Table'; -export type { BigStatProps } from './BigStat'; -export type { TextAreaFieldProps } from './Input/TextArea'; -export type { VerticalStepperProps, VerticalStepProps } from './VerticalStepper'; -export type { CardHorizontalProps } from './CardHorizontal'; -export type { CardPromotionProps } from './CardPromotion'; -export type { ProgressBarProps } from './ProgressBar'; -export type { - GridProps, - CellProps, - SelectedRegion, - SelectionFocus, - SelectionPos, - SelectionAction, - GridContextMenuItemProps, - Rectangle, -} from './Grid/types'; -export type { StyledLinkProps } from './Link/common'; - -export type { DateRange } from './DatePicker/utils'; - -export type States = 'default' | 'active' | 'disabled' | 'error' | 'hover'; -export type HorizontalDirection = 'start' | 'end'; -export type Orientation = 'horizontal' | 'vertical'; -export type { FormContainerProps } from './FormContainer'; -export type { - AutoCompleteProps, - AutoCompleteOptionListItem, - SelectOptionItem, - SelectItemProps, - SelectGroupProps, -} from './AutoComplete'; -export type { PaginationProps } from './Pagination'; -export type { ContextMenuItemProps } from './ContextMenu'; -export type { GenericLabelProps } from './GenericLabel'; -export type { MultiAccordionProps } from './MultiAccordion'; -export type { CheckboxVariants } from './Checkbox'; -export type { CursorOptions } from './Common'; -export type { SelectGroupOptionItem } from './Select/common/types'; - -export type { IconButtonProps }; -export type { AlertProps }; -export type { AvatarProps }; -export type { BadgeProps }; -export type { ButtonGroupProps }; -export type { ButtonProps, ButtonType }; -export type { CardSecondaryProps, BadgeState }; -export type { CardPrimaryProps }; -export type { CheckboxProps }; -export type { ContainerProps }; -export type { ContextMenuProps }; -export type { GridContainerProps }; -export type { HoverCardProps }; -export type { LabelProps }; -export type { NumberFieldProps }; -export type { PasswordFieldProps }; -export type { PopoverProps }; -export type { RadioGroupProps, RadioGroupItemProps }; -export type { SearchFieldProps }; -export type { SelectProps }; -export type { SidebarNavigationItemProps }; -export type { SidebarNavigationTitleProps }; -export type { SidebarCollapsibleItemProps }; -export type { SidebarCollapsibleTitleProps }; -export type { SpacerProps }; -export type { TabsProps }; -export type { TextProps }; -export type { TitleProps }; -export type { TooltipProps }; diff --git a/src/hooks/useInitialTheme.ts b/src/hooks/useInitialTheme.ts index a5bc980dc..7b7c80ef5 100644 --- a/src/hooks/useInitialTheme.ts +++ b/src/hooks/useInitialTheme.ts @@ -1,7 +1,8 @@ 'use client'; import { useState, useEffect } from 'react'; -import { type ThemeName, THEMES } from '@/theme'; +import { THEMES } from '@/theme/theme.core'; +import type { ThemeName } from '@/theme/theme.types'; import { CUI_THEME_STORAGE_KEY } from '@/utils/localStorage'; import { THEME_ATTRIBUTE, getRootElement } from '@/utils/dom'; diff --git a/src/index.ts b/src/index.ts index 41701dfb3..389e545d3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,301 @@ -export * from './components'; -export * from './theme'; -export * from './hooks'; +// ClickHouse Click-UI - Main Library Entry Point +// ================================================ +// This is the primary entry point for the @clickhouse/click-ui package. +// All exports are organized by category for clarity. + +// ================================================ +// Components +// REQUEST: Please keep the types next to the component +// to make it easier to maintain +// ================================================ + +// Accordion +export { Accordion } from './components/Accordion'; + +// Alert +export { + Alert, + DangerAlert, + InfoAlert, + SuccessAlert, + WarningAlert, +} from './components/Alert'; +export type { AlertProps } from './components/Alert'; + +// Assets (Flags, Logos, Icons) +export { Flag as Flags } from './components/Assets/Flags/system/Flag'; +export { Logo } from './components/Assets/Logos/system/Logo'; +export { User as ProfileIcon } from './components/Assets/Icons/User'; + +// AutoComplete +export { AutoComplete } from './components/AutoComplete'; +export type { + AutoCompleteOptionListItem, + AutoCompleteProps, + SelectGroupProps, + SelectItemProps, + SelectOptionItem, +} from './components/AutoComplete'; + +// Avatar +export { Avatar } from './components/Avatar'; +export type { AvatarProps } from './components/Avatar'; + +// Badge +export { Badge } from './components/Badge'; +export type { BadgeProps } from './components/Badge'; + +// BigStat +export { BigStat } from './components/BigStat'; +export type { BigStatProps } from './components/BigStat'; + +// Button +export { Button } from './components/Button'; +export { ButtonGroup } from './components/ButtonGroup'; +export { SplitButton } from './components/SplitButton'; +export type { ButtonGroupProps } from './components/ButtonGroup'; +export type { ButtonProps, ButtonType } from './components/Button'; +export type { Menu, SplitButtonProps } from './components/SplitButton'; + +// Cards +export { CardHorizontal } from './components/CardHorizontal'; +export { CardPrimary } from './components/CardPrimary'; +export { CardPromotion } from './components/CardPromotion'; +export { CardSecondary } from './components/CardSecondary'; +export type { CardHorizontalProps } from './components/CardHorizontal'; +export type { CardPrimaryProps } from './components/CardPrimary'; +export type { CardPromotionProps } from './components/CardPromotion'; +export type { BadgeState, CardSecondaryProps } from './components/CardSecondary'; + +// Checkbox +export { Checkbox } from './components/Checkbox'; +export type { CheckboxProps, CheckboxVariants } from './components/Checkbox'; + +// Code +export { CodeBlock } from './components/CodeBlock'; +export { InlineCodeBlock } from './components/CodeBlock/InlineCodeBlock'; +export type { CodeThemeType } from './components/CodeBlock'; + +// Confirmation Dialog +export { ConfirmationDialog } from './components/ConfirmationDialog'; +export type { ConfirmationDialogProps } from './components/ConfirmationDialog'; + +// Container & Grid +export { Container } from './components/Container'; +export { Grid } from './components/Grid'; +export { GridContainer } from './components/GridContainer'; +export type { ContainerProps } from './components/Container'; +export type { + CellProps, + GridContextMenuItemProps, + GridProps, + Rectangle, + SelectedRegion, + SelectionAction, + SelectionFocus, + SelectionPos, +} from './components/Grid/types'; +export type { GridContainerProps } from './components/GridContainer'; + +// Context Menu +export { ContextMenu } from './components/ContextMenu'; +export type { ContextMenuItemProps } from './components/ContextMenu'; + +// Date Details +export { DateDetails } from './components/DateDetails'; + +// Date Picker +export { DatePicker } from './components/DatePicker'; +export { DateRangePicker } from './components/DatePicker/DateRangePicker'; +export { getPredefinedMonthsForDateRangePicker } from './components/DatePicker/utils'; +export type { DateRange } from './components/DatePicker/utils'; + +// Dialog +export { Dialog } from './components/Dialog'; +export type { DialogContentProps } from './components/Dialog'; + +// Dropdown +export { Dropdown } from './components/Dropdown'; + +// Ellipsis Content +export { EllipsisContent } from './components/EllipsisContent'; + +// File Upload & Tabs +export { FileMultiUpload, FileUpload } from './components/FileUpload'; +export { FileTabs, FileTabElement } from './components/FileTabs'; +export type { FileTabStatusType } from './components/FileTabs'; + +// Flyout +export { Flyout } from './components/Flyout'; +export type { + FlyoutFooterProps, + FlyoutHeaderProps, + FlyoutProps, +} from './components/Flyout'; + +// Form Container +export { FormContainer } from './components/FormContainer'; +export type { FormContainerProps } from './components/FormContainer'; + +// Generic Label +export { GenericLabel } from './components/GenericLabel'; +export type { GenericLabelProps } from './components/GenericLabel'; + +// HoverCard +export { HoverCard } from './components/HoverCard'; + +// Icon +export { Icon } from './components/Icon'; +export { IconButton } from './components/IconButton'; +export type { IconButtonProps } from './components/IconButton'; +export type { ImageName as IconName } from './components/Icon/Icon.types'; + +// Label & Link +export { Label } from './components/Label'; +export { Link } from './components/Link'; +// TODO: This linkStyles require investigation +export { linkStyles } from './components/Link/common'; +export type { LabelProps } from './components/Label'; +export type { StyledLinkProps } from './components/Link/common'; + +// Multi Accordion +export { MultiAccordion } from './components/MultiAccordion'; +export type { MultiAccordionProps } from './components/MultiAccordion'; + +// Navigation +export { SidebarCollapsibleItem } from './components/SidebarCollapsibleItem'; +export { SidebarCollapsibleTitle } from './components/SidebarCollapsibleTitle'; +export { SidebarNavigationItem } from './components/SidebarNavigationItem'; +export { SidebarNavigationTitle } from './components/SidebarNavigationTitle'; +export type { SidebarCollapsibleItemProps } from './components/SidebarCollapsibleItem'; +export type { SidebarCollapsibleTitleProps } from './components/SidebarCollapsibleTitle'; +export type { SidebarNavigationItemProps } from './components/SidebarNavigationItem'; +export type { SidebarNavigationTitleProps } from './components/SidebarNavigationTitle'; + +// Pagination +export { Pagination } from './components/Pagination'; +export type { PaginationProps } from './components/Pagination'; + +// Panel +export { Panel } from './components/Panel'; +export type { PanelProps } from './components/Panel'; + +// Popover +export { Popover } from './components/Popover'; + +// Progress Bar +export { ProgressBar } from './components/ProgressBar'; +export type { ProgressBarProps } from './components/ProgressBar'; + +// Radio Group +export { RadioGroup } from './components/RadioGroup'; +export type { RadioGroupItemProps, RadioGroupProps } from './components/RadioGroup'; + +// Select +export { CheckboxMultiSelect } from './components/Select/CheckboxMultiSelect'; +export { MultiSelect } from './components/Select/MultiSelect'; +export { Select } from './components/Select/SingleSelect'; +export type { CheckboxMultiSelectProps } from './components/Select/CheckboxMultiSelect'; +export type { MultiSelectProps } from './components/Select/MultiSelect'; +export type { + SelectGroupOptionItem, + SelectOptionListItem, +} from './components/Select/common/types'; +export type { SelectProps } from './components/Select/SingleSelect'; + +// Separator +export { Separator } from './components/Separator'; + +// Spacer +export { Spacer } from './components/Spacer'; +export type { SpacerProps } from './components/Spacer'; + +// Switch +export { Switch } from './components/Switch'; + +// Table +export { Table } from './components/Table'; +export type { + TableColumnConfigProps, + TableHeaderType, + TableProps, + TableRowType, +} from './components/Table'; + +// Tabs +export { Tabs, FullWidthTabs } from './components/Tabs'; +export type { TabsProps } from './components/Tabs'; + +// Text Field & Related Inputs +export { NumberField } from './components/Input/NumberField'; +export { PasswordField } from './components/Input/PasswordField'; +export { SearchField } from './components/Input/SearchField'; +export { TextField } from './components/Input/TextField'; +export { TextAreaField } from './components/Input/TextArea'; +export type { NumberFieldProps } from './components/Input/NumberField'; +export type { PasswordFieldProps } from './components/Input/PasswordField'; +export type { SearchFieldProps } from './components/Input/SearchField'; +export type { TextAreaFieldProps } from './components/Input/TextArea'; + +// Toast +export { Toast, ToastProvider } from './components/Toast'; +export { createToast } from './components/Toast/toastEmitter'; +export { useToast } from './components/Toast/useToast'; +export type { ToastProps } from './components/Toast'; + +// Tooltip +export { Tooltip } from './components/Tooltip/Tooltip'; +export type { TooltipProps } from './components/Tooltip'; + +// Typography +export { Text, Title } from './components/Typography'; +export type { TextProps } from './components/Typography/Text/Text'; +export type { TitleProps } from './components/Typography/Title/Title'; + +// Vertical Stepper +export { VerticalStepper } from './components/VerticalStepper'; +export type { + VerticalStepperProps, + VerticalStepProps, +} from './components/VerticalStepper'; + +// ================================================ +// Providers +// ================================================ + +// TODO: Having both ClickUIProvider and ThemeProvider exported is confusing. +// Consider consolidating to a single public provider API. For example, have ThemeProvider only! +export { ClickUIProvider, ThemeProvider } from './providers'; + +// ================================================ +// Theme +// ================================================ + +export { THEMES, themes } from './theme/theme.core'; +export type { ThemeName, Theme } from './theme/theme.types'; +export { + isValidThemeName, + getFallbackThemeName, + getDefaultThemeName, + getAvailableThemeNames, +} from './theme/theme.utils'; +export { InitCUIThemeScript } from './theme/InitCUIThemeScript/InitCUIThemeScript'; +export type { InitCUIThemeScriptProps } from './theme/InitCUIThemeScript/InitCUIThemeScript'; + +// ================================================ +// Global Types +// ================================================ + +export type { HorizontalDirection, Orientation, States, AssetSize } from './types'; + +// TODO: These should NOT be exposed +// prefer click ui props instead + +// ================================================ +// Radix UI Types +// ================================================ + +export type { ContextMenuProps } from '@radix-ui/react-context-menu'; +export type { DialogProps, DialogTriggerProps } from '@radix-ui/react-dialog'; +export type { HoverCardProps } from '@radix-ui/react-hover-card'; +export type { PopoverProps } from '@radix-ui/react-popover'; diff --git a/src/theme/ClickUIProvider/ClickUIProvider.tsx b/src/providers/ClickUIProvider.tsx similarity index 85% rename from src/theme/ClickUIProvider/ClickUIProvider.tsx rename to src/providers/ClickUIProvider.tsx index 65c894736..b38605324 100644 --- a/src/theme/ClickUIProvider/ClickUIProvider.tsx +++ b/src/providers/ClickUIProvider.tsx @@ -2,13 +2,14 @@ import { Provider as TooltipProvider, TooltipProviderProps, } from '@radix-ui/react-tooltip'; -import { ToastProvider, ToastProviderProps } from '@/components/Toast'; -import { ThemeName, THEMES } from '@/theme/theme.types'; -import { ThemeProvider } from '@/theme/theme'; +import { ToastProvider, ToastProviderProps } from '@/components/Toast/Toast'; +import { THEMES } from '@/theme/theme.core'; +import type { ThemeName } from '@/theme/theme.types'; +import { ThemeProvider } from './ThemeProvider'; import { ReactNode, useEffect } from 'react'; import { setRootThemeAttribute, removeRootThemeAttribute } from '@/utils/dom'; import { CUI_THEME_STORAGE_KEY } from '@/utils/localStorage'; -import { isValidThemeName, getFallbackThemeName } from '@/utils/theme'; +import { isValidThemeName, getFallbackThemeName } from '@/theme/theme.utils'; interface Props { config?: { @@ -21,7 +22,7 @@ interface Props { storageKey?: string; } -const ClickUIProvider = ({ +export const ClickUIProvider = ({ children, theme, config = {}, @@ -68,5 +69,3 @@ const ClickUIProvider = ({ ); }; - -export default ClickUIProvider; diff --git a/src/theme/theme.tsx b/src/providers/ThemeProvider.tsx similarity index 73% rename from src/theme/theme.tsx rename to src/providers/ThemeProvider.tsx index c325acabf..a998d49e5 100644 --- a/src/theme/theme.tsx +++ b/src/providers/ThemeProvider.tsx @@ -2,9 +2,10 @@ import { ThemeProvider as StyledThemeProvider, createGlobalStyle, } from 'styled-components'; -import { ThemeName, THEMES } from './theme.types'; -import { themes } from './themes'; -import { isValidThemeName } from '@/utils/theme'; +import { THEMES } from '@/theme/theme.core'; +import type { ThemeName } from '@/theme/theme.types'; +import { themes } from '@/theme/theme.core'; +import { isValidThemeName } from '@/theme/theme.utils'; const GlobalStyle = createGlobalStyle` body{ @@ -13,7 +14,7 @@ const GlobalStyle = createGlobalStyle` } `; -const ThemeProvider = ({ +export const ThemeProvider = ({ theme: name, children, }: { @@ -29,5 +30,3 @@ const ThemeProvider = ({ ); }; - -export { ThemeProvider }; diff --git a/src/providers/index.ts b/src/providers/index.ts new file mode 100644 index 000000000..c5d6b2aaa --- /dev/null +++ b/src/providers/index.ts @@ -0,0 +1,7 @@ +// TODO: Reconcile ClickUIProvider and ThemeProvider - having two public providers is confusing. +// Only one should be public. ClickUIProvider is the main composite provider that includes +// theme, toast, and tooltip providers. ThemeProvider is the lower-level styled-components +// theme provider. Consider deprecating one or making ThemeProvider internal only. + +export { ClickUIProvider } from './ClickUIProvider'; +export { ThemeProvider } from './ThemeProvider'; diff --git a/src/stories/chartColors.stories.tsx b/src/stories/chartColors.stories.tsx index 5b046dd18..732f69323 100644 --- a/src/stories/chartColors.stories.tsx +++ b/src/stories/chartColors.stories.tsx @@ -1,5 +1,5 @@ import { Container } from '@/components/Container'; -import { Text } from '@/components/Typography/Text/Text'; +import { Text } from '@/components/Typography/Text'; import { styled, useTheme } from 'styled-components'; diff --git a/src/theme/ClickUIProvider/index.ts b/src/theme/ClickUIProvider/index.ts deleted file mode 100644 index 04e47b462..000000000 --- a/src/theme/ClickUIProvider/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default as ClickUIProvider } from './ClickUIProvider'; -export { default } from './ClickUIProvider'; diff --git a/src/theme/InitCUIThemeScript/InitCUIThemeScript.tsx b/src/theme/InitCUIThemeScript/InitCUIThemeScript.tsx index c4f21a409..6db22f807 100644 --- a/src/theme/InitCUIThemeScript/InitCUIThemeScript.tsx +++ b/src/theme/InitCUIThemeScript/InitCUIThemeScript.tsx @@ -1,6 +1,7 @@ import { THEME_ATTRIBUTE } from '@/utils/dom'; import { CUI_THEME_STORAGE_KEY } from '@/utils/localStorage'; -import { ThemeName, THEMES } from '@/theme/core'; +import { THEMES } from '@/theme/theme.core'; +import type { ThemeName } from '@/theme/theme.types'; export interface InitCUIThemeScriptProps { defaultTheme?: ThemeName; diff --git a/src/theme/core.ts b/src/theme/core.ts deleted file mode 100644 index 1ffdce21e..000000000 --- a/src/theme/core.ts +++ /dev/null @@ -1,21 +0,0 @@ -import darkTheme from './tokens/variables.dark'; -import lightTheme from './tokens/variables.light'; - -export const THEMES = { - Dark: 'dark', - Light: 'light', -} as const; - -export type ThemeName = (typeof THEMES)[keyof typeof THEMES]; -export type ActiveThemeName = ThemeName; -export type Theme = typeof lightTheme; - -export const themes: Record = { - dark: darkTheme, - light: lightTheme, -}; - -// TODO: DefaultTheme can now be removed safely -declare module 'styled-components' { - export interface DefaultTheme extends Theme {} -} diff --git a/src/theme/index.ts b/src/theme/index.ts deleted file mode 100644 index 79ee63185..000000000 --- a/src/theme/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { ClickUIProvider } from './ClickUIProvider'; -export { THEMES } from './theme.types'; -export type { ThemeName, Theme } from './theme.types'; -export { themes } from './themes'; -export { InitCUIThemeScript } from './InitCUIThemeScript'; -export type { InitCUIThemeScriptProps } from './InitCUIThemeScript'; diff --git a/src/theme/theme.core.ts b/src/theme/theme.core.ts new file mode 100644 index 000000000..815c00df1 --- /dev/null +++ b/src/theme/theme.core.ts @@ -0,0 +1,19 @@ +import darkTheme from './tokens/variables.dark'; +import lightTheme from './tokens/variables.light'; +import type { Theme, ThemeName } from './theme.types'; + +export const THEMES: Record, ThemeName> = { + Dark: 'dark', + Light: 'light', +}; + +// Note: darkTheme and lightTheme have different +// token values but compatible structures. +// We use 'satisfies' to ensure type compatibility +// without casting, allowing TypeScript +// to infer the most precise type while still +// checking against the Theme interface. +export const themes = { + dark: darkTheme, + light: lightTheme, +} satisfies Record; diff --git a/src/theme/theme.types.ts b/src/theme/theme.types.ts index 268934412..90c1ef2de 100644 --- a/src/theme/theme.types.ts +++ b/src/theme/theme.types.ts @@ -1,14 +1,9 @@ import lightTheme from './tokens/variables.light'; -export const THEMES = { - Dark: 'dark', - Light: 'light', -} as const; - -export type ThemeName = (typeof THEMES)[keyof typeof THEMES]; - export type Theme = typeof lightTheme; +export type ThemeName = 'dark' | 'light'; + declare module 'styled-components' { export interface DefaultTheme extends Theme {} } diff --git a/src/utils/theme.ts b/src/theme/theme.utils.ts similarity index 54% rename from src/utils/theme.ts rename to src/theme/theme.utils.ts index 3ce68b7e7..572dd6c50 100644 --- a/src/utils/theme.ts +++ b/src/theme/theme.utils.ts @@ -1,7 +1,12 @@ -import { ThemeName, THEMES } from '@/theme/theme.types'; +import { THEMES } from '@/theme/theme.core'; +import type { ThemeName } from '@/theme/theme.types'; export const isValidThemeName = (theme: string | undefined): theme is ThemeName => theme !== undefined && ([THEMES.Dark, THEMES.Light] as Array).includes(theme); export const getFallbackThemeName = (theme: string | undefined): ThemeName => isValidThemeName(theme) ? theme : THEMES.Light; + +export const getDefaultThemeName = (): ThemeName => THEMES.Light; + +export const getAvailableThemeNames = (): ThemeName[] => [THEMES.Dark, THEMES.Light]; diff --git a/src/types/index.ts b/src/types/index.ts index c960392b2..0acdd9081 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -5,7 +5,7 @@ export type States = 'default' | 'active' | 'disabled' | 'error' | 'hover'; export type HorizontalDirection = 'start' | 'end'; export type Orientation = 'horizontal' | 'vertical'; -export type IconSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'; +export type AssetSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'; export type SVGAssetProps = SVGAttributes & { theme?: ThemeName; diff --git a/src/utils/dom.ts b/src/utils/dom.ts index 0125037b3..b9c6cd1e3 100644 --- a/src/utils/dom.ts +++ b/src/utils/dom.ts @@ -1,4 +1,4 @@ -import { ThemeName } from '@/theme/core'; +import { ThemeName } from '@/theme/theme.types'; import { CUI_THEME_STORAGE_KEY } from './localStorage'; export const THEME_ATTRIBUTE = `data-${CUI_THEME_STORAGE_KEY}`; diff --git a/src/utils/test-utils.tsx b/src/utils/test-utils.tsx index 617fad547..169beb24a 100644 --- a/src/utils/test-utils.tsx +++ b/src/utils/test-utils.tsx @@ -1,5 +1,6 @@ -import { type ThemeName, ClickUIProvider } from '@/theme'; +import type { ThemeName } from '@/theme/theme.types'; import { render as renderTL } from '@testing-library/react'; +import { ClickUIProvider } from '@/providers'; // eslint-disable-next-line react-refresh/only-export-components const Wrapper = ({