@besnovatyj/tree-widget-core
v1.3.2
Published
Framework-agnostic Nested Sets tree widget (ядро). Цепляется к любому бэкенду через ITreeDataSource.
Maintainers
Readme
@besnovatyj/tree-widget-core
Framework-agnostic Nested Sets tree widget (TypeScript). Ядро цепляется к любому
бэкенду через интерфейс ITreeDataSource; готовая HTTP-реализация
(HttpTreeDataSource) из коробки совместима с TreeController пакета
besnovatyj/yii2-cms-tree-manager.
✨ Features
- ✅ Nested Sets модель с поддержкой множественных корней
- ✅ CRUD операции - создание, редактирование, удаление узлов
- ✅ Drag & Drop - desktop (HTML5) и mobile (touch с long press), «липкая» цель drop
- ✅ Root Drop Zone - создание корней через drag & drop
- ✅ Улучшенная визуализация - раздвигание узлов для before/after
- ✅ Lazy Loading - подгрузка детей по требованию
- ✅ Expand/Collapse - с сохранением состояния
- ✅ Система патчей - эффективные обновления (explicit/ops)
- ✅ Серверные формы - HTML формы от сервера с валидацией (ошибки полей
матчатся и по составным именам вида
FormName[attr]) - ✅ Доставка ошибок - доменные сообщения сервера (422 /
success:false) доезжают до Toast/полей, внутренние ошибки сервера не утекают - ✅ Права доступа - гранулярный контроль операций (UX-уровень; enforcement — на сервере)
- ✅ События - changed, nodeSelected, beforeRequest, afterRequest, error
- ✅ Storage - LocalStorage/SessionStorage/Memory
- ✅ UI компоненты - Modal, BottomSheet, Toast, Loader, Menu
- ✅ Темизация - CSS переменные, темная тема
- ✅ Accessibility - ARIA атрибуты
- ✅ TypeScript Strict - без runtime-зависимостей
📦 Installation
npm install @besnovatyj/tree-widget-core🔌 Два формата подключения
IIFE (script-тег, глобальная window.TreeWidget)
dist/index.js — самодостаточный бандл с автоинициализацией контейнеров,
имеющих атрибут data-tree-config (именно его использует Yii2-фасад):
<link rel="stylesheet" href="node_modules/@besnovatyj/tree-widget-core/dist/styles.css">
<script src="node_modules/@besnovatyj/tree-widget-core/dist/index.js"></script>
<script>
const widget = TreeWidget.createTreeWidget({ /* ... */ });
</script>ESM (бандлеры / import)
dist/index.esm.js — то, что отдаёт exports пакета:
import { createTreeWidget } from '@besnovatyj/tree-widget-core';
import '@besnovatyj/tree-widget-core/styles';
const widget = createTreeWidget({
widgetId: 'my-tree',
container: document.getElementById('tree-container'),
dataSource: myDataSource
});
await widget.load();🤝 Контракт виджет ↔ бэкенд
Все фичи виджета работают только с портом ITreeDataSource
(src/shared/api/tree/ports.ts — источник истины контракта):
| Метод порта | Endpoint HttpTreeDataSource | Экшен TreeController (Yii2-фасад) |
|---|---|---|
| loadRoots() | — (initialData из конфига) | index (данные в страницу) |
| loadChildren(id) | endpoints.loadChildren | load-children |
| createNode(data) | endpoints.createNode | create |
| updateNode(id, data) | endpoints.updateNode | update |
| deleteNode(id, mode) | endpoints.deleteNode | delete (mode: subtree/reparent) |
| moveNode(...) | endpoints.moveNode | move |
| toggleStatus(id) | endpoints.toggleStatus | toggle-status |
| checkIntegrity() | endpoints.checkIntegrity (опц.) | check-integrity |
Контракт ошибок: доменные ошибки приходят как HTTP 422 с осмысленным message
(или HTTP 200 + success:false + message) и показываются пользователю;
прочие статусы показываются нейтрально. Ошибки валидации форм — errors
(attr → [messages]), раскладываются по полям формы.
🚀 Integration Examples
Yii2 (через HTTP-реализацию порта)
import { createYii2TreeWidget } from '@besnovatyj/tree-widget-core';
const widget = createYii2TreeWidget({
widgetId: 'my-tree',
container: document.getElementById('tree-container'),
initialData: window.treeData,
endpoints: {
loadChildren: '/tree/load-children',
createNode: '/tree/create',
updateNode: '/tree/update',
deleteNode: '/tree/delete',
moveNode: '/tree/move',
toggleStatus: '/tree/toggle-status'
},
csrfToken: document.querySelector('meta[name="csrf-token"]')?.content
});
await widget.load();Имена
Yii2TreeBackend/Yii2BackendConfig— deprecated-алиасы; новые имена:HttpTreeDataSource/HttpDataSourceConfig(ядро agnostic, от Yii2 в HTTP-реализации — только дефолтный источник CSRF-токена).
Свой бэкенд (REST/GraphQL/mock)
import type { ITreeDataSource } from '@besnovatyj/tree-widget-core';
class RestApiTreeDataSource implements ITreeDataSource {
async loadRoots(): Promise<TreeNodeDto[]> {
const response = await fetch('/api/tree/roots');
return response.json();
}
// ... остальные методы порта
}
const widget = createTreeWidget({
widgetId: 'my-tree',
container: document.getElementById('tree-container'),
dataSource: new RestApiTreeDataSource()
});🛠️ Development
Scripts
npm run build # esbuild: dist/index.js (IIFE) + dist/index.esm.js (ESM) + dist/styles.css
npm run watch # build с watch
npm run type-check # tsc --noEmit
npm run types # эмиссия .d.ts в dist (tsc + tsc-alias, пути без @shared/*)
# npm publish сам выполнит build + types (prepublishOnly)Project Structure (FSD)
src/
├── app/ # Public API (index.ts — entry, автоинициализация)
├── widgets/ # Widgets
│ └── tree/ # Tree widget
├── features/ # Business features
│ ├── create-node/ # Create nodes
│ ├── edit-node/ # Edit nodes
│ ├── delete-node/ # Delete nodes
│ ├── move-node/ # Move (drag & drop)
│ └── ...
├── entities/ # Business entities
│ └── node/ # Tree node
├── shared/ # Shared modules
│ ├── api/ # Transport, HttpError, порт ITreeDataSource + HTTP-реализация
│ ├── ui/ # UI components
│ ├── lib/ # Utils (включая applyFieldErrors)
│ └── config/ # Types & configs
└── styles/ # CSS stylesСвязанные пакеты (порядок сборки)
- этот пакет — публикуется в npm (
npm publish); besnovatyj/yii2-cms-tree-manager(composer) — бандлит ESM-сборку ядра в свойassets/dist/(esbuild.js в корне пакета) и отдаёт через Yii2 AssetBundle;besnovatyj/yii2-nested-sets(composer) — PHP-ядро Nested Sets, серверная сторона контракта.
📝 Example
См. example.html — рабочий пример на mock-данных (ESM-сборка).
🎨 Theming
Виджет использует CSS переменные:
:root {
--ns-tree-primary: #007bff;
--ns-tree-bg: #ffffff;
--ns-tree-border: #e0e0e0;
/* ... */
}
/* Dark theme */
[data-theme="dark"] {
--ns-tree-bg: #1e1e1e;
--ns-tree-border: #3a3a3a;
/* ... */
}📚 Documentation
- Полная документация - 22 раздела с примерами
- SUPPLEMENTARY
📄 License
MIT License - см. LICENSE
Автор: Besnovatyj Версия: 1.3.1 Обновлено: 2026-06-10
