npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@ilb/keepdocs-ui

v2.0.2

Published

React UI library for document management service

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 должен указывать на прокси-эндпоинт, который:

  1. Проксирует запросы на сервер keep-docs
  2. Автоматически добавляет Bearer токен для аутентификации
  3. Обрабатывает 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