# Канонические компоненты

Машинный список находится в `registry/components.json`. Ниже зафиксирован смысл компонентов и границы их использования.

## GlassSurface

Базовая непрозрачная поверхность для карточки, панели и большого окна. Варианты меняют плотность нейтральной поверхности, но не создают отдельный дизайн. Реальный glass-материал с blur и rim используется только у floating-слоёв: modal `Window` и portal-dropdown/select.

- `default` — обычная карточка/панель;
- `strong` — dropdown, modal и поверхность над сложным фоном;
- `soft` — вложенная или вторичная область.

Material rim допустим только как часть floating glass. Жёсткая цветная рамка, случайный browser outline или debug border не являются rim.

`GlassMaterialSurface` — отдельный переносимый контракт Engine Glass V4. Он централизует tint/opacity, blur, saturation, brightness, gradient rim и shadow. Его используют только modal `Window` и modeless draggable Inspector; обычные Launcher/SEO панели остаются непрозрачными. Сам `Window` всегда получает класс `nodedc-glass-material` и `data-material="glass-v4"`, поэтому sharing, confirmation и остальные modal-паттерны физически используют тот же surface, что Inspector и лабораторный preview. Настройки применяются через `applyGlassMaterial`, поэтому consumer не пересобирает CSS материала вручную.

## Button и IconButton

Button используется для всех текстовых действий. IconButton — для действия без текста.

- primary/accent — главное действие текущего контекста;
- secondary — обычное действие на glass surface;
- ghost — малозаметное действие без собственной подложки;
- danger — разрушительное действие, обычно в окне подтверждения.

Icon-only action по умолчанию круглый. Квадратная кнопка с маленьким радиусом допустима только как кнопка закрытия окна или плотный инструмент, где это зафиксировано контрактом.

## Field

FieldFrame объединяет label, control, hint и description. TextField/TextAreaField реализуют стандартные текстовые поля.

Приложение не должно вручную собирать label и input, если подходит Field. Ошибка и validation state будут расширением этого контракта, а не локальным классом приложения.

## Checker

Круглый бинарный контрол из нового Engine settings/agent inspector. Он использует checkbox semantics, но не копирует квадратный системный checkbox.

Внутри Checker допускается только короткий однострочный заголовок. Пояснение, hint или описание размещается отдельным текстовым блоком перед Checker; сам бинарный контрол не является контейнером для вторичной копии.

## RangeControl

Pill-range с заполнением акцентным цветом, встроенной подписью и значением. Домен определяет min/max/step и формат числа. Drag всегда принадлежит невидимому native range и продолжается под областью значения. Над числом постоянно смонтирован один прозрачный native text input: клик включает редактирование без замены DOM-узла, браузер ставит каретку в фактическое место клика, а drag-selection остаётся нативным. Поле не получает собственной подложки, select-all или второго focus-ring. Enter/blur применяют значение с clamp/step-нормализацией, Escape отменяет ввод; события редактора не всплывают в оконные shortcuts. Оконный focus-manager выполняет начальный autofocus только при открытии и не отбирает фокус при последующих ререндерах.

## ColorField

Engine/BIM-геометрия color field: круглый swatch и HEX-значение в pill control. Swatch открывает общий portal-picker: saturation/value plane, hue slider и быстрые цвета. Это устраняет зависимость от тёмной системной палитры браузера и делает выбор одинаковым в dark/light.

Значение контролируемое; приложение по-прежнему отвечает за допустимый формат, сохранение и доменную реакцию на цвет.

## Dropdown

Dropdown владеет floating-layer поведением:

- рендерится в `document.body`;
- позиционируется относительно viewport;
- переворачивается вверх при недостатке места;
- ограничивает размеры viewport;
- обновляется при resize и scroll;
- закрывается по outside pointer и Escape;
- после Escape возвращает фокус на реальную trigger-кнопку, не закрывая родительское окно;
- закрывает другой открытый dropdown.

Содержимое меню передаётся приложением. Selection, action menu и filter menu используют один engine.

Поверх Cesium/map imagery dropdown получает класс `nodedc-map-glass` (`MapGlassSurface`): это отдельный светлый полупрозрачный материал, совпадающий с Map Toolbar. Он не заменяет обычный theme-dependent floating surface вне карты.

## Select

Select добавляет к Dropdown контролируемое значение, options и необязательный поиск. У него две канонические формы:

- `integrated` — единая pill-поверхность Hub/Launcher: label слева, chevron строго у правого края;
- `split` — форма Engine с отдельной областью значения и отдельной кнопкой раскрытия `46 px`, между ними зазор `8 px`.

Native select не используется как видимый runtime UI. Меню рендерится через portal; у Engine-варианта меню имеет радиус `20 px`, а строки — `14 px` и высоту `42 px`.

Внутри `Inspector` форма `integrated` запрещена. Selection-поле собирается только через `InspectorSelectField`: видимая подпись находится сверху, а полноширинный control всегда использует `split`. Компонент намеренно не принимает `layout` и `variant`, поэтому consumer не может вернуть Inspector к Hub/Launcher pill-форме.

## Window

Window — единая механика открытия modal и правой panel:

- приложение контролирует `open`;
- библиотека управляет portal, focus entry/trap/restore, Escape, backdrop и scroll lock;
- `center` — modal;
- `end` — modeless inspector/settings/detail panel без затемнения, backdrop blur, backdrop close, focus trap и блокировки прокрутки страницы.

Содержание, сохранение и запросы принадлежат приложению.

Для modeless Inspector доступен `draggable`: окно двигается за header, не блокирует приложение и ограничивается viewport. Modal-окна не становятся draggable автоматически.

## WorkspaceWindow

`WorkspaceWindow` — modeless-окно внутри рабочей сцены приложения. Оно рендерится непосредственно в переданном workspace, не использует portal и не может перекрыть шапку, навигацию или соседние панели за пределами этого workspace.

На Map Page `WorkspaceWindow` используется и для facet-групп, и для
provider-neutral карточки выбранного subject. Chevron внутри facet-строки
владеет только раскрытием дерева subjects; тело строки сохраняет действие
фильтра. Смена совместимого subject не пересоздаёт карточку и не сбрасывает
активную вкладку. Joined data-product aspects не создают отдельные окна или
слои, а наполняют декларативные секции существующей карточки.

Справочные точки транспорта используют тот же renderer adapter, но отдельный
slot `reference-points`. Их три presentation profiles (`Метро`, `Вокзалы`,
`Станции РЖД`) являются живыми каноническими Inspector sections: приложение
может менять высоту, размер, label и LOD, не создавая provider-specific UI.

Приложение контролирует `rect`, `maximized`, видимость, active-state и `zIndex`. Компонент владеет pointer/keyboard-механикой перемещения и изменения размера, кнопками maximize/restore и close, а также повторно ограничивает геометрию при изменении размеров workspace через `ResizeObserver`. Опциональный `autoHeight` подгоняет высоту под живое содержимое и сжимает её обратно, не выходя за нижнюю границу workspace. Родительский bounds-контейнер должен быть позиционированным и обрезать содержимое (`position: relative; overflow: hidden`).

Окно предназначено для вспомогательных камер, инструментов и сопоставляемых представлений внутри сцены. Modal workflow, подтверждение и viewport-level Inspector по-прежнему используют `Window`.

## Toolbar

`Toolbar` — канонический dock из нового Engine с требованиями BIM Viewer. Он поддерживает позиции `left`, `right`, `bottom`, lens magnification и autohide. Контролируются фон, border, outline, минимальный/максимальный размер и количество иконок линзы.

Дефолты перенесены из Engine без переизобретения: `#111115`, `#111117`, `#1c1c1c`, `25 px`, `87 px`, `5`. Toolbar получает те же section actions, что и основная navigation, но не владеет route-state.

Компонент сам владеет всей механикой dock: base-размеры кнопок не меняют flex-layout, lens использует `transform: scale + shift`, движение сглаживается единым spring-циклом `requestAnimationFrame`, а autohide закрывает панель с задержкой и возвращает её через edge hotzone. Consumer не реализует hover-расчёты, таймеры или анимацию повторно. React использует `Toolbar`, а BIM/CMS и другие DOM-приложения подключают тот же контракт через `createToolbarController`; обе обёртки используют общие `normalizeToolbarSettings`, `calculateToolbarTargets` и `stepToolbarSpring` из `@nodedc/ui-core`.

## ConfirmationModal

ConfirmationModal оборачивает Window и защищает async-confirm от повторного запуска. До завершения операции закрытие можно заблокировать.

## ShareAccessModal

Workflow-sharing modal из нового Engine: заголовок ресурса, compact avatar stack, список участников, редактирование ролей, удаление доступа, email и роль нового участника. Компонент сохраняет Engine-геометрию `600 px` и controls `46 px`, но не импортирует ACL API. Consumer передаёт members, permissions и callbacks.

Владелец отмечается `immutable`; отсутствие права управления задаётся `canManage`. Backdrop по умолчанию не закрывает access-modal, чтобы пользователь не потерял введённое приглашение.

## ShareLinkModal

Read-only link/copy окно из BIM Viewer. React-компонент использует общий Window, а Vanilla DOM consumer использует `createShareLinkController` вместе с `createModalController`. URL формируется сервисом модели; дизайн-система отвечает только за presentation, copy-state и ошибки адаптера.

## SegmentedControl

Pill navigation для верхней панели и компактного переключения режимов. Active segment использует активную поверхность темы; это не обязательно основной accent приложения.

## AppHeader

Трёхосевая верхняя панель:

- слева фиксированная область логотипа и optional context;
- по центру workspace/navigation;
- справа actions/profile.

Компонент фиксирует положение логотипа, высоту и выравнивание, но не знает маршруты конкретного приложения. Launcher-пресет состоит из внешнего toolbar `68 px` и отдельной видимой строки `48 px`; логотип, центральный switcher и profile-group центрируются по строке `48 px`, а не по всей внешней высоте. Эта двухслойная геометрия закрыта внутри компонента и не переопределяется локальным `className/style`.

В Hub-форме центр состоит из круглого workspace trigger и segmented navigation. Справа используется единая profile-group поверхность с иконкой, подписью и круглым avatar. Эти элементы нельзя заменять случайными standalone-кнопками, сохраняя только приблизительную позицию.

В каноническом `ApplicationShell` шапка фиксирована. Её три оси не двигаются при открытии navigation/content и не зависят от ширины предметного контента.

## UserProfileMenu

Каноническая выпадашка профиля для правой группы `AppHeader`. Она использует
общий portal `Dropdown`, показывает identity cover с аватаром, именем и
подписью и принимает список application-owned действий.

Компонент владеет только геометрией, темизацией, закрытием по outside pointer и
Escape. Переход в профиль, открытие настроек, logout, permissions и продуктовые
правила остаются в приложении. Меню не должно содержать скрытый MCP или ACL
контракт.

## FeatureSettingsWindow

Большое модальное окно настроек по принятой механике нового Engine: identity
текущего модуля слева, сгруппированная навигация features и scrollable content
справа. Компонент переиспользует `Window`, поэтому не создаёт собственный
portal, backdrop или focus trap.

`FeatureSettingsWindow` хранит только controlled active section. Формы,
setup-команды, сохранение, API и права принадлежат приложению. Цвет и материал
берутся из активного Design Profile; отдельная Engine/Foundry тема внутри
компонента запрещена.

## ApplicationShell и ApplicationPanel

Общий шаблон приложения по механике Launcher/Hub: фиксированный `AppHeader`, центральный stage, левая navigation panel и отдельное правое content window.

- на главной виден только stage;
- открытая navigation сдвигает stage;
- content открывается справа от navigation;
- expand растягивает content до правого края и уводит stage за viewport;
- на мобильном navigation и content используют всю область под шапкой последовательно;
- нижняя service rail не входит в шаблон — это элемент витрины Launcher.

`useApplicationWorkspace` является каноническим контроллером этих состояний для React. Приложение не должно заново связывать набор локальных boolean-state для navigation/content/expand. DOM-проекты используют идентичный `createApplicationWorkspaceController`.

Постоянные действия всего рабочего окна передаются через `ApplicationPanel.utilityActions` и всегда находятся в правой части шапки перед expand/close. Сохранение общего layout или настроек приложения — одно такое действие для всего окна; оно не дублируется внутри отдельных карточек и секций.

Точные состояния и размеры зафиксированы в `docs/APPLICATION_TEMPLATE.md`.

## MediaSourceField

Общий компонент Launcher/CMS для медиа-поля: file control, имя файла, URL input, переключатель `HD / URL`, круглое превью, path/hint/error. Один контракт применяется и для stage-видео, и для изображений/логотипов; тип файла, подписи и preview задаёт consumer. Публичный API контролируемый.

Компонент владеет геометрией, доступностью и выбором источника. Приложение владеет file picker/media library, загрузкой в storage, валидацией, разрешениями и сохраняемым URL. Поэтому один и тот же компонент подключается к разным backend без fork. В каталоге видео и знак шапки сохраняются одной кнопкой вместе с темой и настройками layout. Для Vanilla DOM используется `createMediaSourceController`.

## SettingsCard и Switch

`SettingsCard` фиксирует нейтральную структуру админской группы: eyebrow/title/description/actions/body. `Switch` покрывает компактное включение/видимость внутри таких групп. Данные секции, сохранение и права остаются в consumer.

## AdminNavigationPanel

Левая выезжающая панель Hub/Launcher. Библиотека владеет оболочкой `352 px`, радиусом `21.6 px`, внутренними отступами, full-bleed context/navigation pills, круглыми icon surfaces и анимацией появления. Приложение передаёт workspace/company, маршруты, active id и footer identity.

На desktop открытая панель занимает отдельную колонку с Launcher page gap `20 px` до content/stage, а не перекрывает их затемнённым overlay.

`AdminNavigationPanel` поддерживает сортируемые route-items через общий Drag & Drop contract. Приложение передаёт новый порядок id, а панель использует каноническую шеститочечную ручку Engine. Порядок не хранится отдельно внутри navigation-компонента.

## Drag & Drop

`DragHandle`, `DragDropRoot`, `DraggableItem`, `DropZone`, `SortableScope`, `SortableItem` и `SortableList` образуют общий React-контракт переноса и сортировки. Он перенесён из рабочего Engine-паттерна: drag начинается только за шесть точек и только после движения на `6 px`, поэтому обычный клик по строке не конфликтует с навигацией.

Sortable-строки ограничены вертикальной осью: горизонтальное движение указателя не сдвигает navigation или composition layout. `DragDropRoot` возвращает реальные active/over rectangles, поэтому consumer может принять перенос только после достаточного перекрытия destination. Module Foundry использует порог `20%` ширины переносимой строки: короткое движение, движение влево или касание границы не создаёт page instance.

В Module Foundry исходная строка Page Template остаётся в Page Library после переноса. Каждый подтверждённый drop создаёт новый page instance с уникальным id; состав приложения и левая навигация читают один массив страниц и потому всегда перестраиваются синхронно. Удаление instance выполняется стандартным `ConfirmationModal`, а не мгновенным действием крестика.

## Icon

`Icon` предоставляет только подтверждённый общий subset иконок. Каноническое имя описывает смысл (`close`, `expand`, `refresh`), а не конкретный путь SVG. Default glyph — `16 px`, stroke — `1.6`; размер не уменьшается дополнительным CSS-scale. В profile-group шапки допустим подтверждённый Launcher-размер `20 px`. Размеры surface/hit target при этом остаются независимыми и не уменьшаются.

Поверхность, круглая форма, hit target, active и disabled состояния принадлежат `IconButton`, `Button` или navigation item. Полный список находится в `registry/icons.json` и `docs/ICONS.md`.

## StatusBadge

Статус использует semantic tone: neutral, success, warning, danger или accent. Бизнес-статус приложения маппится на tone в самом приложении.

## ToastStack

`ToastCard` и `ToastStack` фиксируют Tasker-derived bottom-right уведомления для `success`, `error`, `warning`, `info` и `loading`. Приложение владеет текстом и состоянием операции; стек владеет portal, геометрией, aria-live и таймерами. Loading не закрывается автоматически и обновляется тем же id после завершения операции. Toast не используется вместо modal confirmation.

## Environment Controls: Inspector и ControlRow

Единая accordion-панель для settings и definition controls. Источник — только новый Environment Settings и NDC Agent Inspector.

Inspector владеет:

- заголовками разделов;
- открытием/закрытием секций;
- active state;
- вертикальным ритмом;
- раскладкой label/control.

В uncontrolled-режиме начальные секции задаёт `defaultOpen`. Для layout-aware
приложений Inspector поддерживает controlled-пару
`openSections/onOpenSectionsChange`: она позволяет общей кнопке Save сохранять
точную конфигурацию раскрытых секций и восстанавливать её без remount-default.

Для Engine Environment Settings desktop-контракт точный: окно `390 px`, рабочая колонка `330 px`, строка `154 + 14 + 162 px`, высота контрола `46 px`, section header `50 px` с радиусом `12 px`. Accent-filled section headers и полноширинные range/checker/select сохраняют геометрию исходника.

Engine продолжает владеть определениями полей, типами нод и сохранением значений. В живом catalog эти collapsible sections находятся в `Guideline → Контролы`; отдельной product-вкладки Inspector нет.
