diff --git a/.changeset/tidy-drinks-doubt.md b/.changeset/tidy-drinks-doubt.md new file mode 100644 index 0000000..05ac4f3 --- /dev/null +++ b/.changeset/tidy-drinks-doubt.md @@ -0,0 +1,5 @@ +--- +'@groovy-box/ui': minor +--- + +storybook directory change, modal component, textfield and button component revamp diff --git a/.github/workflows/button-tests.yaml b/.github/workflows/button-tests.yaml deleted file mode 100644 index 306f33d..0000000 --- a/.github/workflows/button-tests.yaml +++ /dev/null @@ -1,36 +0,0 @@ -name: Button-Tests - -on: - push: - branches: [button] - pull_request: - branches: [button] - -jobs: - test_button: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Install Dependencies - run: npm install - - - name: Run Button Component Tests - run: npm run test __test__/Button.test.js - - id: test_button_output - continue-on-error: true - - - name: Set Test Result - if: always() - run: echo "::set-output name=button_tests_result::${{ job.status }}" - - - name: Final Message - if: success() - run: echo "Button component tests passed! 🎉" - - - name: Final Message on Failure - if: failure() - run: echo "Button component tests failed! ❌" diff --git a/.github/workflows/code_coverage.yml b/.github/workflows/code_coverage.yml index 7ea9144..ddd5957 100644 --- a/.github/workflows/code_coverage.yml +++ b/.github/workflows/code_coverage.yml @@ -1,40 +1,40 @@ -name: Running Code Coverage - -on: - push: - branches: - - dev - pull_request: - branches: - - dev - -jobs: - build: - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [20.x] - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - with: - fetch-depth: 2 - - - name: Set up Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node-version }} - - - name: Install dependencies - run: npm install - - - name: Run tests - run: npm run ui:coverage - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4 - with: - token: ${{ secrets.CODECOV_TOKEN }} - directory: apps/ui/coverage +# name: Running Code Coverage + +# on: +# push: +# branches: +# - dev +# pull_request: +# branches: +# - dev + +# jobs: +# build: +# runs-on: ubuntu-latest + +# strategy: +# matrix: +# node-version: [20.x] + +# steps: +# - name: Checkout repository +# uses: actions/checkout@v2 +# with: +# fetch-depth: 2 + +# - name: Set up Node.js ${{ matrix.node-version }} +# uses: actions/setup-node@v3 +# with: +# node-version: ${{ matrix.node-version }} + +# - name: Install dependencies +# run: npm install + +# - name: Run tests +# run: npm run ui:coverage + +# - name: Upload coverage to Codecov +# uses: codecov/codecov-action@v4 +# with: +# token: ${{ secrets.CODECOV_TOKEN }} +# directory: apps/ui/coverage diff --git a/.github/workflows/textfield-test.yaml b/.github/workflows/textfield-test.yaml deleted file mode 100644 index 30ccf1e..0000000 --- a/.github/workflows/textfield-test.yaml +++ /dev/null @@ -1,36 +0,0 @@ -name: Textfield-Tests - -on: - push: - branches: [textfield] - pull_request: - branches: [textfield] - -jobs: - test_button: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Install Dependencies - run: npm install - - - name: Run Button Component Tests - run: npm run test __test__/Textfield.test.js - - id: test_textField_output - continue-on-error: true - - - name: Set Test Result - if: always() - run: echo "::set-output name=textField_tests_result::${{ job.status }}" - - - name: Final Message - if: success() - run: echo "TextField component tests passed! 🎉" - - - name: Final Message on Failure - if: failure() - run: echo "Textfield component tests failed! ❌" diff --git a/apps/ui/.eslintrc.cjs b/apps/ui/.eslintrc.cjs index 6716988..d542efb 100644 --- a/apps/ui/.eslintrc.cjs +++ b/apps/ui/.eslintrc.cjs @@ -14,6 +14,7 @@ module.exports = { 'react/prop-types': 'off', 'react/react-in-jsx-scope': 'off', 'react/no-children-prop': 'off', + '@typescript-eslint/no-explicit-any': 'off', }, parserOptions: { project: true, diff --git a/apps/ui/.storybook/main.ts b/apps/ui/.storybook/main.ts index 2e7bd1d..55a16aa 100644 --- a/apps/ui/.storybook/main.ts +++ b/apps/ui/.storybook/main.ts @@ -4,55 +4,55 @@ import { defineConfig } from 'vite'; const tsconfigPaths = require('vite-tsconfig-paths').default; module.exports = { - stories: ['../stories/**/*.stories.@(ts|tsx|js|jsx)'], + stories: ['../lib/**/*.stories.@(ts|tsx|js|jsx)'], - viteFinal: async (config) => { - return mergeConfig(config, { - plugins: [tsconfigPaths()], - }); - }, - - viteConfig: defineConfig({ - resolve: { - alias: { - '@': '/src', - '@utils': '/utils', - }, + viteFinal: async (config) => { + return mergeConfig(config, { + plugins: [tsconfigPaths()], + }); }, - }), - addons: [ - '@storybook/addon-links', - '@storybook/addon-essentials', - '@storybook/addon-controls', - '@storybook/addon-themes', - 'storybook-css-modules', - { - name: '@storybook/addon-postcss', - options: { - postcssLoaderOptions: { - implementation: require('postcss'), + viteConfig: defineConfig({ + resolve: { + alias: { + '@': '/src', + '@utils': '/utils', + }, }, - }, - }, - ], + }), - // https://storybook.js.org/docs/react/configure/typescript#mainjs-configuration - typescript: { - check: true, // type-check stories during Storybook build - }, + addons: [ + '@storybook/addon-links', + '@storybook/addon-essentials', + '@storybook/addon-controls', + '@storybook/addon-themes', + 'storybook-css-modules', + { + name: '@storybook/addon-postcss', + options: { + postcssLoaderOptions: { + implementation: require('postcss'), + }, + }, + }, + ], - framework: { - name: '@storybook/react-vite', - // options: { - // legacyRootApi: true, - // builder: { - // viteConfigPath: './vite.config.ts', - // }, - // }, - }, + // https://storybook.js.org/docs/react/configure/typescript#mainjs-configuration + typescript: { + check: true, // type-check stories during Storybook build + }, - docs: { - autodocs: true, - }, + framework: { + name: '@storybook/react-vite', + // options: { + // legacyRootApi: true, + // builder: { + // viteConfigPath: './vite.config.ts', + // }, + // }, + }, + + docs: { + autodocs: true, + }, }; diff --git a/apps/ui/.storybook/preview.tsx b/apps/ui/.storybook/preview.tsx index 82e2219..3a12059 100644 --- a/apps/ui/.storybook/preview.tsx +++ b/apps/ui/.storybook/preview.tsx @@ -1,69 +1,69 @@ // https://storybook.js.org/docs/react/writing-stories/parameters#global-parameters import '../lib/tailwind.css'; import '../lib/color-scheme.css'; -import { withGlobalStyles } from './decorator'; +import '@groovy-box/tokens/src/fonts.css'; const customViewports = { - xs: { - name: 'XS', - styles: { - width: '350px', - height: '963px', + xs: { + name: 'XS', + styles: { + width: '350px', + height: '963px', + }, }, - }, - sm: { - name: 'SM', - styles: { - width: '600px', - height: '801px', + sm: { + name: 'SM', + styles: { + width: '600px', + height: '801px', + }, }, - }, - md: { - name: 'MD', - styles: { - width: '900px', - height: '801px', + md: { + name: 'MD', + styles: { + width: '900px', + height: '801px', + }, }, - }, - lg: { - name: 'LG', - styles: { - width: '1200px', - height: '801px', + lg: { + name: 'LG', + styles: { + width: '1200px', + height: '801px', + }, }, - }, - xl: { - name: 'XL', - styles: { - width: '1536px', - height: '801px', + xl: { + name: 'XL', + styles: { + width: '1536px', + height: '801px', + }, }, - }, }; export const parameters = { - // https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args - actions: { argTypesRegex: '^on.*' }, - controls: { - matchers: { - color: /(background|color)$/i, - date: /Date$/, + // https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args + actions: { argTypesRegex: '^on.*' }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/, + }, + }, + visualViewport: { + customViewports, }, - }, - visualViewport: { - customViewports, - }, }; export const globalTypes = { - scheme: { - name: 'Scheme', - description: 'Select light or dark', - defaultValue: 'light', - toolbar: { - icon: 'mirror', - items: ['light', 'dark'], - dynamicTitle: true, + scheme: { + name: 'Scheme', + description: 'Select light or dark', + defaultValue: 'light', + toolbar: { + icon: 'mirror', + items: ['light', 'dark'], + dynamicTitle: true, + }, }, - }, }; diff --git a/apps/ui/.storybook/theme.ts b/apps/ui/.storybook/theme.ts index c68890d..a867536 100644 --- a/apps/ui/.storybook/theme.ts +++ b/apps/ui/.storybook/theme.ts @@ -1,28 +1,28 @@ import { create } from '@storybook/theming/create'; export default create({ - base: 'light', - brandTitle: 'Groovy-Box', - brandUrl: 'https://ui.soumyasagar.in/', - brandImage: - 'https://raw.githubusercontent.com/EnigmaVSSUT/Enigma-UI-Kit/main/assets/logo.png', - brandTarget: '_self', - //fonts - fontBase: '"Inter", sans-serif', - fontCode: 'monospace', + base: 'light', + brandTitle: 'Groovy-Box', + brandUrl: 'https://ui.soumyasagar.in/', + brandImage: + 'https://raw.githubusercontent.com/EnigmaVSSUT/Enigma-UI-Kit/main/assets/logo.png', + brandTarget: '_self', + //fonts + fontBase: '"Inter", sans-serif', + fontCode: 'monospace', - //UI - appBg: '#E9EFE7', + //UI + appBg: '#E9EFE7', - // Text colors - textColor: '#454A44', - textInverseColor: '#10162F', + // Text colors + textColor: '#454A44', + textInverseColor: '#10162F', - // Toolbar default and active colors - barTextColor: '#9E9E9E', - barBg: '#ffffff', + // Toolbar default and active colors + barTextColor: '#9E9E9E', + barBg: '#ffffff', - // Form colors - inputBg: '#ffffff', - inputTextColor: '#10162F', + // Form colors + inputBg: '#ffffff', + inputTextColor: '#10162F', }); diff --git a/apps/ui/__test__/Button.spec.js b/apps/ui/__test__/Button.spec.js deleted file mode 100644 index 0d15fcd..0000000 --- a/apps/ui/__test__/Button.spec.js +++ /dev/null @@ -1,41 +0,0 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import { Button } from '../lib/components/Button/index'; -import { Variants, Sizes } from '../stories/Button.stories'; -import '@testing-library/jest-dom'; - -const argsColor = { - variant: 'default', - size: 'md', -}; - -const args = { - variant: 'default', - size: 'md', -}; - -describe('Button Component', () => { - test('renders without crashing', () => { - render(; -}; - -export const tailwindButtonWithOverridingVariant = () => { return ( - ); diff --git a/apps/ui/lib/components/Button/index.tsx b/apps/ui/lib/components/Button/index.tsx index 6a7af3f..2d07ff1 100644 --- a/apps/ui/lib/components/Button/index.tsx +++ b/apps/ui/lib/components/Button/index.tsx @@ -5,51 +5,52 @@ import { cva, type VariantProps } from 'class-variance-authority'; import { cn } from '@utils/utils'; const buttonVariants = cva( - 'grv-inline-flex grv-items-center grv-justify-center grv-whitespace-nowrap grv-rounded-md grv-text-sm grv-font-medium grv-ring-offset-background grv-transition-colors focus-visible:grv-outline-none focus-visible:grv-ring-2 focus-visible:grv-ring-ring focus-visible:grv-ring-offset-2 disabled:grv-pointer-events-none disabled:grv-opacity-50', - { - variants: { - variant: { - default: - 'grv-bg-primary-700 grv-text-text-primary hover:grv-bg-primary-500 grv-border-none', - destructive: - 'grv-bg-error-900 grv-text-text-primary hover:grv-bg-error-700 grv-border-none grv-outline-0 grv-shadow-none', - outline: - ' grv-border-none hover:grv-bg-bgopacity grv-text-accent [data-mode="dark"]:grv-text-text-primary grv-bg-primary-100/0 grv-outline grv-font-medium grv-outline-2 grv-outline-primary-500 grv-shadow-none', - secondary: - 'grv-bg-secondary-700 grv-text-text-primary hover:grv-bg-secondary-500 grv-border-none grv-outline-0 grv-shadow-none', - link: 'grv-text-primary-300 grv-underline-offset-4 hover:grv-underline grv-bg-primary-100/0 grv-font-medium grv-border-none hover:grv-cursor-pointer', - }, - size: { - default: 'grv-h-10 grv-px-4 grv-py-2', - sm: 'grv-h-9 grv-rounded-md grv-px-3', - lg: 'grv-h-11 grv-rounded-md grv-px-8', - icon: 'grv-h-10 grv-w-10', - }, - }, - defaultVariants: { - variant: 'default', - size: 'default', - }, - } + 'grv-inline-flex grv-items-center grv-justify-center grv-whitespace-nowrap grv-rounded-md grv-text-sm grv-font-medium grv-ring-offset-background grv-transition-colors focus-visible:grv-outline-none focus-visible:grv-ring-2 focus-visible:grv-ring-ring focus-visible:grv-ring-offset-2 disabled:grv-pointer-events-none disabled:grv-opacity-50', + { + variants: { + variant: { + default: + 'grv-bg-primary-700 grv-text-text-primary hover:grv-bg-primary-500 grv-border-none', + destructive: + 'grv-bg-error-900 grv-text-text-primary hover:grv-bg-error-700 grv-border-none grv-outline-0 grv-shadow-none', + outline: + ' grv-border-none hover:grv-bg-bgopacity grv-text-accent grv-bg-primary-100/0 grv-outline grv-font-medium grv-outline-2 grv-outline-primary-500 grv-shadow-none', + secondary: + 'grv-bg-secondary-700 grv-text-text-primary hover:grv-bg-secondary-500 grv-border-none grv-outline-0 grv-shadow-none', + link: 'grv-text-accent grv-underline-offset-4 hover:grv-underline grv-bg-primary-100/0 grv-font-medium grv-border-none hover:grv-cursor-pointer p-0 m-0', + }, + size: { + default: 'grv-h-10 grv-px-4 grv-py-2', + sm: 'grv-h-9 grv-rounded-md grv-px-3', + lg: 'grv-h-11 grv-rounded-md grv-px-8', + icon: 'grv-h-10 grv-w-10', + }, + }, + defaultVariants: { + variant: 'default', + size: 'default', + }, + } ); export interface ButtonProps - extends React.ButtonHTMLAttributes, + extends React.ButtonHTMLAttributes, VariantProps { - asChild?: boolean; + asChild?: boolean; } const Button = React.forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : 'button'; - return ( - - ); - } + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : 'button'; + + return ( + + ); + } ); Button.displayName = 'Button'; diff --git a/apps/ui/stories/Chip.stories.tsx b/apps/ui/lib/components/Chip/Chip.stories.tsx similarity index 90% rename from apps/ui/stories/Chip.stories.tsx rename to apps/ui/lib/components/Chip/Chip.stories.tsx index 0148df7..2d2adce 100644 --- a/apps/ui/stories/Chip.stories.tsx +++ b/apps/ui/lib/components/Chip/Chip.stories.tsx @@ -1,9 +1,8 @@ -import React from 'react'; -import { Meta, Story } from '@storybook/react'; -import { withGlobalStyles } from '../.storybook/decorator'; +import { Story } from '@storybook/react'; +import { withGlobalStyles } from '../../../.storybook/decorator'; -import { Chip, ChipProps } from '../lib'; -import { Avatar, AvatarImage, AvatarFallback } from '../lib'; +import { Chip, ChipProps } from '../..'; +import { Avatar, AvatarImage, AvatarFallback } from '../..'; import { Star, Mail } from 'lucide-react'; const ChipExample = (props: ChipProps) => ( @@ -77,7 +76,7 @@ export default { title: 'components/Chip', component: ChipExample, decorators: [withGlobalStyles], -} as Meta; +}; export const Default: Story = (args) => ; Default.args = { diff --git a/apps/ui/lib/components/Chip/Chip.tsx b/apps/ui/lib/components/Chip/Chip.tsx index 9053f0c..fdac16d 100644 --- a/apps/ui/lib/components/Chip/Chip.tsx +++ b/apps/ui/lib/components/Chip/Chip.tsx @@ -6,134 +6,132 @@ import { X as CloseIcon } from 'lucide-react'; import { cn } from '@utils/utils'; const chipVariants = cva( - 'grv-inline-flex ui grv-items-center grv-rounded-full grv-text-sm grv-font-medium grv-transition-colors focus:grv-outline-none focus:grv-ring-2 grv-ring-ring grv-ring-offset-2', - { - variants: { - variant: { - filled: 'grv-bg-primary-500 ui', - outlined: 'grv-border-2 grv-border-solid grv-border-accent ui', - }, - size: { - sm: 'grv-h-6 grv-px-3 ui', - md: 'grv-h-8 grv-px-4 ui', - lg: 'grv-h-10 grv-px-5 ui', - }, - clickable: { - true: 'grv-cursor-pointer', - false: '', - }, - }, - defaultVariants: { - variant: 'filled', - size: 'md', - clickable: false, - }, - } + 'grv-inline-flex ui grv-items-center grv-rounded-full grv-text-sm grv-font-medium grv-transition-colors focus:grv-outline-none focus:grv-ring-2 grv-ring-ring grv-ring-offset-2', + { + variants: { + variant: { + filled: 'grv-bg-primary-500 ui', + outlined: 'grv-border-2 grv-border-solid grv-border-accent ui', + }, + size: { + sm: 'grv-h-6 grv-px-3 ui', + md: 'grv-h-8 grv-px-4 ui', + lg: 'grv-h-10 grv-px-5 ui', + }, + clickable: { + true: 'grv-cursor-pointer', + false: '', + }, + }, + defaultVariants: { + variant: 'filled', + size: 'md', + clickable: false, + }, + } ); export interface ChipDivProps - extends React.HTMLAttributes, + extends React.HTMLAttributes, VariantProps { - onDelete?: () => void; - as?: React.ElementType; - href?: never; - beforeChildren?: React.ReactNode; - afterChildren?: React.ReactNode; + onDelete?: () => void; + as?: React.ElementType; + href?: never; + beforeChildren?: React.ReactNode; + afterChildren?: React.ReactNode; } export interface ChipAnchorProps - extends React.HTMLAttributes, + extends React.HTMLAttributes, VariantProps { - onDelete?: () => void; - href?: string; - target?: string; - as?: React.ElementType; - beforeChildren?: React.ReactNode; - afterChildren?: React.ReactNode; + onDelete?: () => void; + href?: string; + target?: string; + as?: React.ElementType; + beforeChildren?: React.ReactNode; + afterChildren?: React.ReactNode; } export type ChipProps = ChipAnchorProps | ChipDivProps; const Chip = React.forwardRef( - ( - { - className, - variant, - size, - clickable, - onDelete, - href, - as, - beforeChildren, - afterChildren, - children, - ...props - }, - ref - ) => { - const Component = as || (href ? 'a' : 'div'); - const isClickable = Boolean(clickable || href || props.onClick); + ( + { + className, + variant, + size, + clickable, + onDelete, + href, + as, + beforeChildren, + afterChildren, + children, + ...props + }, + ref + ) => { + const Component = as || (href ? 'a' : 'div'); + const isClickable = Boolean(clickable || href || props.onClick); - console.log(variant); - const textColor = - variant === 'outlined' ? 'grv-text-accent' : 'grv-text-text-primary'; + const textColor = + variant === 'outlined' ? 'grv-text-accent' : 'grv-text-text-primary'; - console.log(size); - const textSize = - size === 'sm' - ? 'grv-text-[10px]' - : size === 'md' - ? 'grv-text-[12px]' - : 'grv-text-[14px]'; + const textSize = + size === 'sm' + ? 'grv-text-[10px]' + : size === 'md' + ? 'grv-text-[12px]' + : 'grv-text-[14px]'; - return ( - - {beforeChildren && ( -
- {beforeChildren} -
- )} -
{children}
- {afterChildren && ( -
- {afterChildren} -
- )} - {onDelete && ( -
{ - e.stopPropagation(); - onDelete(); - }} - > - -
- )} -
- ); - } + return ( + + {beforeChildren && ( +
+ {beforeChildren} +
+ )} +
{children}
+ {afterChildren && ( +
+ {afterChildren} +
+ )} + {onDelete && ( +
{ + e.stopPropagation(); + onDelete(); + }} + > + +
+ )} +
+ ); + } ); Chip.displayName = 'Chip'; diff --git a/apps/ui/stories/Label.stories.tsx b/apps/ui/lib/components/Label/Label.stories.tsx similarity index 73% rename from apps/ui/stories/Label.stories.tsx rename to apps/ui/lib/components/Label/Label.stories.tsx index 10e27e6..b97d93c 100644 --- a/apps/ui/stories/Label.stories.tsx +++ b/apps/ui/lib/components/Label/Label.stories.tsx @@ -1,7 +1,6 @@ -import React from 'react'; -import { Meta, StoryObj } from '@storybook/react'; -import { Label } from '../lib'; -import { withGlobalStyles } from '../.storybook/decorator'; +import { StoryObj } from '@storybook/react'; +import { Label } from '../..'; +import { withGlobalStyles } from '../../../.storybook/decorator'; type LabelComponentStory = StoryObj; @@ -14,7 +13,7 @@ export default { htmlFor: { control: 'text' }, children: { control: 'text' }, }, -} as Meta; +}; export const BasicLabelComponent: LabelComponentStory = { args: { diff --git a/apps/ui/lib/components/Modal/Modal.stories.tsx b/apps/ui/lib/components/Modal/Modal.stories.tsx new file mode 100644 index 0000000..0bf282d --- /dev/null +++ b/apps/ui/lib/components/Modal/Modal.stories.tsx @@ -0,0 +1,149 @@ +import { + Dialog, + DialogTrigger, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, + DialogClose, +} from './Modal'; +import { Text } from '../Typography'; +import { Button } from '../Button'; +import { Label } from '../Label'; +import { TextField } from '../Textfield'; +import { withGlobalStyles } from '../../../.storybook/decorator'; + +export default { + title: 'Components/Modal', + component: Dialog, + decorators: [withGlobalStyles], +}; + +const BasicDialog = () => ( + + + + + + + + + Dialog Title + + This is a description for the dialog content. + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar + risus non rikus. + + + +); + +export const Basic = () => ; + +const ModalWithFooter = () => ( + + + + + + + + + Dialog Title + + This is a description for the dialog content. + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar + risus non rikus. + + + + + + + +); + +export const WithFooter = () => ; + +const ModalWithImage = () => ( + + + + + + + + Hello 2025 + + + + Random Image + + + Wish you a very happy new year. May this year bring you joy and + happiness. + + + +); + +export const WithImage = () => ; + +const LoginModal = () => ( + + + + + + + + Login + + Please enter your credentials to login. + + +
+
+ + +
+
+ + +
+ +
+
+
+); + +export const Login = () => ; diff --git a/apps/ui/lib/components/Modal/Modal.tsx b/apps/ui/lib/components/Modal/Modal.tsx new file mode 100644 index 0000000..9a1393d --- /dev/null +++ b/apps/ui/lib/components/Modal/Modal.tsx @@ -0,0 +1,168 @@ +import * as React from 'react'; +import * as DialogPrimitive from '@radix-ui/react-dialog'; +import { motion, AnimatePresence } from 'framer-motion'; +import { X } from 'lucide-react'; + +import { cn } from '@utils/utils'; + +const Dialog = DialogPrimitive.Root; + +const DialogTrigger = DialogPrimitive.Trigger; + +const DialogPortal = DialogPrimitive.Portal; + +const DialogClose = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className }, ref) => ( + + + + + +)); + +DialogClose.displayName = DialogPrimitive.Close.displayName; + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)); +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + {children} + + + + +)); +DialogContent.displayName = DialogPrimitive.Content.displayName; + +const DialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+); +DialogHeader.displayName = 'DialogHeader'; + +const DialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+); +DialogFooter.displayName = 'DialogFooter'; + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogTitle.displayName = DialogPrimitive.Title.displayName; + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogDescription.displayName = DialogPrimitive.Description.displayName; + +export { + Dialog, + DialogPortal, + DialogOverlay, + DialogClose, + DialogTrigger, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +}; diff --git a/apps/ui/lib/components/Modal/index.tsx b/apps/ui/lib/components/Modal/index.tsx new file mode 100644 index 0000000..cb89ee1 --- /dev/null +++ b/apps/ui/lib/components/Modal/index.tsx @@ -0,0 +1 @@ +export * from './Modal'; diff --git a/apps/ui/stories/Navigation.stories.tsx b/apps/ui/lib/components/Navigation-menu/Navigation.stories.tsx similarity index 96% rename from apps/ui/stories/Navigation.stories.tsx rename to apps/ui/lib/components/Navigation-menu/Navigation.stories.tsx index df0a9a6..071bcea 100644 --- a/apps/ui/stories/Navigation.stories.tsx +++ b/apps/ui/lib/components/Navigation-menu/Navigation.stories.tsx @@ -1,16 +1,12 @@ -import React from 'react'; -import { Meta, Story } from '@storybook/react'; - import { NavigationMenu, NavigationMenuList, NavigationMenuItem, NavigationMenuTrigger, NavigationMenuContent, - NavigationMenuIndicator, NavigationMenuLink, ListItem, -} from '../lib'; +} from '../..'; const components: { title: string; href: string; description: string }[] = [ { @@ -111,7 +107,7 @@ const Test = () => ( export default { title: 'components/Navigation', component: Test, -} as Meta; +}; export const Default = () => { return ; diff --git a/apps/ui/stories/Progress.stories.tsx b/apps/ui/lib/components/Progress/Progress.stories.tsx similarity index 75% rename from apps/ui/stories/Progress.stories.tsx rename to apps/ui/lib/components/Progress/Progress.stories.tsx index 6313e01..75a388a 100644 --- a/apps/ui/stories/Progress.stories.tsx +++ b/apps/ui/lib/components/Progress/Progress.stories.tsx @@ -1,7 +1,5 @@ -import React from 'react'; -import { Meta, Story } from '@storybook/react'; -import { withGlobalStyles } from '../.storybook/decorator'; -import { Progress, Text } from '../lib'; +import { withGlobalStyles } from '../../../.storybook/decorator'; +import { Progress, Text } from '../..'; const DefaultTemplate = ({ value = 40 }) => { return ( @@ -27,7 +25,7 @@ export default { title: 'components/Progress', component: DefaultTemplate, decorators: [withGlobalStyles], -} as Meta; +}; export const Default = () => { return ; diff --git a/apps/ui/stories/Select.stories.tsx b/apps/ui/lib/components/Select/Select.stories.tsx similarity index 78% rename from apps/ui/stories/Select.stories.tsx rename to apps/ui/lib/components/Select/Select.stories.tsx index 8315d5f..f3980c6 100644 --- a/apps/ui/stories/Select.stories.tsx +++ b/apps/ui/lib/components/Select/Select.stories.tsx @@ -1,13 +1,5 @@ // SelectDemo.stories.js - -import React from 'react'; -import { - CheckIcon, - ChevronDownIcon, - ChevronUpIcon, -} from '@radix-ui/react-icons'; -import { Check } from 'lucide-react'; -import { Meta, StoryObj } from '@storybook/react'; +import { ChevronDownIcon, ChevronUpIcon } from '@radix-ui/react-icons'; import { Select, SelectContent, @@ -16,10 +8,9 @@ import { SelectLabel, SelectScrollDownButton, SelectScrollUpButton, - SelectSeparator, SelectTrigger, SelectValue, -} from '../lib'; // Import your custom Select component +} from '../..'; // Import your custom Select component import { SelectIcon } from '@radix-ui/react-select'; // type SelectComponentStory = StoryObj; @@ -35,7 +26,7 @@ const options = [ { value: 'cabbage', label: 'Cabbage' }, ]; -const Test = () => ( +const BasicSelect = () => (
{ + setIsFocused(true); + onFocus?.(e); + }} + onBlur={(e) => { + setIsFocused(false); + onBlur?.(e); + }} + {...props} + /> + ); } - }; - - return ( -
- {label && } -
- {startIcon && {startIcon}} - - {endIcon && {endIcon}} -
-
- ); +); + +const Icon = ({ children, position, className }: TextFieldIconProps) => { + const { isFocused } = useTextField(); + + const iconVariants = { + initial: { opacity: 0.7 }, + focus: { opacity: 1 }, + }; + + return ( + + {children} + + ); }; + +const HelperText = ({ children, className }: TextFieldHelperTextProps) => { + const { error } = useTextField(); + + return ( + + + + {children} + + + + ); +}; + +export const TextField = { + Root, + Input: Input, + Icon, + HelperText, +}; + +Input.displayName = 'TextField.Input'; \ No newline at end of file diff --git a/apps/ui/stories/Toast.stories.tsx b/apps/ui/lib/components/Toast/Toast.stories.tsx similarity index 89% rename from apps/ui/stories/Toast.stories.tsx rename to apps/ui/lib/components/Toast/Toast.stories.tsx index 4902fa5..0f9599e 100644 --- a/apps/ui/stories/Toast.stories.tsx +++ b/apps/ui/lib/components/Toast/Toast.stories.tsx @@ -1,7 +1,5 @@ -import React from 'react'; -import { Meta, Story } from '@storybook/react'; -import { withGlobalStyles } from '../.storybook/decorator'; -import { useToast, Button, Toaster, ToastAction } from '../lib'; +import { withGlobalStyles } from '../../../.storybook/decorator'; +import { useToast, Button, Toaster, ToastAction } from '../..'; export const Default = () => { const { toast } = useToast(); @@ -33,7 +31,7 @@ export default { title: 'components/Toast', component: Default, decorators: [withGlobalStyles], -} as Meta; +}; export const Destructive = () => { const { toast } = useToast(); diff --git a/apps/ui/lib/components/Typography/Text.tsx b/apps/ui/lib/components/Typography/Text.tsx index fab6b84..fb52618 100644 --- a/apps/ui/lib/components/Typography/Text.tsx +++ b/apps/ui/lib/components/Typography/Text.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { VARIANT_MAPPINGS } from './constants'; import { Slot } from './Slot'; -import style from './text.module.css'; import { cn } from '@utils/utils'; export interface TextProps extends React.HTMLAttributes { variant?: keyof typeof VARIANT_MAPPINGS; @@ -21,8 +20,6 @@ export const Text: React.FC = ({ }) => { const textStyle = { textAlign: alignment || 'center', - margin: '0 0 0 0', - padding: '0 0 0 0', display: asChild ? 'inline-block' : 'block', textOverflow: 'ellipsis', overflow: 'hidden', @@ -31,12 +28,11 @@ export const Text: React.FC = ({ const Comp = asChild ? Slot : 'p'; const classNames = VARIANT_MAPPINGS[variant as keyof typeof VARIANT_MAPPINGS]; - const mergedClasses = cn(style.text, classNames?.slice(1), props.className); return ( diff --git a/apps/ui/stories/Typography.stories.tsx b/apps/ui/lib/components/Typography/Typography.stories.tsx similarity index 97% rename from apps/ui/stories/Typography.stories.tsx rename to apps/ui/lib/components/Typography/Typography.stories.tsx index 551e1e9..923f67c 100644 --- a/apps/ui/stories/Typography.stories.tsx +++ b/apps/ui/lib/components/Typography/Typography.stories.tsx @@ -1,5 +1,4 @@ -import React from 'react'; -import { Text, TextProps } from '../lib'; +import { Text } from '../..'; export default { title: 'Components/Text', @@ -63,7 +62,7 @@ export default { }; // Create a template for your Text component -const Template = (args) => ; +const Template = (args: any) => ; export const Default = Template.bind({}); Default.args = { @@ -214,7 +213,7 @@ export const withTailwind = () => { export const withTailwindAndVariant = () => { return (
- + with tailwind classes and variant
diff --git a/apps/ui/lib/index.tsx b/apps/ui/lib/index.tsx index 6c74336..b34e0d1 100644 --- a/apps/ui/lib/index.tsx +++ b/apps/ui/lib/index.tsx @@ -12,4 +12,5 @@ export * from './components/Navigation-menu'; export * from './components/Switch'; export * from './components/Toast'; export * from './components/Progress'; -export * from './components/Chip'; \ No newline at end of file +export * from './components/Chip'; +export * from './components/Modal'; \ No newline at end of file diff --git a/apps/ui/lib/tailwind.css b/apps/ui/lib/tailwind.css index 17f910e..29784c9 100644 --- a/apps/ui/lib/tailwind.css +++ b/apps/ui/lib/tailwind.css @@ -36,11 +36,12 @@ --warning-900: 222, 193, 110; --text-primary: 235, 235, 235; - --text-secondary: 30, 30, 30; + --text-secondary: 93, 97, 102; --accent: 0, 0, 0; --background-paper: 255 255 255; --background-opacity: 0, 0, 0, 0.05; + --background-overlay: 0, 0, 0, 0.7; } /* Dark Mode Colors */ @@ -76,12 +77,13 @@ --warning-900: 187, 167, 81; --text-primary: 245, 245, 245; - --text-secondary: 23, 23, 23; + --text-secondary: 102, 98, 93; --accent: 255, 245, 245; --background-paper: 253, 253, 253; --background-opacity: 253, 253, 253, 0.1; + --background-overlay: 0, 0, 0, 0.7; } } diff --git a/apps/ui/package.json b/apps/ui/package.json index c02b2c9..b2e8b98 100644 --- a/apps/ui/package.json +++ b/apps/ui/package.json @@ -21,7 +21,7 @@ "build": "npx sort-package-json && tsc && vite build", "build-storybook": "storybook build", "dev": "storybook dev -p 6006", - "format": "prettier --write lib/**/* stories/**/*", + "format": "prettier --write lib/**/*", "lint": "eslint ./lib --ext .ts,.tsx", "lint-fix": "eslint --fix .", "pub:beta": "npm run build && npm publish --no-git-checks --access public --tag beta", @@ -44,6 +44,7 @@ }, "dependencies": { "@radix-ui/react-avatar": "^1.0.4", + "@radix-ui/react-dialog": "^1.1.4", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-select": "^2.0.0", "class-variance-authority": "^0.7.0", diff --git a/apps/ui/stories/Textfield.stories.tsx b/apps/ui/stories/Textfield.stories.tsx deleted file mode 100644 index e932747..0000000 --- a/apps/ui/stories/Textfield.stories.tsx +++ /dev/null @@ -1,177 +0,0 @@ -import React from 'react'; -import { Meta } from '@storybook/react'; -import { TextField } from '../lib'; - -export default { - title: 'Components/TextField', - component: TextField, - argTypes: { - variant: { - options: ['filled', 'outlined', 'standard'], - control: { type: 'radio' }, - }, - size: { - options: ['sm', 'md', 'lg'], - control: { type: 'radio' }, - }, - type: { - options: ['password', 'number', 'email', 'text'], - control: { type: 'radio' }, - }, - color: { - options: ['primary', 'secondary'], - control: { type: 'radio' }, - }, - placeholder: { - control: { type: 'text' }, - }, - disabled: { - control: { type: 'boolean' }, - }, - required: { - control: { type: 'boolean' }, - }, - readOnly: { - control: { type: 'boolean' }, - }, - fullWidth: { - control: { type: 'boolean' }, - }, - multiline: { - control: { type: 'boolean' }, - }, - rows: { - control: { type: 'number' }, - }, - rowsMax: { - control: { type: 'number' }, - }, - startIcon: { - control: { type: 'text' }, - }, - endIcon: { - control: { type: 'text' }, - }, - onChange: { - control: { type: 'text' }, - }, - onClick: { - control: { type: 'text' }, - }, - onFocus: { - control: { type: 'text' }, - }, - onBlur: { - control: { type: 'text' }, - }, - onKeyPress: { - control: { type: 'text' }, - }, - onKeyUp: { - control: { type: 'text' }, - }, - onKeyDown: { - control: { type: 'text' }, - }, - }, -} as Meta; - -export const Default = (args: any) => ; - -Default.args = { - label: 'Label', - placeholder: 'Placeholder', - startIcon: '👋', - endIcon: '👋', -}; - -export const Colors = (args: any) => ( -
-
- -
-
- -
-
-); - -Colors.args = { - variant: 'filled', -}; - -export const Variants = (args: any) => ( -
-
- -
-
- -
-
-); - -Variants.args = { - color: 'primary', -}; - -export const Sizes = (args: any) => ( -
-
- -
-
- -
-
- -
-
-); - -Sizes.args = { - color: 'primary', -}; - -export const Multiline = (args: any) => ( -
-
- -
-
- -
-
-); diff --git a/apps/ui/tailwind.config.ts b/apps/ui/tailwind.config.ts index 53c64cb..66915cd 100644 --- a/apps/ui/tailwind.config.ts +++ b/apps/ui/tailwind.config.ts @@ -1,78 +1,107 @@ import plugin from 'tailwindcss/plugin'; import type { Config } from 'tailwindcss'; import { - scopedPreflightStyles, - isolateInsideOfContainer, + scopedPreflightStyles, + isolateInsideOfContainer, } from 'tailwindcss-scoped-preflight'; import { customTypographyClasses, groovyFontFamily } from '@groovy-box/tokens'; /** @type {import('tailwindcss').Config} */ module.exports = { - prefix: 'grv-', - important: true, - darkMode: ['class', '[data-mode="dark"]'], - content: [ - './lib/**/*.{html,ts,tsx,js,jsx}', - './stories/**/*.{ts,tsx,js,jsx}', - ], - theme: { - extend: { - fontFamily: groovyFontFamily, + prefix: 'grv-', + important: true, + darkMode: ['class', '[data-mode="dark"]'], + content: [ + './lib/**/*.{html,ts,tsx,js,jsx}', + './stories/**/*.{ts,tsx,js,jsx}', + ], + theme: { + extend: { + fontFamily: groovyFontFamily, + }, + keyframes: { + overlayShow: { + from: { opacity: "0" }, + to: { opacity: "1" }, + }, + contentShow: { + from: { + opacity: "0", + transform: "translate(-50%, -48%) scale(0.96)", + }, + to: { opacity: "1", transform: "translate(-50%, -50%) scale(1)" }, + }, + }, + animation: { + overlayShow: "overlayShow 150ms cubic-bezier(0.16, 1, 0.3, 1)", + contentShow: "contentShow 150ms cubic-bezier(0.16, 1, 0.3, 1)", + }, + colors: { + primary: { + 100: 'rgb(var(--primary-100))', + 300: 'rgb(var(--primary-300))', + 500: 'rgb(var(--primary-500))', + 700: 'rgb(var(--primary-700))', + 900: 'rgb(var(--primary-900))', + }, + secondary: { + 100: 'rgb(var(--secondary-100))', + 300: 'rgb(var(--secondary-300))', + 500: 'rgb(var(--secondary-500))', + 700: 'rgb(var(--secondary-700))', + 900: 'rgb(var(--secondary-900))', + }, + success: { + 100: 'rgb(var(--success-100))', + 300: 'rgb(var(--success-300))', + 500: 'rgb(var(--success-500))', + 700: 'rgb(var(--success-700))', + 900: 'rgb(var(--success-900))', + }, + error: { + 100: 'rgb(var(--error-100))', + 300: 'rgb(var(--error-300))', + 500: 'rgb(var(--error-500))', + 700: 'rgb(var(--error-700))', + 900: 'rgb(var(--error-900))', + }, + warning: { + 100: 'rgb(var(--warning-100))', + 300: 'rgb(var(--warning-300))', + 500: 'rgb(var(--warning-500))', + 700: 'rgb(var(--warning-700))', + 900: 'rgb(var(--warning-900))', + }, + text: { + primary: 'rgb(var(--text-primary))', + secondary: 'rgb(var(--text-secondary))', + }, + accent: 'rgb(var(--accent))', + backgroundPaper: 'rgb(var(--background-paper))', + bgopacity: 'rgb(var( --background-opacity))', + bgOverlay: 'rgb(var(--background-overlay))', + }, + fontWeight: { + thin: '100', + light: '300', + regular: '400', + medium: '500', + semibold: '600', + bold: '700', + }, + fontFamily: { + sans: ['"Inter var"', 'system-ui', 'sans-serif'] + }, }, - colors: { - primary: { - 100: 'rgb(var(--primary-100))', - 300: 'rgb(var(--primary-300))', - 500: 'rgb(var(--primary-500))', - 700: 'rgb(var(--primary-700))', - 900: 'rgb(var(--primary-900))', - }, - secondary: { - 100: 'rgb(var(--secondary-100))', - 300: 'rgb(var(--secondary-300))', - 500: 'rgb(var(--secondary-500))', - 700: 'rgb(var(--secondary-700))', - 900: 'rgb(var(--secondary-900))', - }, - success: { - 100: 'rgb(var(--success-100))', - 300: 'rgb(var(--success-300))', - 500: 'rgb(var(--success-500))', - 700: 'rgb(var(--success-700))', - 900: 'rgb(var(--success-900))', - }, - error: { - 100: 'rgb(var(--error-100))', - 300: 'rgb(var(--error-300))', - 500: 'rgb(var(--error-500))', - 700: 'rgb(var(--error-700))', - 900: 'rgb(var(--error-900))', - }, - warning: { - 100: 'rgb(var(--warning-100))', - 300: 'rgb(var(--warning-300))', - 500: 'rgb(var(--warning-500))', - 700: 'rgb(var(--warning-700))', - 900: 'rgb(var(--warning-900))', - }, - text: { - primary: 'rgb(var(--text-primary))', - secondary: 'rgb(var(--text-secondary))', - }, - accent: 'rgb(var(--accent))', - backgroundPaper: 'rgb(var(--background-paper))', - bgopacity: 'rgb(var( --background-opacity))', + plugins: [ + plugin(({ addUtilities }) => { + addUtilities(customTypographyClasses, { respectPrefix: false }); + }), + scopedPreflightStyles({ + isolationStrategy: isolateInsideOfContainer('.ui', {}), + }), + ], + corePlugins: { + preflight: false, // <== disable this! }, - }, - plugins: [ - plugin(({ addUtilities }) => { - addUtilities(customTypographyClasses, { respectPrefix: false }); - }), - scopedPreflightStyles({ - isolationStrategy: isolateInsideOfContainer('.ui', {}), - }), - ], - corePlugins: { - preflight: false, // <== disable this! - }, } satisfies Config; diff --git a/apps/ui/utils/utils.ts b/apps/ui/utils/utils.ts index 1a860ee..c1d3862 100644 --- a/apps/ui/utils/utils.ts +++ b/apps/ui/utils/utils.ts @@ -2,5 +2,5 @@ import { type ClassValue, clsx } from "clsx" import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)) + return twMerge(clsx(inputs)) } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index d76c833..76549d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -85,6 +85,7 @@ "license": "MIT", "dependencies": { "@radix-ui/react-avatar": "^1.0.4", + "@radix-ui/react-dialog": "^1.1.4", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-select": "^2.0.0", "class-variance-authority": "^0.7.0", @@ -174,6 +175,309 @@ "react": ">=16" } }, + "apps/ui/node_modules/@radix-ui/primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", + "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==" + }, + "apps/ui/node_modules/@radix-ui/react-dialog": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.4.tgz", + "integrity": "sha512-Ur7EV1IwQGCyaAuyDRiOLA5JIUZxELJljF+MbM/2NC0BYwfuRrbpS30BiQBJrVruscgUkieKkqXYDOoByaxIoA==", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.3", + "@radix-ui/react-focus-guards": "1.1.1", + "@radix-ui/react-focus-scope": "1.1.1", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-portal": "1.1.3", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-slot": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.1.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "^2.6.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", + "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.3.tgz", + "integrity": "sha512-onrWn/72lQoEucDmJnr8uczSNTujT0vJnA/X5+3AkChVPowr8n1yvIKIabhWyMQeMvvmdpsvcyDqx3X1LEXCPg==", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-escape-keydown": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", + "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.1.tgz", + "integrity": "sha512-01omzJAYRxXdG2/he/+xy+c8a8gCydoQ1yOxnWNcRhrrBW5W+RQJ22EK1SaO8tb3WoUsuEw7mJjBozPzihDFjA==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-portal": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.3.tgz", + "integrity": "sha512-NciRqhXnGojhT93RPyDaMPfLH3ZSl4jjIFbZQ1b/vxvZEdHsBZ49wP9w8L3HzUQwep01LcWtkUvm0OVB5JAHTw==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-presence": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz", + "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-primitive": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz", + "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==", + "dependencies": { + "@radix-ui/react-slot": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz", + "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/react-remove-scroll": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.2.tgz", + "integrity": "sha512-KmONPx5fnlXYJQqC62Q+lwIeAk64ws/cUw6omIumRzMRPqgnYqhSSti99nbj0Ry13bv7dF+BKn7NB+OqkdZGTw==", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/react-remove-scroll/node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "dependencies": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/react-remove-scroll/node_modules/react-remove-scroll-bar/node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "dependencies": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "apps/ui/node_modules/@radix-ui/react-dialog/node_modules/react-remove-scroll/node_modules/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "apps/ui/node_modules/@storybook/manager-api": { "version": "8.3.5", "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-8.3.5.tgz",