160 lines
13 KiB
Markdown
160 lines
13 KiB
Markdown
# @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.
|
||
|
||
## План переноса компонентов (инвентаризация + решения, 2026-08-13)
|
||
|
||
Источник — request-portal `shared/ui/`, `shared/approval/ui/`, `shared/dictionary/ui/`,
|
||
и (фаза 2) `components/`.
|
||
|
||
### Группа 1 — чистая презентация, переносим КАК ЕСТЬ
|
||
Alert, FormCard, FormGrid, FormField, TextInput, TextArea, PhoneInput, MoneyInput,
|
||
Select, Toggle, CollapseSection, FormActions, Icon (+ IconSprite/iconNames),
|
||
RequestNumber, StatusBadge, ErrorOverlay, FormMode (FormModeProvider + useFormReadOnly).
|
||
|
||
### Группа 2 — презентация с нюансами (решения приняты)
|
||
- ConfirmDialog (+ confirmModal), FileDropzone, useFlipRows → переносим КАК ЕСТЬ (проверено: чисты).
|
||
- AttachmentList → переносим, но РАЗВЯЗАТЬ тип: вместо `import { IAttachmentInfo }`
|
||
из attachments.service объявить локальный `{ url: string; fileName: string }`.
|
||
- PrintButton → переносим КАК ЕСТЬ; сохраняем соглашение классов `.rp-print-root` /
|
||
`.rp-no-print` — задокументировать в README, чтобы потребители их соблюдали.
|
||
- ItemsTable → ОБОБЩАЕМ в generic `DataTable` (колонки через проп: {key,title,width?,
|
||
align?,editable?,render?}, value/onChange/readOnly). Excel-вставка — ОПЦИОНАЛЬНАЯ/
|
||
подключаемая (не хардкодить parseExcelRows под ТМЦ; проект даёт свой маппинг/парсер).
|
||
ТМЦ-таблица = конфиг колонок поверх DataTable. Это ОТДЕЛЬНАЯ design-задача (не copy-paste),
|
||
делать позже, сверяя абстракцию со 2-м реальным примером таблицы.
|
||
|
||
### Группа 3 — бизнес-логика / SharePoint, НЕ в ui-kit (как есть)
|
||
PeopleField/PeopleFieldMulti, UserPicker, InitiatorLine, SubmitActions, useRequestSubmit,
|
||
DecisionPanel, ApprovalMatrix, DepartmentPicker, ProjectPicker.
|
||
- SubmitActions — на обсуждении: можно «очистить» от useRequestSubmit → презентационный → в ui-kit.
|
||
- Пикеры — возможно позже РАЗДЕЛИТЬ: презентационный UI (ui-kit) + data-обёртка (проект).
|
||
- Логику согласования — возможно в отдельный пакет @tnsu/approval (или @tnsu/sp-core). На будущее.
|
||
|
||
### Адаптивность (жёсткое требование) — базовый проход СДЕЛАН
|
||
Часть DoD каждого компонента. Основа: в tokens.scss брейкпоинты
|
||
`$bp-xs:350 / $bp-sm:640 / $bp-md:768 / $bp-lg:1024 / $bp-xl:1280` + миксины `below()`/`above()`.
|
||
Проход по компонентам (в 0.2.0):
|
||
- FormGrid / CollapseSection — 2 колонки → 1 на < sm (через below($bp-sm)).
|
||
- TextInput/TextArea/Select — сделаны резиновыми (width:100% + box-sizing) — раньше зависели
|
||
от глобального стиля портала.
|
||
- FormCard — padding 32→18 на < sm.
|
||
- FormActions — кнопки в столбец на всю ширину на < sm (поля согласованы с FormCard 18px).
|
||
- ConfirmDialog — уже адаптивна (overlay padding + max-width).
|
||
- Sidebar — рейл ↔ выезжающий drawer + SidebarToggle (бургер, виден только < md).
|
||
- Мелкие (Alert, Icon, Toggle, Button, AttachmentList, FileDropzone, PrintButton) — уже резиновые.
|
||
ItemsTable→скролл сделаем вместе с обобщением в DataTable.
|
||
|
||
### Группа 4 — навигация / app shell (ФАЗА 2)
|
||
- [СДЕЛАНО, не опубликовано] Sidebar — обобщён (items/brand пропсами, id=string) +
|
||
адаптивный: десктоп-рейл со сворачиванием, < 768px — выезжающий drawer + затемнение
|
||
(mobileOpen/onMobileClose, бургер рисует родитель). Собирается, в index экспортирован.
|
||
Tabs (из CategoryTabs), Breadcrumbs (новый), Sidebar (из SideNav), AppLayout (из RequestPortal),
|
||
Drawer(?). Сначала «расцепить» от роутинга портала → сделать controlled
|
||
(items + activeId + onSelect), потом переносить. Даёт новым приложениям готовую оболочку.
|
||
|
||
### Порядок работ
|
||
1. [СДЕЛАНО в 0.1.0] Быстрая пачка (20 компонентов): вся Группа 1 (кроме ErrorOverlay/
|
||
StatusBadge — оказались связаны с diagnostics/statuses, отложены) + ConfirmDialog/
|
||
FileDropzone/useFlipRows + AttachmentList (тип развязан на локальный {url,fileName}) +
|
||
PrintButton. Сборка чистая, типы ок.
|
||
2. DataTable — отдельной design-задачей.
|
||
3. Группа 3/4 — по мере надобности.
|
||
|
||
## Как мигрировать старый проект (памятка на будущее)
|
||
|
||
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=<TOKEN>`
|
||
- Токен создаётся в Gitea: аватар → Настройки → Приложения → права `package` = Чтение и запись.
|
||
- Публикация: `npm run build && npm publish`. Бамп версии в package.json перед каждой
|
||
публикацией (npm не даёт перезаписать уже опубликованную версию).
|
||
- Потребителю (request-portal и др.) нужен такой же `@tnsu:registry` в его `.npmrc` +
|
||
свой токен на чтение пакетов.
|
||
- ПРОВЕРЕНО: коллега (другой пользователь Gitea) успешно установил @tnsu/ui-kit со своим
|
||
read-токеном — кросс-доступ к личным пакетам работает, переносить в организацию пока НЕ нужно.
|
||
|
||
## Окружение
|
||
|
||
- 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
|