From 409aa202413e4af54a4a6ffb854443e93afbacc3 Mon Sep 17 00:00:00 2001 From: Fing0r Date: Sat, 21 Feb 2026 16:24:56 +0700 Subject: [PATCH 1/9] =?UTF-8?q?chore(repo):=20=D0=B4=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=20@ianvs/prettier-plugin-sort-imports=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D1=81=D0=BE=D1=80=D1=82=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B8=20=D0=B8=D0=BC=D0=BF=D0=BE=D1=80=D1=82=D0=BE?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .prettierrc.mjs | 24 ++++++++++++++++++++++-- package.json | 1 + pnpm-lock.yaml | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/.prettierrc.mjs b/.prettierrc.mjs index 89f612fb..c09cbcef 100644 --- a/.prettierrc.mjs +++ b/.prettierrc.mjs @@ -1,4 +1,24 @@ -import config from "@repo/eslint-config/prettier-base"; +import defautlConfig from '@repo/eslint-config/prettier-base' + +const config = { + ...defautlConfig, + plugins: ['@ianvs/prettier-plugin-sort-imports'], + importOrder: [ + '', + '', + '', + '^@repo(.*)$', + '', + '^[../]', + '^[./]', + ], + importOrderParserPlugins: ['typescript', 'jsx'], + importOrderTypeScriptVersion: '5.0.0', + importOrderCaseSensitive: false, + importOrderMergeDuplicateImports: true, + importOrderCombineTypeAndValueImports: true, + importOrderSortSpecifiers: true, +} /** @type {import("prettier").Config} */ -export default config; +export default config diff --git a/package.json b/package.json index 609b6f9a..6c821e4d 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "devDependencies": { "@commitlint/cli": "^20.4.1", "@commitlint/config-conventional": "^20.4.1", + "@ianvs/prettier-plugin-sort-imports": "^4.7.1", "@repo/eslint-config": "workspace:*", "@repo/typescript-config": "workspace:*", "@typescript-eslint/eslint-plugin": "^8.56.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ec22c06a..56c04eb4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: '@commitlint/config-conventional': specifier: ^20.4.1 version: 20.4.1 + '@ianvs/prettier-plugin-sort-imports': + specifier: ^4.7.1 + version: 4.7.1(prettier@3.8.1) '@repo/eslint-config': specifier: workspace:* version: link:packages/eslint-config @@ -914,6 +917,24 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} + '@ianvs/prettier-plugin-sort-imports@4.7.1': + resolution: {integrity: sha512-jmTNYGlg95tlsoG3JLCcuC4BrFELJtLirLAkQW/71lXSyOhVt/Xj7xWbbGcuVbNq1gwWgSyMrPjJc9Z30hynVw==} + peerDependencies: + '@prettier/plugin-oxc': ^0.0.4 || ^0.1.0 + '@vue/compiler-sfc': 2.7.x || 3.x + content-tag: ^4.0.0 + prettier: 2 || 3 || ^4.0.0-0 + prettier-plugin-ember-template-tag: ^2.1.0 + peerDependenciesMeta: + '@prettier/plugin-oxc': + optional: true + '@vue/compiler-sfc': + optional: true + content-tag: + optional: true + prettier-plugin-ember-template-tag: + optional: true + '@img/colour@1.0.0': resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==} engines: {node: '>=18'} @@ -6871,6 +6892,17 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} + '@ianvs/prettier-plugin-sort-imports@4.7.1(prettier@3.8.1)': + dependencies: + '@babel/generator': 7.29.1 + '@babel/parser': 7.29.0 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + prettier: 3.8.1 + semver: 7.7.4 + transitivePeerDependencies: + - supports-color + '@img/colour@1.0.0': optional: true From 29dd3793d181eb29617e64b90ca8dbaaf92a968d Mon Sep 17 00:00:00 2001 From: Fing0r Date: Sat, 21 Feb 2026 16:26:20 +0700 Subject: [PATCH 2/9] =?UTF-8?q?feat(ui):=20=D0=BD=D0=B0=D1=81=D1=82=D1=80?= =?UTF-8?q?=D0=BE=D0=B8=D0=BB=20public=20api=20=D0=B4=D0=BB=D1=8F=20ui-kit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui/components.json | 3 ++- packages/ui/package.json | 20 ++++++++++++++------ packages/ui/src/components/index.ts | 12 ++++++++++++ packages/ui/src/index.ts | 2 ++ packages/ui/src/lib/index.ts | 1 + 5 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 packages/ui/src/components/index.ts create mode 100644 packages/ui/src/index.ts create mode 100644 packages/ui/src/lib/index.ts diff --git a/packages/ui/components.json b/packages/ui/components.json index 22b66dcf..80c8d811 100644 --- a/packages/ui/components.json +++ b/packages/ui/components.json @@ -16,7 +16,8 @@ "components": "@repo/ui/components", "ui": "@repo/ui/components", "lib": "@repo/ui/lib", - "utils": "@repo/ui/lib/utils" + "utils": "@repo/ui/lib/utils", + "hooks": "@repo/ui/hooks" }, "registries": {} } diff --git a/packages/ui/package.json b/packages/ui/package.json index 16134c34..03916bfb 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -3,6 +3,7 @@ "version": "0.0.0", "private": true, "exports": { + ".": "./src/index.ts", "./globals.css": "./src/globals.css", "./postcss.config": "./postcss.config.mjs", "./lib/*": "./src/lib/*.ts", @@ -16,6 +17,13 @@ "generate:component": "turbo gen react-component", "check-types": "tsc --noEmit" }, + "peerDependencies": { + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-hook-form": "^7.0.0", + "@hookform/resolvers": "^5.0.0", + "zod": "^4.0.0" + }, "dependencies": { "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", @@ -25,20 +33,20 @@ "tw-animate-css": "^1.4.0" }, "devDependencies": { + "@hookform/resolvers": "^5.2.2", "@repo/eslint-config": "workspace:*", "@repo/typescript-config": "workspace:*", - "@hookform/resolvers": "^5.2.2", - "react": "^19.2.4", - "react-dom": "^19.2.4", - "react-hook-form": "^7.71.1", - "zod": "^4.3.6", "@tailwindcss/postcss": "^4.2.0", "@types/node": "^22.15.3", "@types/react": "19.2.14", "@types/react-dom": "19.2.3", "eslint": "^9.31.0", + "react": "^19.2.4", + "react-dom": "^19.2.4", + "react-hook-form": "^7.71.1", "shadcn": "^3.8.5", "tailwindcss": "^4.2.0", - "typescript": "5.8.2" + "typescript": "5.8.2", + "zod": "^4.3.6" } } diff --git a/packages/ui/src/components/index.ts b/packages/ui/src/components/index.ts new file mode 100644 index 00000000..f81cb38c --- /dev/null +++ b/packages/ui/src/components/index.ts @@ -0,0 +1,12 @@ +export * from './button' +export * from './card' +export * from './dialog' +export * from './dropdown-menu' +export * from './form' +export * from './input' +export * from './label' +export * from './select' +export * from './separator' +export * from './sheet' +export * from './textarea' +export * from './tooltip' diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts new file mode 100644 index 00000000..b8c05a57 --- /dev/null +++ b/packages/ui/src/index.ts @@ -0,0 +1,2 @@ +export * from './components' +export * from './lib' diff --git a/packages/ui/src/lib/index.ts b/packages/ui/src/lib/index.ts new file mode 100644 index 00000000..9c56149e --- /dev/null +++ b/packages/ui/src/lib/index.ts @@ -0,0 +1 @@ +export * from './utils' From bd525bf0f866205dc42309f966f97596f1951c6b Mon Sep 17 00:00:00 2001 From: Fing0r Date: Sat, 21 Feb 2026 16:27:36 +0700 Subject: [PATCH 3/9] =?UTF-8?q?fix(web):=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=20=D0=B8=D0=BC=D0=BF=D0=BE=D1=80=D1=82=D1=8B?= =?UTF-8?q?=20=D0=B8=D0=B7=20@repo/ui?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../authorization/authorization-dialog-layout.tsx | 3 ++- apps/web/app/authorization/authorization-dialog.tsx | 8 ++++---- apps/web/app/authorization/authorization-form.tsx | 13 +++++-------- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/apps/web/app/authorization/authorization-dialog-layout.tsx b/apps/web/app/authorization/authorization-dialog-layout.tsx index fc92559e..e6fe29b3 100644 --- a/apps/web/app/authorization/authorization-dialog-layout.tsx +++ b/apps/web/app/authorization/authorization-dialog-layout.tsx @@ -1,6 +1,7 @@ -import { DialogFooter, DialogHeader, DialogTitle } from '@repo/ui/components/dialog' import type { ReactNode } from 'react' +import { DialogFooter, DialogHeader, DialogTitle } from '@repo/ui' + interface AuthorizationDialogLayoutProps { children?: ReactNode footer?: ReactNode diff --git a/apps/web/app/authorization/authorization-dialog.tsx b/apps/web/app/authorization/authorization-dialog.tsx index 34df77a3..26e0baf5 100644 --- a/apps/web/app/authorization/authorization-dialog.tsx +++ b/apps/web/app/authorization/authorization-dialog.tsx @@ -1,11 +1,11 @@ 'use client' import React from 'react' -import { Button } from '@repo/ui/components/button' -import { Dialog, DialogContent, DialogTrigger } from '@repo/ui/components/dialog' -import { Form } from '@repo/ui/components/form' -import { AuthorizationForm } from './authorization-form' + +import { Button, Dialog, DialogContent, DialogTrigger, Form } from '@repo/ui' + import { AuthorizationDialogLayout } from './authorization-dialog-layout' +import { AuthorizationForm } from './authorization-form' import { useAuthorizationForm } from './use-authorization-form' const AuthorizationDialog = () => { diff --git a/apps/web/app/authorization/authorization-form.tsx b/apps/web/app/authorization/authorization-form.tsx index fc2e3e6c..c0f1bba5 100644 --- a/apps/web/app/authorization/authorization-form.tsx +++ b/apps/web/app/authorization/authorization-form.tsx @@ -1,13 +1,10 @@ -import { - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from '@repo/ui/components/form' -import { Input } from '@repo/ui/components/input' +'use client' + import React from 'react' import { useFormContext } from 'react-hook-form' + +import { FormControl, FormField, FormItem, FormLabel, FormMessage, Input } from '@repo/ui' + import { AuthorizationFormValues } from './use-authorization-form' const AuthorizationForm = () => { From 57cb7c3700ee0c131290303a8a330ce3b2c48b81 Mon Sep 17 00:00:00 2001 From: Fing0r Date: Sat, 21 Feb 2026 16:47:27 +0700 Subject: [PATCH 4/9] =?UTF-8?q?docs(ui):=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D1=8E=20=D0=B4=D0=BB=D1=8F=20ui-kit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui/README.md | 468 ++++++++++++++++++++++++++++ packages/ui/src/components/index.ts | 2 + 2 files changed, 470 insertions(+) create mode 100644 packages/ui/README.md diff --git a/packages/ui/README.md b/packages/ui/README.md new file mode 100644 index 00000000..572e6847 --- /dev/null +++ b/packages/ui/README.md @@ -0,0 +1,468 @@ +# @repo/ui + +UI-kit на основе Radix UI и Tailwind CSS + +## Установка + +Пакет доступен как часть монорепозитория. Добавьте зависимость в `package.json`: + +```json +{ + "dependencies": { + "@repo/ui": "workspace:*" + } +} +``` + +## Использование + +Все компоненты доступны через единый импорт: + +```tsx +import { Button, Card, Input, Avatar } from '@repo/ui' +``` + +## Добавление новых компонентов + +Для добавления компонентов из shadcn/ui выполните команду из директории `packages/ui`: + +```bash +cd packages/ui +npx shadcn@latest add +``` + +После добавления компонента не забудьте добавить экспорт в `src/components/index.ts`: + +```ts +export * from './new-component' +``` + +## Известные проблемы + +### Типы lucide-react + +Временный костыль: типы для иконок из `lucide-react` объявлены вручную в файле `src/lucide-react.d.ts`. + +Если после добавления нового компонента возникает ошибка типов для иконки, добавьте её в этот файл: + +```ts +// src/lucide-react.d.ts +declare module 'lucide-react' { + export const NewIcon: LucideIcon +} +``` + +## Компоненты + +### Button + +Кнопка с различными вариантами и размерами. + +```tsx +import { Button } from '@repo/ui' + +// Варианты +return ( + <> + + + + + + + +) + +// Размеры +return ( + <> + + + + + + +) +``` + +### Input + +Поле ввода текста. + +```tsx +import { Input } from '@repo/ui' + +return ( + <> + + + + + +) +``` + +### Card + +Карточка для группировки контента. + +```tsx +import { + Card, + CardHeader, + CardTitle, + CardDescription, + CardContent, + CardFooter, + CardAction, +} from '@repo/ui' +return ( + + + Заголовок карточки + Описание карточки + + + + + +

Содержимое карточки

+
+ + + +
+) +``` + +### Avatar + +Аватар пользователя с поддержкой изображений и fallback. + +```tsx +import { + Avatar, + AvatarImage, + AvatarFallback, + AvatarBadge, + AvatarGroup, + AvatarGroupCount, +} from '@repo/ui' + +// Простой аватар +return ( + + + ИП + +) + +// С размером +return ( + <> + + SM + + + LG + + +) + +// С бейджем (например, статус онлайн) +return ( + + + ИП + + +) + +// Группа аватаров +return ( + + + А + + + Б + + +5 + +) +``` + +### Badge + +Бейдж для отображения статусов и меток. + +```tsx +import { Badge } from '@repo/ui' + +return ( + <> + Default + Secondary + Destructive + Outline + +) +``` + +### Form + +Компоненты для работы с формами (интеграция с react-hook-form). + +```tsx +import { + Form, + FormField, + FormItem, + FormLabel, + FormControl, + FormDescription, + FormMessage, +} from '@repo/ui' +import { useForm } from 'react-hook-form' + +const form = useForm() + +return ( +
+ ( + + Email + + + + Ваш рабочий email + + + )} + /> + +) +``` + +### Dialog + +Модальное окно. + +```tsx +import { + Dialog, + DialogTrigger, + DialogContent, + DialogHeader, + DialogTitle, + DialogDescription, + DialogFooter, + DialogClose, +} from '@repo/ui' + +return ( + + + + + + + Заголовок + Описание диалога + +

Содержимое диалога

+ + + + + + +
+
+) +``` + +### Select + +Выпадающий список. + +```tsx +import { + Select, + SelectTrigger, + SelectValue, + SelectContent, + SelectItem, + SelectGroup, + SelectLabel, +} from '@repo/ui' + +return ( + +) +``` + +### Textarea + +Многострочное поле ввода. + +```tsx +import { Textarea } from '@repo/ui' + +return ( + <> +