@ilb/keepdocs-ui
v2.0.2
Published
React UI library for document management service
Keywords
Readme
Keep Docs UI
Современная React UI библиотека для работы с сервисом хранения документов. Обеспечивает полноценное управление документами с поддержкой версионирования, интерактивного просмотра и продвинутой навигации.
🚀 Установка
npm install @keep-docs/ui📖 Использование
import React from 'react';
import { KeepDocs } from '@keep-docs/ui';
import '@keep-docs/ui/styles/index.css';
const config = {
baseUrl: 'http://localhost:3333/api/proxydocs',
schema: 'client_dossier'
};
const params = {
statusCode: 'CREATION',
userType: 'INDIVIDUAL'
};
const uuid = '550e8400-e29b-41d4-a716-446655440000';
function App() {
const handleError = (error: string) => {
console.error('Keep Docs Error:', error);
};
const handleInit = (dossier) => {
console.log('Dossier initialized:', dossier);
};
return (
<KeepDocs
uuid={uuid}
config={config}
params={params}
onError={handleError}
onInit={handleInit}
/>
);
}KeepDocsSingle
Компонент для работы с одним документом. Используется совместно с KeepDocsSchemaProvider для оптимальной загрузки схемы.
import React from 'react';
import { KeepDocsSchemaProvider, KeepDocsSingle } from '@keep-docs/ui';
import '@keep-docs/ui/styles/index.css';
const config = {
baseUrl: 'http://localhost:3333/api/proxydocs',
schema: 'strizh_entity_business'
};
const uuid = '550e8400-e29b-41d4-a716-446655440000';
function App() {
return (
<KeepDocsSchemaProvider config={config} uuid={uuid}>
<KeepDocsSingle
documentType="passport_first_page"
onError={(error) => console.error('Passport error:', error)}
onUpdate={(doc) => console.log('Passport updated:', doc)}
/>
<KeepDocsSingle
documentType="passport_registration"
onError={(error) => console.error('Registration error:', error)}
onUpdate={(doc) => console.log('Registration updated:', doc)}
/>
</KeepDocsSchemaProvider>
);
}Преимущества:
- ✅ Одна загрузка схемы для всех компонентов
- ✅ Автоматическое обновление после загрузки файлов
- ✅ Компактный интерфейс для одного документа
- ✅ Поддержка множественных экземпляров на странице
📋 Props
KeepDocs
| Prop | Тип | Обязательный | Описание |
|---------------|----------------------------------------|--------------|-----------------------------------------|
| config | DocumentManagerConfig | ✅ | Конфигурация подключения к API |
| uuid | string | ✅ | UUID досье |
| defaultTab? | string | ❌ | Активная вкладка по умолчанию |
| params? | { [key: string]: any } | ❌ | Параметры для фильтрации и прав доступа |
| onError? | (error: string) => void | ❌ | Обработчик ошибок |
| onInit? | (dossier: Dossier) => void | ❌ | Вызывается после инициализации |
| onUpdate? | (document: Document) => void | ❌ | Вызывается после загрузки документа |
| onRemove? | (type: string, uuid: string) => void | ❌ | Вызывается после удаления страницы |
KeepDocsSchemaProvider
| Prop | Тип | Обязательный | Описание |
|------------|-------------------------|--------------|--------------------------------|
| config | DocumentManagerConfig | ✅ | Конфигурация подключения к API |
| uuid | string | ✅ | UUID досье |
| children | ReactNode | ✅ | Дочерние компоненты |
KeepDocsSingle
| Prop | Тип | Обязательный | Описание |
|----------------|-------------------------------|--------------|-------------------------------------|
| documentType | string | ✅ | Тип документа из схемы |
| onError? | (error: string) => void | ❌ | Обработчик ошибок |
| onUpdate? | (document: Document) => void| ❌ | Вызывается после загрузки документа |
DocumentManagerConfig
interface DocumentManagerConfig {
baseUrl: string; // URL прокси-эндпоинта
schema: string; // Имя схемы документов
}Настройка прокси-сервера
Важно: baseUrl должен указывать на прокси-эндпоинт, который:
- Проксирует запросы на сервер keep-docs
- Автоматически добавляет Bearer токен для аутентификации
- Обрабатывает CORS если необходимо
Пример прокси-эндпоинта (Next.js API Route):
// pages/api/proxydocs/[...path].ts
import { NextApiRequest, NextApiResponse } from 'next';
export const config = {
api: {
bodyParser: false, // Отключаем встроенный парсер для multipart/form-data
},
};
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const { path } = req.query;
const pathString = Array.isArray(path) ? path.join('/') : path;
// Получаем Bearer токен из сессии/cookies/headers
const token = req.headers.authorization || await getTokenFromSession(req);
// Подготавливаем headers, исключая host и content-length
const forwardHeaders = { ...req.headers };
delete forwardHeaders.host;
delete forwardHeaders['content-length'];
// Добавляем Authorization header
forwardHeaders['authorization'] = `Bearer ${token}`;
let body;
if (req.method !== 'GET' && req.method !== 'HEAD') {
// Для multipart/form-data и других типов - передаем raw body
body = await getRawBody(req);
}
const response = await fetch(`${process.env.KEEP_DOCS_SERVER_URL}/${pathString}`, {
method: req.method,
headers: forwardHeaders,
body: body,
});
// Проксируем response headers
response.headers.forEach((value, key) => {
res.setHeader(key, value);
});
// Возвращаем response как stream для больших файлов
res.status(response.status);
if (response.body) {
const reader = response.body.getReader();
const pump = () => reader.read().then(({ done, value }) => {
if (done) {
res.end();
return;
}
res.write(value);
return pump();
});
return pump();
} else {
res.end();
}
}
// Утилита для получения raw body
async function getRawBody(req: NextApiRequest): Promise<Buffer> {
return new Promise((resolve, reject) => {
const chunks: Buffer[] = [];
req.on('data', (chunk) => chunks.push(chunk));
req.on('end', () => resolve(Buffer.concat(chunks)));
req.on('error', reject);
});
}Альтернативный вариант с http-proxy-middleware:
// pages/api/proxydocs/[...path].ts
import { createProxyMiddleware } from 'http-proxy-middleware';
import { NextApiRequest, NextApiResponse } from 'next';
export const config = {
api: {
bodyParser: false,
externalResolver: true,
},
};
const proxy = createProxyMiddleware({
target: process.env.KEEP_DOCS_SERVER_URL,
changeOrigin: true,
pathRewrite: {
'^/api/proxydocs': '', // удаляем префикс
},
onProxyReq: (proxyReq, req) => {
// Добавляем Bearer токен
const token = getTokenFromRequest(req);
if (token) {
proxyReq.setHeader('Authorization', `Bearer ${token}`);
}
},
});
export default function handler(req: NextApiRequest, res: NextApiResponse) {
return proxy(req, res);
}Схема работы:
[Keep Docs UI] → [Ваш прокси /api/proxydocs] → [Keep Docs Server]
↑ добавляет Bearer токен✨ Функциональность
📁 Управление документами
- ✅ Система вкладок с автоматической фильтрацией по схеме
- ✅ Drag & Drop загрузка файлов с поддержкой множественного выбора
- ✅ Версионирование документов
- ✅ Превью документов всех поддерживаемых форматов
🖼️ Интерактивный просмотр изображений
- ✅ Модальное окно для полноэкранного просмотра
- ✅ Навигация между страницами с помощью кнопок и клавиш стрелок
- ✅ Масштабирование (zoom in/out) с поддержкой колеса мыши
- ✅ Поворот изображений на 90°, 180°, 270°
- ✅ Сброс к исходному состоянию
🎛️ Управление страницами
- ✅ Добавление/Удаление страниц
- ✅ Скачивание отдельных страниц и целых документов
♿ Доступность (a11y)
- ✅ Полная поддержка клавиатуры для всех интерактивных элементов
- ✅ ARIA-атрибуты для скринридеров
- ✅ Семантическая разметка с правильными ролями
- ✅ Focus management в модальных окнах
🔧 Техническое
- ✅ TypeScript поддержка из коробки
- ✅ Обработка ошибок с детальными сообщениями
- ✅ Состояния загрузки с индикаторами прогресса
- ✅ Мемоизация для оптимизации производительности
🎨 Стили
Подключите CSS файл для корректного отображения:
import '@keep-docs/ui/styles/index.css';Кастомизация темы
Библиотека поддерживает CSS переменные для настройки внешнего вида:
🎯 Горячие клавиши
В модальном окне просмотра:
Esc- Закрыть модальное окно←/→- Навигация между страницами+/-- Увеличение/уменьшение масштабаR- Поворот изображенияSpace- Сброс к исходному состоянию
🛠️ Разработка
# Установка зависимостей
npm install
# Сборка библиотеки
npm run build
# Режим разработки с hot reload
npm run dev
# Проверка типов TypeScript
npm run typecheck
# Линтинг и исправление кода
npm run lint
npm run lint:fix
# Форматирование кода
npm run format