# GNexus UI Kit

UI-kit для веб-интерфейсов GNexus. Текущий стиль: темная cyber/terminal панель с легкой примесью Tokyo Night, IBM Plex Mono, Phosphor Icons, жесткие прямые формы, акцентные бордеры и яркие состояния.

Проект выделен из старого `webclient`, но развивается как отдельный набор UI-компонентов с demo/docs страницей.

## Документация

Человеческая документация по подключению, стилю, JS API и компонентам находится в [`docs/`](docs/index.md).
Официальный Vue 3 adapter описан в [`docs/vue.md`](docs/vue.md).

## Быстрый старт

```bash
npm install
npm run dev
```

Dev server:

```text
http://localhost:3000
```

Production build:

```bash
npm run build
```

Release check:

```bash
npm run release:check
```

Vue adapter only:

```bash
npm run build:vue
```

Vue example smoke build:

```bash
npm --prefix examples/vue install
npm run build:example:vue
```

## Структура

```text
demo/                 Demo/docs страница и HTML partials
public/assets/        Шрифты, иконки, highlight.js и изображения
src/js/               Browser JS entry и UI-компоненты
src/scss/             SCSS entry, tokens, utilities и компоненты
dist/                 Результат сборки, не коммитится
webclient/            Исходный старый клиент, игнорируется git
```

Ключевые entry points:

```text
src/scss/kit.scss     Основной CSS UI-kit
src/scss/demo.scss    CSS для demo/docs страницы
src/js/index.js       Browser JS bundle entry
src/vue/index.js      Vue 3 adapter entry
demo/index.html       Demo/docs страница
```

## Команды

```bash
npm run dev
```

Собирает проект, запускает BrowserSync и следит за изменениями.

```bash
npm run build
```

Собирает:

- `dist/css/kit.css`
- `dist/css/demo.css`
- `dist/js/gnexus-ui-kit.js`
- `dist/vue/index.js`
- `dist/index.html`
- `dist/assets/*`

```bash
npm run release:check
```

Runs the Vue adapter smoke build and package smoke validation from a packed
tarball. See [`docs/release.md`](docs/release.md).

## Использование

Для подключения kit в обычную HTML-страницу нужны CSS, иконки и JS bundle:

```html
<link rel="stylesheet" href="/assets/fonts/phosphor-icons/src/css/icons.css">
<link rel="stylesheet" href="/css/kit.css">
<script src="/js/gnexus-ui-kit.js"></script>
```

JS bundle публикует API в `window`:

```js
Toasts.createSuccess("Success", "Saved").show();

const modal = Modals.create("example-modal", {
  title: "Modal",
  bodyText: "Content"
});

modal.show();
```

Также доступен global namespace:

```js
GNexusUIKit.Toasts.createInfo("Info", "Message").show();
```

## Vue Adapter (Primary Contract)

In Vue projects, always use the official adapter. It is the primary contract — not a thin wrapper. Import CSS once, then use adapter components:

```js
import "gnexus-ui-kit/dist/css/kit.css";
import "gnexus-ui-kit/dist/assets/fonts/phosphor-icons/src/css/icons.css";
import { GnButton, GnTabs, GnexusUiVue } from "gnexus-ui-kit/vue";
```

Do not write raw `.btn`, `.modal`, `.tabs` markup in Vue SFCs when the adapter exposes `GnButton`, `GnModal`, `GnTabs`.

### Icon Naming

All icon props **must** use the `ph-` prefix. Phosphor Icons are the only supported icon set.

```js
// Correct
icon="ph-house"
icon="ph-plus"
icon="ph-bold ph-spinner"

// Wrong — triggers a dev warning and may not render
icon="house"
icon="plus"
```

### Vue Component Catalog

| Need | Component | Props you will use |
|------|-----------|-------------------|
| Button | `GnButton` | `variant`, `size`, `icon`, `loading`, `disabled` |
| Icon-only button | `GnIconButton` | `icon`, `label`, `size` |
| Copy button | `GnCopyButton` | `text`, `icon`, `successIcon`, `duration`, `label`, `size` |
| Status label | `GnBadge` | `variant`, `outline` |
| Message block | `GnAlert` | `variant` |
| Card / panel | `GnCard` | `title` (slot), `footer` (slot) |
| Horizontal card | `GnHorizontalCard` | `image`, `title`, `titleHref`, `icon`, `footer` (slot) |
| Page title bar | `GnPageHeader` | `kicker`, `title`, `subtitle`, `meta`, `actions` (slot) |
| Text field | `GnInput` | `v-model`, `label`, `icon`, `state`, `help` |
| Textarea | `GnTextarea` | `v-model`, `label`, `state`, `help` |
| Select dropdown | `GnSelect` | `v-model`, `label`, `options` |
| Checkbox | `GnCheckbox` | `v-model`, `label`, `disabled` |
| Toggle switch | `GnSwitch` | `v-model`, `label`, `disabled` |
| Radio | `GnRadio` / `GnRadioGroup` | `v-model`, `options` |
| Range slider | `GnRange` | `v-model`, `label`, `min`, `max` |
| File upload | `GnFileUpload` | `v-model`, `badge`, `multiple`, `accept` |
| Searchable select | `GnCombobox` | `v-model`, `label`, `options`, `placeholder` |
| Tabs | `GnTabs` | `v-model`, `items` |
| Router tabs | `GnRouterTabs` | `items` (with `to`), `activeMatch` |
| Accordion | `GnAccordion` | `items`, `v-model`, `multiple` |
| Modal dialog | `GnModal` | `v-model:open`, `title`, `closeOnBackdrop` |
| Side drawer | `GnDrawer` | `v-model:open`, `title`, `position` |
| Toasts | `GnToastProvider` + `useToast` | Wrap app once; call `toast.success({ title, text })` |
| Confirm dialog | `GnConfirmDialog` | `v-model:open`, `title`, `message`, `confirmVariant` |
| Table | `GnTable` | `columns`, `rows`, `caption`, `emptyText` |
| Toolbar | `GnToolbar` | `title`, `meta`, `actions` (slot) |
| Input group | `GnInputGroup` | `addon` (slot), `action` (slot) |
| Search field | `GnSearchField` | `v-model` |
| Pagination | `GnPagination` | `page`, `total-pages` |
| Empty state | `GnEmptyState` | `title`, `text`, `icon`, `actions` (slot) |
| Skeleton loader | `GnSkeleton` | — |
| Key-value list | `GnDescriptionList` | `items` |
| Progress bar | `GnProgress` | `value`, `label`, `animated` |
| Usage meter card | `GnUsageMeter` | `value`, `label`, `max` |
| Staged progress | `GnProgressStages` | `items` |
| Wizard steps | `GnSteps` | `items`, `current` |
| Chip / tag | `GnChip` | `variant`, `selected`, `removable` |
| Chip group | `GnChipGroup` | — |
| Avatar | `GnAvatar` | `initials`, `icon`, `image`, `size`, `status` |
| Identity row | `GnIdentity` | `title`, `meta`, `avatar` props |
| Avatar stack | `GnAvatarStack` | `items` |
| Timeline | `GnTimeline` | `items` |
| Activity log | `GnActivityLog` | `items` |
| Basic list | `GnList` | `items` |
| Definition list | `GnDefinitionList` | `items` |
| Action list | `GnActionList` | `items` |
| Loader / spinner | `GnLoader` | — |
| Status card | `GnStatusCard` | `variant`, `title`, `meta` |
| Metric card | `GnMetricCard` | `title`, `value`, `trend` |
| Action card | `GnActionCard` | `title`, `text`, `actions` (slot) |
| Dropdown menu | `GnDropdown` | `items`, `label`, `variant` |
| Popover panel | `GnPopover` | `title`, `text`, `label` |
| Tooltip | `GnTooltip` | `text` |
| Navigation list | `GnNavList` | `items` |
| App shell | `GnNavigationShell` | `brand`, `items`, `current`, `footerLeft`, `footerRight` |

### What NOT to do

- Do **not** copy raw modal markup from demo partials into Vue apps.
- Do **not** call `GNexusUIKit.Modals.create()` from Vue components.
- Do **not** call `GNexusUIKit.Overlays.init()` or `GNexusUIKit.NavigationShell.init()` in Vue projects.
- Do **not** run `Accordion.init()` or `Tabs.init()` inside Vue components.
- Do **not** use the legacy `advancedSelect()` helper in Vue; use `GnCombobox`.
- Do **not** use `InputPatterns.init()` for Vue file upload previews; use `GnFileUpload`.
- Do **not** invent new variant names.
- Do **not** duplicate GNexus CSS in scoped `<style>` blocks.
- Do **not** write `class="btn btn-primary"` when `GnButton` exists.
- Do **not** pass icon names without the `ph-` prefix.

See [`docs/vue.md`](docs/vue.md) and [`docs/vue/ai-usage-guide.md`](docs/vue/ai-usage-guide.md) for full details.

## JS API

Bundle публикует компоненты и helper-модули двумя способами:

```js
Toasts.createSuccess("Success", "Saved").show();
GNexusUIKit.Toasts.createInfo("Info", "Message").show();
```

Текущий публичный namespace:

```text
GNexusUIKit.Helper
GNexusUIKit.Toasts
GNexusUIKit.Modals
GNexusUIKit.advancedSelect
GNexusUIKit.editableString
GNexusUIKit.confirmPopup
GNexusUIKit.Drawer
GNexusUIKit.NavigationShell
GNexusUIKit.Overlays
GNexusUIKit.InputPatterns
GNexusUIKit.Accordion
```

`Overlays.init()`, `NavigationShell.init()`, `InputPatterns.init()` и `Accordion.init()` запускаются автоматически на `DOMContentLoaded`.

## Компоненты

Сейчас в demo/docs представлены:

- Typography
- Palette
- Buttons
- Forms
- Utilities
- Editable String
- Navigation & Overlays
- Navigation Shell
- Lists
- Badges
- Alerts
- Tables
- Data Patterns
- Page Header
- Key-Value / Description List
- Progress
- Steps
- Chips
- Avatar / Identity
- Timeline / Activity Log
- Accordion / Disclosure
- Drawer / Side Panel
- Toasts
- Cards
- Modals
- Confirm Dialog

Каждая секция demo содержит визуальный пример, короткое описание и копируемый блок кода.

### Navigation & Overlays

Секция включает:

- Tabs
- Dropdown
- Tooltip
- Popover

JS-модуль: `src/js/components/overlays.js`.

### Navigation Shell

Секция включает:

- Topbar: sticky верхняя панель с menu toggle, brand и текущим разделом.
- Nav Drawer: left drawer для длинной навигации.
- Footer: версия продукта и copyright.
- Responsive behavior: drawer работает на desktop, tablet и mobile.

JS-модуль: `src/js/components/navigation-shell.js` обрабатывает `data-navigation-toggle`, `data-navigation-drawer`, `data-navigation-close` и `data-navigation-link`.

### Utilities

Секция включает:

- Spacing scale: `$space-0` ... `$space-12`.
- Margin utilities: `m-*`, `mt-*`, `mr-*`, `mb-*`, `ml-*`, `mx-*`, `my-*`.
- Padding utilities: `p-*`, `pt-*`, `pr-*`, `pb-*`, `pl-*`, `px-*`, `py-*`.
- Gap utilities: `g-*`, `gx-*`, `gy-*`.
- Layout/display/text helpers: `grid-*`, `row`, `column`, `items-*`, `justify-*`, `d-*`, `text-*`.

### Data Patterns

Секция включает:

- Toolbar
- Search Field
- Input Group
- Pagination
- Empty State
- Skeleton

JS-модуль: `src/js/components/input-patterns.js` добавляет поведение для `data-input-clear`.

### Page Header и Key-Value

Секции включают:

- Page Header: заголовок экрана, subtitle, status/meta и actions.
- Compact Page Header: плотный вариант для внутренних экранов и настроек.
- Description List: read-only пары key-value для деталей сущности.
- Compact Description List: плотный вариант для metadata blocks.

### Progress и Steps

Секции включают:

- Progress Bar: determinate progress с CSS custom property `--progress-value`.
- Usage Meter: карточка лимита/использования с progress bar.
- Staged Progress: сегментированное состояние операции.
- Steps: горизонтальный и вертикальный wizard-flow.

### Chips и Avatar

Секции включают:

- Chips: static, selectable, removable и state variants.
- Avatar: initials, icon, image, sizes и status marker.
- Identity: avatar + title/meta row.
- Avatar Stack: компактное отображение группы.

### Timeline и Accordion

Секции включают:

- Timeline: вертикальная история событий со state variants.
- Activity Log: компактный audit/job log.
- Accordion: группы на native `<details>` / `<summary>`.
- Disclosure: компактная одиночная раскрываемая группа.

JS-модуль: `src/js/components/accordion.js` добавляет управляемую анимацию раскрытия.

### Drawer и Confirm Dialog

Секции включают:

- Drawer: боковая overlay-панель для деталей, quick edit и secondary flows.
- Side Panel variants: правая и левая позиция через `position: "left"`.
- Confirm Dialog: документация для существующего `confirmPopup`.

JS-модули: `src/js/components/drawer.js` и `src/js/components/confirm-popup.js`.

## SCSS

Базовые файлы:

```text
src/scss/_palette-colors.scss
src/scss/_design-tokens.scss
src/scss/_spacing.scss
src/scss/_mixins.scss
src/scss/_utils.scss
```

Компоненты находятся в:

```text
src/scss/components/
```

Основная идея стиля сохраняется от исходного UI: моноширинная типографика, Tokyo Night influenced dark surface, sharp edges, толстые акцентные бордеры, цветовая инверсия на hover/focus и яркие status colors.

## Assets

Локально подключены:

- IBM Plex Mono
- Phosphor Icons
- highlight.js для подсветки кода в demo/docs

`dist/` генерируется из `public/assets`, `src` и `demo`.

## Текущие замечания

- Сборка работает на Gulp 5, modern Dart Sass API, PostCSS/autoprefixer, clean-css, esbuild и gulp-file-include.
- Sass переведен на `@use` / `@forward`; deprecated `map-*` global functions заменены на `sass:map`.
- `npm audit --audit-level=low` проходит без найденных уязвимостей.
- `webclient/` оставлен как источник старого клиента и игнорируется git.
- `.codex` является локальным служебным файлом и не должен попадать в коммиты.

## Запланировано

Ближайшие полезные компоненты:

- На текущий момент список запланированных компонентов закрыт; дальше можно расширять набор по новым сценариям.

Технические задачи:

- На текущий момент технический backlog пуст; дальше расширяем компонентный набор.
