npm package: @qkit-emr/web-ui
Description: Shared UI Component Library for EMR Monorepo
Author: QKIT-Software company
Latest version: 2.0.9

# @qkit-emr/web-ui

Thư viện UI component dùng chung cho hệ thống EMR (Electronic Medical Record) Monorepo, được xây dựng trên nền tảng React, TypeScript và Tailwind CSS với tích hợp shadcn/ui.

## 🚀 Tính năng chính

- **Atomic Design**: Tổ chức component theo nguyên tắc Atomic Design (atoms, molecules, organisms, templates, pages)
- **shadcn/ui Integration**: Tích hợp đầy đủ các component từ shadcn/ui với customization
- **Separate Client/Server Exports**: Tối ưu bundle size với entry points riêng cho client và server ⚡
- **TypeScript**: Full TypeScript support với type safety
- **Tailwind CSS**: Built on Tailwind CSS với utility-first approach
- **Responsive Design**: Mobile-first responsive design với breakpoints chuẩn
- **Accessibility**: WCAG 2.1 AA compliant components
- **Theme Support**: Light/dark theme switching
- **Healthcare UI**: Components được tối ưu cho giao diện y tế
- **Performance**: Optimized cho healthcare applications với tree-shaking tối ưu

## 📦 Cài đặt

```bash
npm install @qkit-emr/web-ui
```

## 🎯 Sử dụng cơ bản

### Import Strategy - Hybrid Approach ⚡

Từ phiên bản **1.7.0**, `@qkit-emr/web-ui` hỗ trợ **hybrid import pattern** - kết hợp tốt nhất của simple imports và optimized server utilities:

#### ✅ **Recommended: Client Components (Simple & Clean)**

```tsx
'use client'

// ✅ Import client components & hooks từ root (simple)
import { 
  Button, 
  Card, 
  Input, 
  useTheme, 
  useFormField,
  cn
} from '@qkit-emr/web-ui'

export function PatientForm() {
  const { theme } = useTheme()
  
  return (
    <Card className={cn('p-6', theme === 'dark' && 'bg-gray-800')}>
      <h2 className="text-xl font-bold mb-4">Quản lý bệnh nhân</h2>
      <Input placeholder="Tìm kiếm bệnh nhân..." className="mb-4" />
      <Button>Thêm bệnh nhân mới</Button>
    </Card>
  )
}
```

#### ✅ **Server Components (Explicit & Optimized)**

```tsx
// ✅ Import server utilities & types từ /server (explicit)
import { cn, colors, BREAKPOINTS } from '@qkit-emr/web-ui/server'
import { PatientForm } from '@/components/PatientForm' // Client component

export default function PatientsPage() {
  return (
    <div 
      className={cn('container', 'mx-auto', 'p-4')}
      style={{ 
        maxWidth: BREAKPOINTS.xl,
        backgroundColor: colors.background.default 
      }}
    >
      <h1 className="text-2xl font-bold">Patients</h1>
      <PatientForm />
    </div>
  )
}
```

#### 💡 **Alternative: Pure UI Components**

```tsx
'use client'

// Alternative: Import từ /ui nếu chỉ cần pure shadcn/ui
import { Button, Card, Input } from '@qkit-emr/web-ui/ui'

export function SimpleCard() {
  return (
    <Card>
      <Input placeholder="Search..." />
      <Button variant="default" size="lg">
        Click me
      </Button>
    </Card>
  )
}
```

#### 🔄 **Advanced: Full Separation (Optional)**

```tsx
'use client'

// Optional: Import từ /client nếu muốn explicit separation
import { Button, Card, useTheme } from '@qkit-emr/web-ui/client'

function App() {
  const { theme } = useTheme()
  return (
    <Card className="p-6">
      <Button>Themed Button</Button>
    </Card>
  )
}
```

### 📊 Bundle Size & Usage Comparison

| Pattern | Client Import | Server Import | Total Bundle | Use Case |
|---------|--------------|---------------|--------------|----------|
| **Hybrid (Recommended)** ⭐ | Root (~250KB) | `/server` (~20KB) | ~270KB | ✅ Best DX + Server optimization |
| Full Separation | `/client` (~180KB) | `/server` (~20KB) | ~200KB | ✅ Maximum optimization |
| Pure UI Only | `/ui` (~150KB) | `/server` (~20KB) | ~170KB | ✅ Lightweight UI-only |

**Why Hybrid Pattern?**
- ✅ **Simple client imports** - không cần remember paths
- ✅ **Explicit server separation** - clear intent, minimal bundle
- ✅ **Best developer experience** - easy to read & maintain
- ✅ **Server optimization** - chỉ ~20KB cho server utilities

**Note:** Root import (~250KB) là acceptable cho client vì client components thường cần nhiều features. Optimization tập trung vào server components với `/server` entry point (~20KB).

> **💡 Learn More:** Xem [MIGRATION-GUIDE-CLIENT-SERVER.md](./MIGRATION-GUIDE-CLIENT-SERVER.md) để biết chi tiết patterns và best practices.

### Setup Tailwind CSS

**Bắt buộc** thêm `content` path tới dist của thư viện (để Tailwind sinh đủ class cho component) và preset:

```js
module.exports = {
  content: [
    "./src/**/*.{js,ts,jsx,tsx}",
    "./node_modules/@qkit-emr/web-ui/dist/**/*.{js,ts,jsx,tsx}",
  ],
  presets: [require("@qkit-emr/web-ui/tailwind.preset")],
}
```

> **Dùng từ NPM:** Xem [docs/CONSUMING-NPM.md](./docs/CONSUMING-NPM.md) để biết vì sao bản npm có thể “không giống Storybook” và checklist đầy đủ (content, preset, thứ tự CSS, peer deps).

### Import styles

```tsx
import '@qkit-emr/web-ui/styles';
```

## 🏗️ Cấu trúc component chi tiết

### 📋 **ATOMS** - Thành phần cơ bản nhất

#### **Self-Implemented Atoms (Complex - có thư mục riêng)**
```tsx
import { 
  Button, 
  ButtonGroup, 
  ButtonGroupItem, 
  useButtonGroup,
  Input, 
  InputAtom, 
  MemoizedInputAtom,
  Label, 
  LabelAtom, 
  MemoizedLabelAtom,
  Icon 
} from '@qkit-emr/web-ui';

// Button với variants và medical-specific features
<Button variant="primary" size="md" medical>Khám bệnh</Button>
<ButtonGroup>
  <ButtonGroupItem>Lưu</ButtonGroupItem>
  <ButtonGroupItem>Hủy</ButtonGroupItem>
</ButtonGroup>

// Input với validation và medical masks
<Input placeholder="Nhập tên bệnh nhân" />
<InputAtom type="phone" mask="(999) 999-9999" />

// Label với accessibility
<Label htmlFor="patient-name">Họ và tên</Label>

// Icon với medical icon mapping
<Icon name="stethoscope" size="md" />
```

#### **UI-Dependent Atoms (Simple - single file)**
```tsx
import {
  // Data Display
  BadgeAtom,
  StatusBadgeAtom,
  ProgressAtom,
  TimelineAtom,
  DataTableAtom,
  
  // Form Controls
  DatePickerAtom,
  TimePickerAtom,
  MultiSelectAtom,
  RadioGroupAtom,
  InputOTPAtom,
  SecureInputAtom,
  
  // UI Enhancement
  ModalAtom,
  DrawerAtom,
  TabsAtom,
  AccordionAtom,
  TooltipAtom,
  CarouselAtom,
  
  // Medical-Specific
  LabResultAtom,
  
  // Utilities
  SpinnerAtom as Spinner,
  DividerAtom as Divider,
  TypographyAtom as Typography,
  FileInputAtom
} from '@qkit-emr/web-ui';

// Medical status badges
<StatusBadgeAtom status="critical" />
<StatusBadgeAtom status="stable" />
<StatusBadgeAtom status="discharged" />

// Progress indicators
<ProgressAtom value={75} label="Tiến độ điều trị" />

// Medical timeline
<TimelineAtom items={medicalEvents} />

// Lab results display
<LabResultAtom 
  testName="Xét nghiệm máu"
  result="120 mg/dL"
  normalRange="70-100 mg/dL"
  status="high"
/>

// Secure input for sensitive data
<SecureInputAtom 
  placeholder="Nhập mật khẩu"
  showToggle={true}
/>

// OTP input for 2FA
<InputOTPAtom length={6} />

// Medical file upload
<FileInputAtom 
  accept=".pdf,.jpg,.png"
  maxSize={5 * 1024 * 1024} // 5MB
  medical={true}
/>
```

#### **Typography Atoms**
```tsx
import {
  Heading1,
  Heading2, 
  Heading3,
  Paragraph,
  Caption,
  ErrorText,
  SuccessText
} from '@qkit-emr/web-ui';

<Heading1>Tiêu đề chính</Heading1>
<Heading2>Tiêu đề phụ</Heading2>
<Paragraph>Nội dung văn bản</Paragraph>
<ErrorText>Thông báo lỗi</ErrorText>
<SuccessText>Thông báo thành công</SuccessText>
```

### 🧬 **MOLECULES** - Kết hợp Atoms

```tsx
import { 
  FormField,
  SearchBar,
  Alert,
  Badge,
  Card,
  Modal
} from '@qkit-emr/web-ui';

// Form field với validation
<FormField
  label="Họ và tên"
  error="Tên không được để trống"
  required
>
  <Input placeholder="Nhập họ và tên" />
</FormField>

// Search bar với medical context
<SearchBar 
  placeholder="Tìm kiếm bệnh nhân, mã BHYT..."
  onSearch={(value) => console.log(value)}
  medical={true}
/>

// Medical alert
<Alert 
  type="warning"
  title="Cảnh báo thuốc"
  description="Bệnh nhân có tiền sử dị ứng với Penicillin"
/>

// Medical calendar - FullCalendar
<FullCalendar
  events={medicalEvents}
  initialView="timeGridWeek"
  medical={true}
  selectable={true}
  onEventClick={(info) => console.log(info.event)}
  onDateClick={(info) => console.log('Clicked date:', info.date)}
/>
```

#### 📅 **FullCalendar** - Medical Scheduling

**✨ Fully integrated with [shadcn/ui](https://ui.shadcn.com/) design system!**

**⚠️ Important:** FullCalendar CSS is separated from main bundle for optimal performance:

```tsx
// 1️⃣ Import FullCalendar CSS ONLY when using calendar (không tự động load)
import '@qkit-emr/web-ui/fullcalendar-styles';

// 2️⃣ Import component
import { FullCalendar, type MedicalEvent } from '@qkit-emr/web-ui';

// 3️⃣ Define medical events
const appointments: MedicalEvent[] = [
  {
    id: '1',
    title: 'Khám bệnh - Nguyễn Văn A',
    start: '2024-01-15T09:00:00',
    end: '2024-01-15T09:30:00',
    medicalType: 'appointment',
    status: 'confirmed',
    priority: 'normal',
    patientName: 'Nguyễn Văn A',
    doctorName: 'BS. Trần Thị B',
    department: 'Khoa Nội',
    location: 'Phòng 101',
  },
  {
    id: '2',
    title: 'Phẫu thuật - Lê Thị C',
    start: '2024-01-15T14:00:00',
    end: '2024-01-15T16:00:00',
    medicalType: 'surgery',
    status: 'scheduled',
    priority: 'high',
    patientName: 'Lê Thị C',
    doctorName: 'PGS.TS Nguyễn Văn D',
    department: 'Khoa Ngoại',
    location: 'Phòng mổ 1',
  },
  {
    id: '3',
    title: 'Cấp cứu - BHYT',
    start: '2024-01-16T10:30:00',
    medicalType: 'emergency',
    status: 'inProgress',
    priority: 'emergency',
    department: 'Khoa Cấp cứu',
  },
];

// Month view with full event details
<FullCalendar
  events={appointments}
  initialView="dayGridMonth"
  medical={true}
/>

// Month view with dot display (compact)
<FullCalendar
  events={appointments}
  initialView="dayGridMonth"
  medical={true}
  dotView={true}
  dayMaxEvents={3} // Show max 3 events, rest in "+X more"
/>

// Week view with time slots
<FullCalendar
  events={appointments}
  initialView="timeGridWeek"
  medical={true}
  selectable={true}
  editable={true}
  slotMinTime="08:00:00"
  slotMaxTime="18:00:00"
  businessHours={{
    daysOfWeek: [1, 2, 3, 4, 5],
    startTime: '08:00',
    endTime: '18:00',
  }}
  onEventClick={(info) => {
    console.log('Event clicked:', info.event);
  }}
  onSelect={(info) => {
    console.log('Time slot selected:', info.start, 'to', info.end);
  }}
/>

// Day view with drag & drop
<FullCalendar
  events={appointments}
  initialView="timeGridDay"
  medical={true}
  selectable={true}
  editable={true}
  droppable={true}
  nowIndicator={true}
  onEventDrop={(info) => {
    console.log('Event moved:', info.event, 'Delta:', info.delta);
  }}
  onEventResize={(info) => {
    console.log('Event resized:', info.event);
  }}
/>

// List view
<FullCalendar
  events={appointments}
  initialView="listWeek"
  medical={true}
/>
```

**Medical Event Types:**
- `appointment` - Lịch khám bệnh
- `surgery` - Phẫu thuật
- `shift` - Ca trực
- `meeting` - Họp
- `emergency` - Cấp cứu
- `checkup` - Khám định kỳ
- `followup` - Tái khám
- `vaccination` - Tiêm chủng

**Event Status:**
- `scheduled` - Đã lên lịch
- `confirmed` - Đã xác nhận
- `inProgress` - Đang diễn ra
- `completed` - Hoàn thành
- `cancelled` - Đã hủy
- `noShow` - Không đến
- `rescheduled` - Đã dời lịch

**Priority Levels:**
- `low` - Thấp
- `normal` - Bình thường
- `high` - Cao
- `urgent` - Khẩn cấp
- `emergency` - Cấp cứu

### 🧠 **ORGANISMS** - Components phức tạp

```tsx
import { 
  Header,
  Sidebar,
  Navigation,
  DataTable,
  Breadcrumb,
  Pagination
} from '@qkit-emr/web-ui';

// Medical data table
<DataTable
  data={patients}
  columns={[
    { key: 'name', label: 'Họ tên' },
    { key: 'age', label: 'Tuổi' },
    { key: 'diagnosis', label: 'Chẩn đoán' },
    { key: 'status', label: 'Trạng thái' }
  ]}
  pagination={{
    currentPage: 1,
    totalPages: 10,
    onPageChange: (page) => console.log(page)
  }}
  medical={true}
/>

// Medical navigation
<Navigation
  items={[
    { label: 'Dashboard', icon: 'dashboard', href: '/' },
    { label: 'Bệnh nhân', icon: 'users', href: '/patients' },
    { label: 'Lịch hẹn', icon: 'calendar', href: '/appointments' },
    { label: 'Báo cáo', icon: 'chart', href: '/reports' }
  ]}
  medical={true}
/>
```

### 📄 **TEMPLATES** - Layout patterns

```tsx
import {
  AuthTemplate,
  DashboardTemplate,
  DetailTemplate,
  ErrorTemplate,
  FormTemplate,
  ListTemplate
} from '@qkit-emr/web-ui';

// Medical dashboard template
<DashboardTemplate
  header={<Header title="Dashboard Bệnh viện" />}
  sidebar={<Sidebar />}
  content={<DashboardContent />}
  medical={true}
/>

// Patient detail template
<DetailTemplate
  header={<PatientHeader patient={patient} />}
  content={<PatientDetails patient={patient} />}
  actions={<PatientActions patient={patient} />}
  medical={true}
/>

// Medical form template
<FormTemplate
  title="Thêm bệnh nhân mới"
  form={<PatientForm />}
  actions={<FormActions />}
  medical={true}
/>
```

### 📱 **RESPONSIVE SYSTEM** - Mobile-first development

```tsx
import {
  // Responsive Providers & Hooks
  ResponsiveProvider,
  useResponsive,
  
  // Responsive Layout Components
  ResponsiveLayoutContainer,
  ResponsiveGrid,
  
  // Mobile Components
  MobileLayout,
  MobileStack,
  MobileContainer,
  MobileBottomNavigation,
  MobileDrawerNavigation,
  MobileHamburgerMenu,
  
  // Tablet Components
  TabletLayout,
  TabletContainer,
  TabletStack,
  
  // Desktop Components
  DesktopLayout,
  DesktopContainer,
  DesktopStack,
  DesktopGrid,
  
  // Responsive Form Components
  ResponsiveForm,
  ResponsiveFormField,
  ResponsiveInputField,
  ResponsiveSelectField,
  ResponsiveTextareaField,
  ResponsiveCheckboxField,
  ResponsiveRadioField,
  ResponsiveFormActions
} from '@qkit-emr/web-ui';

// Responsive medical form
<ResponsiveProvider>
  <ResponsiveForm>
    <ResponsiveFormField label="Họ và tên">
      <ResponsiveInputField placeholder="Nhập họ và tên" />
    </ResponsiveFormField>
    <ResponsiveFormField label="Ngày sinh">
      <ResponsiveInputField type="date" />
    </ResponsiveFormField>
    <ResponsiveFormActions>
      <Button>Lưu</Button>
      <Button variant="outline">Hủy</Button>
    </ResponsiveFormActions>
  </ResponsiveForm>
</ResponsiveProvider>
```

## 🎨 Theme và Styling

### Theme Provider

```tsx
import { ThemeProvider } from '@qkit-emr/web-ui';

function App() {
  return (
    <ThemeProvider>
      <YourApp />
    </ThemeProvider>
  );
}
```

### Theme Toggle

```tsx
import { useThemeToggle } from '@qkit-emr/web-ui';

function ThemeToggle() {
  const { toggleTheme, theme } = useThemeToggle();
  
  return (
    <Button onClick={toggleTheme}>
      {theme === 'dark' ? '🌞' : '🌙'}
    </Button>
  );
}
```

### Medical Theme Colors

```tsx
// Primary medical colors
className="bg-blue-600 text-white" // Medical blue
className="bg-green-500 text-white" // Success green
className="bg-red-600 text-white"   // Error red
className="bg-yellow-500 text-white" // Warning yellow

// Medical status colors
className="bg-red-100 text-red-800" // Critical
className="bg-yellow-100 text-yellow-800" // Warning
className="bg-green-100 text-green-800" // Stable
className="bg-blue-100 text-blue-800" // Info
```

## 🔧 Customization

### Override component styles

```tsx
import { Button } from '@qkit-emr/web-ui';

// Sử dụng className để override
<Button className="bg-blue-600 hover:bg-blue-700">
  Custom Button
</Button>
```

### Medical variants

```tsx
import { Button } from '@qkit-emr/web-ui';

// Button với medical variant
<Button variant="medical" size="lg">
  Khám bệnh
</Button>
```

## 📱 Responsive Design

Tất cả components đều hỗ trợ responsive design với breakpoints:

- **Mobile**: 320px - 640px (default)
- **Tablet**: 640px+ (`sm:`)
- **Desktop**: 1024px+ (`lg:`, `xl:`, `2xl:`)

```tsx
<Card className="p-4 sm:p-6 lg:p-8">
  <h1 className="text-xl sm:text-2xl lg:text-3xl">
    Responsive Title
  </h1>
</Card>
```

## ♿ Accessibility

Tất cả components đều tuân thủ WCAG 2.1 AA:

- Keyboard navigation support
- Screen reader compatibility
- Focus management
- ARIA labels
- Color contrast compliance

```tsx
<Button aria-label="Thêm bệnh nhân mới">
  <Icon name="plus" />
</Button>
```

## 🧪 Testing

### Unit Testing

```tsx
import { render, screen } from '@testing-library/react';
import { Button } from '@qkit-emr/web-ui';

test('Button renders correctly', () => {
  render(<Button>Test Button</Button>);
  expect(screen.getByRole('button')).toBeInTheDocument();
});
```

### Storybook

Chạy Storybook để xem tất cả components:

```bash
npm run storybook
```

Truy cập online: [https://qkit-emr-share-ui.web.app/](https://qkit-emr-share-ui.web.app/)

## 📚 API Reference

### Button Component

```tsx
interface ButtonProps {
  variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link' | 'medical';
  size?: 'default' | 'sm' | 'lg' | 'icon';
  disabled?: boolean;
  loading?: boolean;
  children: React.ReactNode;
  onClick?: () => void;
  className?: string;
  medical?: boolean; // Medical-specific styling
}
```

### Input Component

```tsx
interface InputProps {
  type?: 'text' | 'email' | 'password' | 'number' | 'tel';
  placeholder?: string;
  value?: string;
  onChange?: (value: string) => void;
  error?: string;
  disabled?: boolean;
  className?: string;
  mask?: string; // Input mask for phone, date, etc.
  medical?: boolean; // Medical-specific validation
}
```

### Medical Components

```tsx
// LabResultAtom
interface LabResultAtomProps {
  testName: string;
  result: string;
  normalRange: string;
  status: 'normal' | 'high' | 'low' | 'critical';
  unit?: string;
  date?: Date;
}

// StatusBadgeAtom
interface StatusBadgeAtomProps {
  status: 'critical' | 'warning' | 'stable' | 'discharged' | 'admitted';
  size?: 'sm' | 'md' | 'lg';
}

// SecureInputAtom
interface SecureInputAtomProps {
  placeholder?: string;
  showToggle?: boolean;
  medical?: boolean; // HIPAA compliance
}
```

## 🔗 Dependencies

### Peer Dependencies

```json
{
  "react": "^18.2.0",
  "react-dom": "^18.2.0",
  "@radix-ui/react-*": "^1.0.0",
  "tailwindcss": "^3.3.0",
  "class-variance-authority": "^0.7.0",
  "clsx": "^2.0.0",
  "tailwind-merge": "^2.0.0"
}
```

### Dev Dependencies

```json
{
  "@types/react": "^18.2.0",
  "@types/react-dom": "^18.2.0",
  "typescript": "~5.8.2"
}
```

## 🚀 Development

### Build

```bash
npm run build
```

### Development mode

```bash
npm run dev
```

### Storybook

```bash
npm run storybook
npm run build-storybook
```

### Testing

```bash
npm test
npm run test:watch
```

### Linting

```bash
npm run lint
npm run lint:fix
```

### Publishing to npm

1. **Đăng nhập**: Chạy `npm login` (hoặc đã login rồi thì bỏ qua). pnpm dùng chung credential với npm.
2. **Publish** (từ root repo):

```bash
pnpm run publish:web-ui
```

Hoặc từ thư mục `libs/web-ui`: `npm run publish:npm`.  
*(CI: set `NPM_TOKEN` trong env hoặc `.env.local` nếu dùng token thay cho login.)*

## 📦 Exports Strategy

### 1️⃣ Root Entry Point (`@qkit-emr/web-ui`) ⭐ **Recommended for Client**

**Use for:** Client components, hooks, providers (cần 'use client' directive)

**Why:** Simple, clean imports - không cần remember complex paths

```tsx
'use client'

import { 
  // Atoms
  Button, Input, Label, Icon,
  
  // Molecules
  Card, Badge, Alert, FormField,
  
  // Organisms
  DataTable, Header, Sidebar,
  
  // Hooks
  useTheme, useFormField, useResponsive,
  
  // Providers
  ThemeProvider, ResponsiveProvider,
  
  // UI Components
  Dialog, DropdownMenu, Select,
  
  // Utils
  cn
} from '@qkit-emr/web-ui'
```

**Bundle Size:** ~250KB (comprehensive, includes everything you need)

### 2️⃣ Server Entry Point (`@qkit-emr/web-ui/server`) ⭐ **Recommended for Server**

**Use for:** Server utilities, types, constants (KHÔNG cần 'use client')

**Why:** Explicit server-only code, minimal bundle (~20KB), clear separation

```tsx
// Server Component - NO 'use client' needed
import { 
  // Utilities
  cn,
  
  // Theme Configuration
  colors, typography, spacing, shadows,
  BREAKPOINTS, animations,
  
  // Types
  type ButtonProps,
  type CardProps,
  type Theme,
  
  // Validators
  emailSchema, phoneSchema
} from '@qkit-emr/web-ui/server'
```

**Bundle Size:** ~20KB (minimal, server-safe, optimized) ✅

### 3️⃣ UI Entry Point (`@qkit-emr/web-ui/ui`) 💡 **Alternative**

**Use for:** Pure shadcn/ui components only (lighter weight alternative)

```tsx
'use client'

import {
  // Pure shadcn/ui components
  Button, Input, Card, Dialog,
  Alert, Badge, Checkbox, Select,
  Table, Tabs, Toast, Tooltip
} from '@qkit-emr/web-ui/ui'
```

**Bundle Size:** ~150KB (pure UI components)

**When to use:** Khi bạn chỉ cần UI components mà không cần custom atoms/molecules/organisms

### 4️⃣ Client Entry Point (`@qkit-emr/web-ui/client`) 🔄 **Advanced**

**Use for:** Explicit client-side separation (advanced use cases)

```tsx
'use client'

import { 
  Button, 
  Card, 
  useTheme, 
  cn 
} from '@qkit-emr/web-ui/client'
```

**Bundle Size:** ~180KB (optimized client bundle)

**When to use:** Khi bạn muốn explicit separation và maximum optimization

### 📋 Import Mapping Table (Hybrid Pattern)

| Component/Hook | Root (Client) | Server | UI | Client |
|---------------|---------------|--------|-----|--------|
| `Button` | ✅ **Recommended** | ❌ | ✅ | ✅ |
| `useTheme` | ✅ **Recommended** | ❌ | ❌ | ✅ |
| `cn` (in client) | ✅ **Recommended** | ❌ | ❌ | ✅ |
| `cn` (in server) | ❌ | ✅ **Recommended** | ❌ | ❌ |
| `colors` | ❌ | ✅ **Only here** | ❌ | ❌ |
| `BREAKPOINTS` | ❌ | ✅ **Only here** | ❌ | ❌ |
| `type ButtonProps` | ❌ | ✅ **Only here** | ❌ | ❌ |

**Recommended Pattern:**
- ✅ Client components → Import từ **root** (`@qkit-emr/web-ui`)
- ✅ Server components → Import từ **/server** (`@qkit-emr/web-ui/server`)

## 🤝 Contributing

1. Fork repository
2. Tạo feature branch (`git checkout -b feature/amazing-feature`)
3. Commit changes (`git commit -m 'Add amazing feature'`)
4. Push to branch (`git push origin feature/amazing-feature`)
5. Tạo Pull Request

### Development Guidelines

- Tuân thủ Atomic Design principles
- Viết TypeScript với strict mode
- Thêm unit tests cho mọi component
- Tạo Storybook stories
- Đảm bảo accessibility compliance
- Responsive design cho mọi component
- Medical-specific features cho healthcare UI

## 📄 License

MIT License - xem file [LICENSE](LICENSE) để biết thêm chi tiết.

## 🆘 Support

- **Issues**: [GitHub Issues](https://github.com/Quy-Khanh-IT/EMR-Monorepo/issues)
- **Documentation**: [Storybook](https://qkit-emr-share-ui.web.app/)
- **Email**: support@qkit-emr.com

## 🔄 Changelog

Xem [CHANGELOG.md](CHANGELOG.md) để biết lịch sử thay đổi.

### Latest Changes (v1.7.0)

- ✅ **Separate Client/Server Exports**: Tối ưu bundle size với entry points riêng
- ✅ **Bundle Size Optimization**: Giảm 28% bundle size với optimized imports
- ✅ **Next.js 13+ Support**: Full support cho App Router với proper 'use client' directives
- ✅ **Migration Guide**: Comprehensive guide để migrate từ legacy imports
- ✅ **Backward Compatible**: Legacy imports vẫn hoạt động

## 📖 Additional Documentation

- 📚 **[Migration Guide](./MIGRATION-GUIDE-CLIENT-SERVER.md)** - Hướng dẫn migrate từ legacy imports
- 🎨 **[Storybook](https://qkit-emr-share-ui.web.app/)** - Component documentation và examples
- 📦 **[Build Guide](./build-guide.md)** - Hướng dẫn build và deploy
- 🔧 **[Architecture](./docs/)** - Chi tiết về architecture và best practices

---

**Made with ❤️ by EMR Team**