npm package: @kpmi/lumen
Description: React component library built on shadcn/ui patterns with a custom KPMI design system.
Latest version: 0.14.0

# @kpmi/lumen

React component library built on shadcn/ui patterns with a custom KPMI design system.

---

## Инструкция по добавлению нового компонента

### Структура каждого компонента

Каждый компонент живёт в своей директории `src/components/<component-name>/` и содержит хотя бы три файла:

```
src/components/my-component/
├── my-component.tsx         # Сам компонент
├── my-component.stories.tsx # Stories для Storybook
└── index.ts                 # Barrel-экспорт
```

---

### Шаг 1. Создать файл компонента

Есть два варианта:

#### Вариант А — Установить через shadcn/ui

Если компонент уже есть в библиотеке shadcn:

```bash
npx shadcn@latest add <component-name>
```

shadcn сам создаст директорию `src/components/<component-name>/` с файлом компонента и установит нужные Radix-зависимости. После установки — адаптировать стили под дизайн-систему KPMI.

#### Вариант Б — Создать с нуля

Создать директорию вручную и добавить файл компонента:

```tsx
import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils/index";

const myComponentVariants = cva("base-classes", {
  variants: {
    variant: {
      default: "...",
    },
  },
  defaultVariants: {
    variant: "default",
  },
});

export interface MyComponentProps
  extends
    React.HTMLAttributes<HTMLDivElement>,
    VariantProps<typeof myComponentVariants> {}

const MyComponent = React.forwardRef<HTMLDivElement, MyComponentProps>(
  ({ className, variant, ...props }, ref) => (
    <div
      className={cn(myComponentVariants({ variant, className }))}
      ref={ref}
      {...props}
    />
  ),
);
MyComponent.displayName = "MyComponent";

export { MyComponent, myComponentVariants };
```

> **Важные паттерны:**
>
> - `React.forwardRef` — обязателен для всех компонентов
> - `displayName` — обязателен для отображения в DevTools
> - `cn()` — всегда использовать для объединения классов
> - Если нужна поддержка `asChild`, добавить `Slot` из `@radix-ui/react-slot`

---

### Шаг 2. Создать barrel-экспорт

**`src/components/my-component/index.ts`**

```ts
export * from "./my-component";
```

---

### Шаг 3. Создать Storybook stories

**`src/components/my-component/my-component.stories.tsx`**

```tsx
import type { Meta, StoryObj } from "@storybook/react";
import { MyComponent } from "./my-component";

const meta = {
  title: "UI/MyComponent",
  component: MyComponent,
  parameters: {
    layout: "centered",
  },
  tags: ["autodocs"],
  argTypes: {
    variant: {
      control: { type: "select" },
      options: ["default"],
    },
  },
} satisfies Meta<typeof MyComponent>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
  args: {
    children: "Пример",
    variant: "default",
  },
};

export const Variants: Story = {
  render: () => (
    <div style={{ display: "flex", gap: "1rem" }}>
      <MyComponent variant="default">Вариант 1</MyComponent>
    </div>
  ),
};
```

---

### Шаг 4. Зарегистрировать в общем экспорте

Добавить строку в **`src/components/index.ts`**:

```ts
export * from "./my-component";
```

---

### Шаг 5. Добавить subpath export в `package.json`

В раздел `"exports"` добавить запись для прямого импорта (`@kpmi/lumen/my-component`):

```json
"./my-component": {
  "types": "./dist/types/components/my-component/index.d.ts",
  "import": "./dist/esm/components/my-component/index.js"
}
```

---

### Шаг 6. Проверить результат

```bash
# Запустить Storybook для визуальной проверки
npm run storybook

# Проверить типы
npm run typecheck

# Проверить линтер
npm run lint:all

# Полная сборка для финальной проверки
npm run build
```

---

### Итоговый чеклист

| #   | Задача                                                   | Обязательно    |
| --- | -------------------------------------------------------- | -------------- |
| 1   | Создан `my-component.tsx` с `forwardRef` и `displayName` | ✅             |
| 2   | Создан `index.ts` с barrel-экспортом                     | ✅             |
| 3   | Создан `my-component.stories.tsx` с `Default` story      | ✅             |
| 4   | Добавлен экспорт в `src/components/index.ts`             | ✅             |
| 5   | Добавлен subpath в `package.json` → `"exports"`          | ✅             |
| 6   | Пройдена проверка `typecheck` и `lint:all`               | ✅             |
| 7   | Установлен shadcn-примитив (если нужен)                  | ⬜ опционально |