# @tnsu/ui-kit — память проекта Единый пакет UI-компонентов для SPFx web part'ов ТНСУ + Storybook как витрина. Этот файл — источник правды по решениям, плану и прогрессу. Обновлять по ходу работы. ## Зачем проект У команды много SPFx web part'ов в **разных репозиториях** (request-portal, бывший 1c-ticket-form, pto-tracker и др.). В каждом дизайн разъезжается, компоненты копируются и пишутся заново. Цель — вынести компоненты в один npm-пакет, подключать его в любую web part через `npm i`, и держать единый вид через дизайн-токены. Источник компонентов: `request-portal/src/webparts/requestPortal/shared/ui/` — там уже ~30 чистых компонентов на SCSS-модулях с barrel-экспортом (`ui/index.ts`). Это база. ## Ключевые архитектурные решения - **Гибридный подход**: отдельный репозиторий `tnsu-ui-kit` (пакет + Storybook), публикуется в GitLab Package Registry. Существующие web part'ы остаются в своих репах и просто ставят пакет. НЕ монорепо (не хотим переселять существующие проекты). - **Сборка — Vite (library mode)**, не tsup. Причина: компоненты на `.module.scss`, Vite понимает SCSS-модули из коробки и он же движок Storybook → один инструмент. - **React/Fluent/tslib — только `peerDependencies`** (React 17, @fluentui/react 8, tslib). Защита от двух React в бандле («Invalid hook call»). Локально те же версии стоят как devDependencies для сборки и Storybook. - **Дизайн-токены** (`tokens.scss`: цвета, отступы, радиусы) — единый рычаг общего вида. Компоненты тянут значения оттуда, а не хардкодят. - **Скоуп имени `@tnsu`** — сверить с именем группы в GitLab на шаге публикации. Пока имя ни на что не влияет, переименование = find-replace. - **Что переносим**: только чистые UI-примитивы (Button, TextInput, FormCard, Select, ItemsTable, PeopleField...). НЕ переносим бизнес-логику: `approval/`, `pnp/`, `dictionary/`, сервисы SharePoint — они привязаны к спискам. Возможно позже отдельный пакет `@tnsu/sp-core`. - **Расширение через пропсы**, не форки. Если в старом проекте компонент выглядел иначе — добавляем `variant`/`size` в ui-kit, а не плодим копии. - **Версии инструментов синхронны с SPFx**: TypeScript пинить на `~5.8.0` (как в request-portal). Без пина `npm i typescript` ставит TS 7 (нативный компилятор без JS Compiler API) — vite-plugin-dts падает. То же правило для React/Fluent. ## План (маршрут) 1. [x] Скелет репо — папка, git, package.json, зависимости 2. [x] Сборка (Vite) — vite.config.ts, пакет собирается в dist/ 3. [x] Первый компонент — Button перенесён, сборка чистая 4. [x] Дизайн-токены — src/tokens/_tokens.scss перенесён из request-portal 5. [x] Storybook — витрина работает (SB 10.4 + Vite), Button виден со всеми вариантами 6. [x] Публикация — @tnsu/ui-kit@0.0.1 опубликован в Gitea (это Gitea 1.26.4, НЕ GitLab!) 7. [~] Потребление проверено ПОЛНОСТЬЮ: request-portal собрался (heft webpack ок) + кнопки из пакета отрисовались в SharePoint workbench со стилями (accent-золото, secondary-рамки). CSS из пакета применяется в рантайме. Осталась публикация в registry. ВАЖНО про потребление (проверено 2026-08-13): - Тест через локальный тарбол (`npm pack` → `npm i ../tnsu-ui-kit/*.tgz`), НЕ npm link (link тащит второй React → Invalid hook call). - CSS подключается в SPFx через `import '@tnsu/ui-kit/styles.css'` в корневом компоненте веб-парта (RequestPortal.tsx). SPFx-webpack (5.95) обрабатывает .css из node_modules — ОК. - Заменён Button в SubmitActions.tsx (`../Button/Button` → `@tnsu/ui-kit`). Правки НЕ коммитить, пока пакет не опубликован в registry (сейчас ссылается на file:-тарбол). Известный tech-debt: Sass `@import` устарел (Dart Sass 3.0). Мигрировать токены и модули на `@use`/`@forward` — отдельной задачей, сейчас работает с варнингом. ## Прогресс / журнал - **Шаг 1 готов**: создан репо `C:\Users\gorodetskiy.timur\Documents\Projects\tnsu-ui-kit`, `git init`, болванка package.json. - **Шаг 2 в работе**: переписан package.json (@tnsu/ui-kit, exports, peerDeps, Vite-скрипты), ставятся devDependencies, добавлен .gitignore. ## Как мигрировать старый проект (памятка на будущее) 1. `npm i @tnsu/ui-kit` — ничего не ломается, пакет просто лежит рядом. 2. Заменяем импорты по одному компоненту/форме: `../shared/ui` → `@tnsu/ui-kit`. Пропсы те же, JSX не меняется. Старый и новый компонент могут сосуществовать. 3. Проверили форму → удалили старый компонент из `shared/ui`. 4. Повторяем, пока `shared/ui` не опустеет. 5. Перед миграцией проекта проверить: его версии React/Fluent совместимы с peerDeps ui-kit. ## Публикация (Gitea, НЕ GitLab!) - Хостинг git — **Gitea 1.26.4** на http://git.tnsu.kz (не GitLab). Registry npm привязан к ВЛАДЕЛЬЦУ, не к проекту. Никакого "project ID" не нужно. - Адрес registry: `http://git.tnsu.kz/api/packages/timur.gorodetskiy/npm/` - `.npmrc` в проекте (можно коммитить, НЕ секрет): `@tnsu:registry=http://git.tnsu.kz/api/packages/timur.gorodetskiy/npm/` - Токен (СЕКРЕТ) — в `~/.npmrc` (C:\Users\gorodetskiy.timur\.npmrc), в git НЕ попадает: `//git.tnsu.kz/api/packages/timur.gorodetskiy/npm/:_authToken=` - Токен создаётся в Gitea: аватар → Настройки → Приложения → права `package` = Чтение и запись. - Публикация: `npm run build && npm publish`. Бамп версии в package.json перед каждой публикацией (npm не даёт перезаписать уже опубликованную версию). - Потребителю (request-portal и др.) нужен такой же `@tnsu:registry` в его `.npmrc` + свой токен на чтение пакетов. ## Окружение - Node: v22.x (как в SPFx: >=22.14 <23) - React 17.0.1, @fluentui/react ^8.106.4, tslib 2.3.1 - GitLab: http://git.tnsu.kz/timur.gorodetskiy/tnsu-ui-kit.git