@cavicode/uikit-webadmin (1.0.2)
Installation
@cavicode:registry=npm install @cavicode/uikit-webadmin@1.0.2"@cavicode/uikit-webadmin": "1.0.2"About this package
@cavicode/uikit-webadmin
Vue 3 UI-компоненты административных интерфейсов CaviCode/HVZ.
Установка
npm install @cavicode/uikit-webadmin
.npmrc:
@cavicode:registry=https://git.cavicode.tech/api/packages/cavicode/npm/
@tanstack/vue-table встроен в package bundle. Отдельная установка нужна только
consumer, который напрямую импортирует его runtime API или типы.
Nuxt 4
// plugins/uikit.ts
import CavicodeUIKitWebadmin from '@cavicode/uikit-webadmin'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(CavicodeUIKitWebadmin)
})
// nuxt.config.ts
export default defineNuxtConfig({
css: ['@cavicode/uikit-webadmin/style.css'],
})
Для template types consumer добавляет GlobalComponents augmentation. Nuxt
components[] не подходит: опубликованный dist содержит compiled JS и .d.ts,
а не каталог исходных .vue.
Tailwind v4 consumer должен импортировать package CSS в общий pipeline и сканировать compiled dist:
@import "tailwindcss";
@import "@cavicode/uikit-webadmin/style.css";
@source "../../../node_modules/@cavicode/uikit-webadmin/dist";
Путь @source зависит от расположения consumer stylesheet.
Компоненты (46)
- Поля:
UiInput,UiTextarea,UiSelect,UiCheckbox,UiRadio,UiColorInput,UiSearchInput. - Кнопки и иконки:
UiButton,UiIconButton,UiIcon. - Формы/layout:
UiFormField,UiFormGrid,UiCard,UiMetricCard,UiAlert. - Диалоги:
UiModal,UiConfirmDialog,UiDrawer. - Таблицы:
UiDataTable,UiSimpleTable,UiTableSearch,UiTableToolbar. - Навигация:
UiPagination,UiTabs,UiPageHeader,UiBreadcrumbs,UiNavbar,UiSidebar,UiMenu,UiTooltip. - Состояния:
UiState,UiStatusBadge,UiToast,UiSpinner,UiSkeleton,UiProgress. - Прочее:
UiDropdown,UiMediaPicker,UiOrderControls,UiBarChart,UiLineChart,UiPieChart,UiTag,UiDefinitionList,UiDateDivider,UiLogConsole.
Базовый API 0.2
UiInput, UiTextarea, UiSelect, UiSearchInput, UiColorInput и
UiDropdown используют размеры sm | md | lg. Поля связывают hint/error/success
с контролом через aria-describedby; UiInput, UiTextarea и UiSearchInput
поддерживают clearable и событие clear.
UiInput предоставляет slots prefix и suffix:
<UiInput v-model="amount" label="Сумма" clearable>
<template #suffix>₽</template>
</UiInput>
UiDropdown теперь выводит label визуально и поддерживает hint, error,
success, required, loading, а также slots selection, option и empty.
По умолчанию control занимает всю ширину контейнера. Prop fit-content сжимает
trigger по выбранному тексту (не шире контейнера), при этом popup остаётся не уже
trigger, расширяется под длинные option labels и ограничивается viewport:
<UiDropdown v-model="branchId" :options="branches" fit-content />
UiButton поддерживает loading, loading-text, block, icon,
icon-position и href. В loading-state повторный action блокируется:
<UiButton icon="save" :loading="saving" loading-text="Сохраняем">
Сохранить
</UiButton>
UiIcon выводит встроенные SVG по типизированному имени UiIconName, переданный
Vue-компонент или slot. Icon font и внешняя загрузка шрифтов не требуются.
Breaking changes 0.2
UiFormFieldрендерит корневойdiv, а неlabel. Для связи кастомного контрола передаётся propfor; это исключает невалидные вложенные label.UiRadioбезnameне создаёт уникальное имя. Для нативной keyboard-группы consumer передаёт одинаковыйnameвсем radio.- DOM и CSS-классы базовых полей изменены; использовать внутренние селекторы компонентов как consumer API нельзя.
Навигация и overlays 0.3
UiNavbar и UiSidebar предоставляют структуру приложения и не зависят от
router. UiSidebar поддерживает v-model:collapsed; для мобильной панели
используется отдельный UiDrawer.
<UiSidebar v-model:collapsed="collapsed" collapsible>
<template #default="{ collapsed }">...</template>
</UiSidebar>
UiBreadcrumbs принимает массив { label, href?, icon?, disabled? }.
UiMenu принимает typed items и предоставляет activator props, которые нужно
передать реальной кнопке через v-bind:
<UiMenu :items="actions" @select="runAction">
<template #activator="{ props }">
<UiButton v-bind="props">Действия</UiButton>
</template>
</UiMenu>
Такая же схема activator используется у UiTooltip, чтобы aria-describedby
и keyboard handlers находились на фокусируемом элементе.
Общий overlay stack
UiModal и UiDrawer используют общий stack, body lock, focus trap и focus
restoration. При открытии нового modal layer нижние слои получают inert.
UiDropdown, UiMenu и UiTooltip закрываются при смене stack, поэтому
teleport-popover не может остаться активным над неактивным modal/drawer.
Политика модальных окон
UiModal по умолчанию не закрывается кликом по overlay или клавишей Escape.
Пользователь закрывает окно только крестиком либо явным consumer action
«Отмена»/«Закрыть»; программное закрытие через v-model="false" после успешной
операции работает как обычно. Props close-on-overlay и close-on-escape с
default false предназначены только для осознанных исключений.
Для дополнительного времени, статуса или другого содержимого справа от
заголовка используется typed slot header-extra:
<UiModal v-model="open" title="Занятие">
<template #header-extra><UiStatusBadge label="Проведено" /></template>
<!-- Содержимое -->
</UiModal>
На экранах шириной до 768 px все UiModal разворачиваются на весь фактически
видимый viewport, в том числе при открытой экранной клавиатуре, с учётом safe
area и отдельной прокруткой body. Несколько открытых modal используют общий
body lock, располагаются по порядку стека и корректно передают фокус верхнему
окну либо внешнему opener после закрытия всего стека. Неактивные слои стека
получают inert и скрываются от accessibility tree; только верхнее окно является
modal и обрабатывает клавиатуру. UiDrawer по умолчанию закрывается по overlay
и Escape. Popover закрываются по Escape/клику снаружи и при изменении общего
overlay stack.
UiDataTable автоматически распознаёт строковый заголовок ID и ограничивает
колонку диапазоном 72–112 px без переноса цифр. В UiSimpleTable для той же
семантики consumer ставит table-id-column на соответствующие th и td.
Для реестров, которые на телефоне должны становиться карточками, используется
opt-in prop mobile-cards. Роль колонки задаётся через ColumnDef.meta:
const columns = [
{ accessorKey: 'name', header: 'Название', meta: { mobileRole: 'title' } },
{ accessorKey: 'status', header: 'Статус', meta: { mobileRole: 'badge' } },
{ accessorKey: 'note', header: 'Комментарий', meta: { mobileFullWidth: true } },
{ id: 'actions', header: '', meta: { mobileRole: 'actions' }, cell: renderActions },
]
Поддерживаются роли title, subtitle, badge, field и actions, а также
mobileLabel, mobileHidden и mobileFullWidth. По умолчанию колонка выводится
как обычное поле. Desktop-представление при этом остаётся таблицей.
Таблицы 0.4
UiDataTable использует manual sorting/filtering: библиотека хранит и эмитит
state, но server filtering, sorting и page slice выполняет consumer. Все состояния
могут работать controlled через v-model:
<UiDataTable
v-model:sorting="sorting"
v-model:row-selection="selection"
v-model:column-visibility="visibility"
v-model:column-filters="filters"
v-model:global-filter="search"
v-model:page-size="pageSize"
:data="pageRows"
:columns="columns"
:get-row-id="row => String(row.id)"
toolbar
searchable
selectable
show-column-visibility
/>
Для selection между страницами обязателен стабильный get-row-id; без него
TanStack использует индекс строки текущего массива. selection-change содержит
только загруженные выбранные rows, а row-selection-change — полный map ID.
Default toolbar поддерживает debounced search, slot filters, slot actions,
selection actions, видимость колонок и page size. Его можно заменить slot
toolbar или использовать UiTableToolbar отдельно. loading и empty также
имеют slots.
UiPagination сохраняет 0-based page, но теперь поддерживает номера страниц,
first/last, sibling-count, compact mode и show-jump. На узком viewport номера
скрываются, оставляя touch-friendly direction controls.
Media и charts 1.0
UiMediaPicker применяет одну consumer policy к file dialog и drag-and-drop.
Форматы задаются через MIME, wildcard или расширение; размеры указываются в bytes.
Upload lifecycle остаётся у consumer и передаётся keyed map через file-states:
<UiMediaPicker
v-model="files"
:accept="['image/*', '.pdf']"
:max-files="3"
:max-file-size="10 * 1024 * 1024"
:file-states="uploadStates"
@add="upload"
@rejected="showValidationErrors"
/>
UiBarChart, UiLineChart и UiPieChart используют общий набор props:
loading, loading-text, empty-text, aria-label, show-legend, show-data,
format-value и controlled v-model:selected-index. Marks доступны с клавиатуры
и эмитят select; loading, empty и legend можно заменить slots. Bar/line
дополнительно управляют grid и axes, pie — inner-radius и center value.
<UiLineChart
v-model:selected-index="selectedPoint"
:data="points"
:loading="loading"
:format-value="formatMoney"
show-legend
/>
В UiDateDivider режим table рендерит валидную пару tr/td; количество
колонок таблицы передаётся через colspan.
Consumer-owned state
UiToast и UiConfirmDialog презентационные. Consumer передаёт props и
обрабатывает emits; Nuxt composables в пакет не переносятся.
Charts используют generic data:
type UiBarChartDatum = { label: string; value: number; color?: string }
type UiLineChartPoint = { label?: string; date: string; value: number }
type UiPieChartDatum = { label: string; value: number; color?: string }
Метрики 1.1
UiMetricCard отображает единичный KPI с типизированной иконкой, пояснением,
цветовым тоном и slots icon, default, detail, aside. Компонент адаптивен и
подходит для dashboard без consumer-копирования рамок, типографики и состояний:
<UiMetricCard
label="Расчётная зарплата"
value="42 500 ₽"
detail="за август 2026"
icon="payments"
tone="success"
/>
Миграция на 1.0
Breaking changes и удаляемые consumer workarounds перечислены в
docs/solutions/uikit-1-migration.md.
Ограничения версии 1.0.0
- Upload transport и lifecycle файлов не входят в
UiMediaPicker. - Charts ожидают неотрицательные значения; отрицательные pie values не строятся.
- Export
./themeне предоставляет отдельный runtime API: tokens входят в общийstyle.css.
Разработка
npm ci
npm run typecheck
npm run build
npm run build также выполняет vue-tsc --noEmit. Тестов и lint script сейчас
нет; изменения компонентов требуют проверки package build и consumer builds.
Dependencies
Development dependencies
| ID | Version |
|---|---|
| @tanstack/vue-table | ^8.21.3 |
| @types/node | ^26.2.0 |
| @vitejs/plugin-vue | ^5.2.1 |
| @vue/tsconfig | ^0.7.0 |
| sass-embedded | ^1.100.0 |
| tailwindcss | ^4.3.3 |
| typescript | ^5.6.0 |
| vite | ^6.0.0 |
| vite-plugin-dts | ^4.5.0 |
| vue | ^3.5.0 |
| vue-tsc | ^3.3.8 |
Peer dependencies
| ID | Version |
|---|---|
| vue | ^3.5.0 |