{"_id":"@besnovatyj/tree-widget-core","_rev":"8-fadc907165a2bc99a7c7bdad2782cf54","name":"@besnovatyj/tree-widget-core","dist-tags":{"latest":"1.3.2"},"versions":{"1.0.0":{"name":"@besnovatyj/tree-widget-core","version":"1.0.0","keywords":["tree","nested-sets","drag-and-drop","typescript","widget"],"author":{"name":"Besnovatyj"},"license":"MIT","_id":"@besnovatyj/tree-widget-core@1.0.0","maintainers":[{"name":"besnovatyj","email":"metr31@yandex.ru"}],"dist":{"shasum":"d2662a37456296ed842ac083b682fb6588201582","tarball":"https://registry.npmjs.org/@besnovatyj/tree-widget-core/-/tree-widget-core-1.0.0.tgz","fileCount":124,"integrity":"sha512-9QE2BU4YlqnxsUI/6SUNKY+yXia2jIEiHA0n85g/aWUerMwoth90uwJdJBvB0bI/9zS9en5mHxwgcgAuwiwWgQ==","signatures":[{"sig":"MEYCIQCi/9FSyFxGM1MVtxVhsb9qpOhbnDS72xC7q01dtTV5bAIhAP2akQ2u+g1X9fD/nFSDrxD3cYXaKbB0Zbmfwc2sXhvP","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":658608},"main":"./dist/index.js","type":"module","types":"./dist/app/index.d.ts","engines":{"npm":">= 10.0.0","node":">= 23.3.0"},"exports":{".":{"types":"./dist/app/index.d.ts","import":"./dist/index.js"},"./styles":"./dist/styles.css"},"gitHead":"3449e10412d110cc976241fec035fc77fa26db57","scripts":{"build":"node esbuild.config.js","types":"tsc -p tsconfig.json --emitDeclarationOnly --declaration --noEmit false --outDir dist && tsc-alias -p tsconfig.json","watch":"node esbuild.config.js --watch","type-check":"tsc --noEmit","prepublishOnly":"npm run build && npm run types"},"_npmUser":{"name":"besnovatyj","email":"metr31@yandex.ru"},"_npmVersion":"11.16.0","description":"Framework-agnostic Nested Sets tree widget (ядро). Цепляется к любому бэкенду через ITreeDataSource.","directories":{},"_nodeVersion":"24.16.0","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.28.0","tsc-alias":"^1.8.16","typescript":"^5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/tree-widget-core_1.0.0_1781081911438_0.4695017337475973","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@besnovatyj/tree-widget-core","version":"1.1.0","keywords":["tree","nested-sets","drag-and-drop","typescript","widget"],"author":{"name":"Besnovatyj"},"license":"MIT","_id":"@besnovatyj/tree-widget-core@1.1.0","maintainers":[{"name":"besnovatyj","email":"metr31@yandex.ru"}],"dist":{"shasum":"bc4a394abab7fb0f6e60d270ed1d318b3be9e326","tarball":"https://registry.npmjs.org/@besnovatyj/tree-widget-core/-/tree-widget-core-1.1.0.tgz","fileCount":126,"integrity":"sha512-4imrj9Jd/w604kTwxbHhLNtyIAzjEOn/sZguvZtx4ReqL8wphN7UBpCfW0npQLvAILsIwdph20zqJJJxIl32Mg==","signatures":[{"sig":"MEQCIC9YNLx+YHnbk41no0ARGrtjdiMTMarc0wZKtaFpBW5ZAiBl/bwgrGVYW44AoD1T9ZOrqRBg1SD8/PsN8W0CAl2acQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1002432},"main":"./dist/index.js","type":"module","types":"./dist/app/index.d.ts","module":"./dist/index.esm.js","engines":{"npm":">= 10.0.0","node":">= 23.3.0"},"exports":{".":{"types":"./dist/app/index.d.ts","import":"./dist/index.esm.js"},"./styles":"./dist/styles.css"},"gitHead":"a4e81e1813875e54b56ecd3f9dddac1fe6470c5a","scripts":{"build":"node esbuild.config.js","types":"tsc -p tsconfig.json --emitDeclarationOnly --declaration --noEmit false --outDir dist && tsc-alias -p tsconfig.json","watch":"node esbuild.config.js --watch","type-check":"tsc --noEmit","prepublishOnly":"npm run build && npm run types"},"_npmUser":{"name":"besnovatyj","email":"metr31@yandex.ru"},"_npmVersion":"11.16.0","description":"Framework-agnostic Nested Sets tree widget (ядро). Цепляется к любому бэкенду через ITreeDataSource.","directories":{},"_nodeVersion":"24.16.0","allowScripts":{"esbuild@0.28.0":true},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.28.0","tsc-alias":"^1.8.16","typescript":"^5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/tree-widget-core_1.1.0_1781082806087_0.4053153530659208","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@besnovatyj/tree-widget-core","version":"1.2.0","keywords":["tree","nested-sets","drag-and-drop","typescript","widget"],"author":{"name":"Besnovatyj"},"license":"MIT","_id":"@besnovatyj/tree-widget-core@1.2.0","maintainers":[{"name":"besnovatyj","email":"metr31@yandex.ru"}],"dist":{"shasum":"1b375012fec0f3a3288b43c011ca61c53ff3d5cc","tarball":"https://registry.npmjs.org/@besnovatyj/tree-widget-core/-/tree-widget-core-1.2.0.tgz","fileCount":132,"integrity":"sha512-+fk6KpsXR2xXG3Pu4bYHRKnZmEWJihAEVLGIeTNGz1hLuB6NS9pxhbkZZwK7e/LOUVC4ANS4astVKMdfzcWpVw==","signatures":[{"sig":"MEYCIQC7rAwZPsXYkfC2TR2QUwsjSWRNgk6DAWfHK5FKsoLexAIhAIC5uYkvoaFN0t6pN8rcROVkapHySNdgcdSt+qJvI8U0","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1048311},"main":"./dist/index.js","type":"module","types":"./dist/app/index.d.ts","module":"./dist/index.esm.js","engines":{"npm":">= 10.0.0","node":">= 23.3.0"},"exports":{".":{"types":"./dist/app/index.d.ts","import":"./dist/index.esm.js"},"./styles":"./dist/styles.css"},"gitHead":"0277be3ca3d76eed8a387515df880c55e9f650a4","scripts":{"build":"node esbuild.config.js","types":"tsc -p tsconfig.json --emitDeclarationOnly --declaration --noEmit false --outDir dist && tsc-alias -p tsconfig.json","watch":"node esbuild.config.js --watch","type-check":"tsc --noEmit","prepublishOnly":"npm run build && npm run types"},"_npmUser":{"name":"besnovatyj","email":"metr31@yandex.ru"},"_npmVersion":"11.16.0","description":"Framework-agnostic Nested Sets tree widget (ядро). Цепляется к любому бэкенду через ITreeDataSource.","directories":{},"_nodeVersion":"24.16.0","allowScripts":{"esbuild@0.28.0":true},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.28.0","tsc-alias":"^1.8.16","typescript":"^5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/tree-widget-core_1.2.0_1781087543627_0.998834111637616","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"name":"@besnovatyj/tree-widget-core","version":"1.2.1","keywords":["tree","nested-sets","drag-and-drop","typescript","widget"],"author":{"name":"Besnovatyj"},"license":"MIT","_id":"@besnovatyj/tree-widget-core@1.2.1","maintainers":[{"name":"besnovatyj","email":"metr31@yandex.ru"}],"dist":{"shasum":"5f8d12279b6e56aed19933eee49bab418d0241b8","tarball":"https://registry.npmjs.org/@besnovatyj/tree-widget-core/-/tree-widget-core-1.2.1.tgz","fileCount":132,"integrity":"sha512-TTVqkkHyKLVvu2vRz8exd8HfCRfh3ZU3DsHStbI1bm5wGi+U2QEwwbWRWwDuYj8JfKO9QrI0lR12MnJQs6+gog==","signatures":[{"sig":"MEYCIQCDhwSzhyPG1NT2NBaebOVPzNQV1wjxcrmSbrFJI4MrowIhAOeqepPcVqVXvoBWuESJ4bXrtd9TClg6fjWTWPnhBIhe","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1060517},"main":"./dist/index.js","type":"module","types":"./dist/app/index.d.ts","module":"./dist/index.esm.js","engines":{"npm":">= 10.0.0","node":">= 23.3.0"},"exports":{".":{"types":"./dist/app/index.d.ts","import":"./dist/index.esm.js"},"./styles":"./dist/styles.css"},"gitHead":"865c80356089389b6fbde402db247313707315d6","scripts":{"build":"node esbuild.config.js","types":"tsc -p tsconfig.json --emitDeclarationOnly --declaration --noEmit false --outDir dist && tsc-alias -p tsconfig.json","watch":"node esbuild.config.js --watch","type-check":"tsc --noEmit","prepublishOnly":"npm run build && npm run types"},"_npmUser":{"name":"besnovatyj","email":"metr31@yandex.ru"},"_npmVersion":"11.16.0","description":"Framework-agnostic Nested Sets tree widget (ядро). Цепляется к любому бэкенду через ITreeDataSource.","directories":{},"_nodeVersion":"24.16.0","allowScripts":{"esbuild@0.28.0":true},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.28.0","tsc-alias":"^1.8.16","typescript":"^5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/tree-widget-core_1.2.1_1781088572868_0.5537303851003503","host":"s3://npm-registry-packages-npm-production"}},"1.2.2":{"name":"@besnovatyj/tree-widget-core","version":"1.2.2","keywords":["tree","nested-sets","drag-and-drop","typescript","widget"],"author":{"name":"Besnovatyj"},"license":"MIT","_id":"@besnovatyj/tree-widget-core@1.2.2","maintainers":[{"name":"besnovatyj","email":"metr31@yandex.ru"}],"dist":{"shasum":"0be06c44a2a62ce1e3d949580df471178480d6ac","tarball":"https://registry.npmjs.org/@besnovatyj/tree-widget-core/-/tree-widget-core-1.2.2.tgz","fileCount":132,"integrity":"sha512-UXtzpzVmxJ8YgrkLS4H+w6DlNS6jE/jxhFhvASo2g/hsd5WcEu0Z6Shjo0w3oQLl8PledTxUg4bnJ4vrCmc/Iw==","signatures":[{"sig":"MEYCIQD3IARtIm3gBHDe3vXqjYblb4ojkrsTAAmCEqmiYoakPQIhAK/d+NzSa8H0rrHSuZVItPAXXaG68FoHLvgYPZQVHf4Y","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1062372},"main":"./dist/index.js","type":"module","types":"./dist/app/index.d.ts","module":"./dist/index.esm.js","engines":{"npm":">= 10.0.0","node":">= 23.3.0"},"exports":{".":{"types":"./dist/app/index.d.ts","import":"./dist/index.esm.js"},"./styles":"./dist/styles.css"},"gitHead":"9c47f84e0a424fd09b1b94ffa72ca5e55addf075","scripts":{"build":"node esbuild.config.js","types":"tsc -p tsconfig.json --emitDeclarationOnly --declaration --noEmit false --outDir dist && tsc-alias -p tsconfig.json","watch":"node esbuild.config.js --watch","type-check":"tsc --noEmit","prepublishOnly":"npm run build && npm run types"},"_npmUser":{"name":"besnovatyj","email":"metr31@yandex.ru"},"_npmVersion":"11.16.0","description":"Framework-agnostic Nested Sets tree widget (ядро). Цепляется к любому бэкенду через ITreeDataSource.","directories":{},"_nodeVersion":"24.16.0","allowScripts":{"esbuild@0.28.0":true},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.28.0","tsc-alias":"^1.8.16","typescript":"^5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/tree-widget-core_1.2.2_1781089316332_0.9845058386337446","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@besnovatyj/tree-widget-core","version":"1.3.0","keywords":["tree","nested-sets","drag-and-drop","typescript","widget"],"author":{"name":"Besnovatyj"},"license":"MIT","_id":"@besnovatyj/tree-widget-core@1.3.0","maintainers":[{"name":"besnovatyj","email":"metr31@yandex.ru"}],"dist":{"shasum":"8eec625e281faf84061040279160cd127949eef6","tarball":"https://registry.npmjs.org/@besnovatyj/tree-widget-core/-/tree-widget-core-1.3.0.tgz","fileCount":132,"integrity":"sha512-xJuMbHVYJm2Wn/RIXBK8VBXhGofgfiSd+W7MrJ8Kvd7HDkKq7rsL6fiF8XdgU4uvEnazBno7MPq9DNtP5T3nKw==","signatures":[{"sig":"MEYCIQC+l5TJsa03hp5a2yGQCZcc5q9C5hCnTyeJPt2Fy4R+WgIhAKJqUE4y46U3YjGtEcdnlMrIJZCJbOSN6jLH0BKHk99a","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1050573},"main":"./dist/index.js","type":"module","types":"./dist/app/index.d.ts","module":"./dist/index.esm.js","engines":{"npm":">= 10.0.0","node":">= 23.3.0"},"exports":{".":{"types":"./dist/app/index.d.ts","import":"./dist/index.esm.js"},"./styles":"./dist/styles.css"},"gitHead":"cf4e141896591698553cd9b025a73b0b49a6c570","scripts":{"build":"node esbuild.config.js","types":"tsc -p tsconfig.json --emitDeclarationOnly --declaration --noEmit false --outDir dist && tsc-alias -p tsconfig.json","watch":"node esbuild.config.js --watch","type-check":"tsc --noEmit","prepublishOnly":"npm run build && npm run types"},"_npmUser":{"name":"besnovatyj","email":"metr31@yandex.ru"},"_npmVersion":"11.16.0","description":"Framework-agnostic Nested Sets tree widget (ядро). Цепляется к любому бэкенду через ITreeDataSource.","directories":{},"_nodeVersion":"24.16.0","allowScripts":{"esbuild@0.28.0":true},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.28.0","tsc-alias":"^1.8.16","typescript":"^5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/tree-widget-core_1.3.0_1781092249895_0.19146766200570986","host":"s3://npm-registry-packages-npm-production"}},"1.3.1":{"name":"@besnovatyj/tree-widget-core","version":"1.3.1","keywords":["tree","nested-sets","drag-and-drop","typescript","widget"],"author":{"name":"Besnovatyj"},"license":"MIT","_id":"@besnovatyj/tree-widget-core@1.3.1","maintainers":[{"name":"besnovatyj","email":"metr31@yandex.ru"}],"dist":{"shasum":"d152738c63b0594080954c409f6fbedba726494c","tarball":"https://registry.npmjs.org/@besnovatyj/tree-widget-core/-/tree-widget-core-1.3.1.tgz","fileCount":132,"integrity":"sha512-dTBBXTojnwEU6MXeEzQvxs/dZuMGMvq9pWEeDxFnL2/OHs1xOmTsKoOsaLtIJE4KMhJMBOI4ttpIzJTjpTOfcA==","signatures":[{"sig":"MEYCIQCJ6Z7oNIPxs2V+veTpkuVybPQ2SuKrSqOBLKe4UDyeGgIhAPz7jupig2RNTkdDQu4aoXfzG7E+DzfG5uT1xxdD2yZ+","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1056278},"main":"./dist/index.js","type":"module","types":"./dist/app/index.d.ts","module":"./dist/index.esm.js","engines":{"npm":">= 10.0.0","node":">= 23.3.0"},"exports":{".":{"types":"./dist/app/index.d.ts","import":"./dist/index.esm.js"},"./styles":"./dist/styles.css"},"gitHead":"0c5c4f4479e2211d05ee8202b6eb7229a34a6434","scripts":{"build":"node esbuild.config.js","types":"tsc -p tsconfig.json --emitDeclarationOnly --declaration --noEmit false --outDir dist && tsc-alias -p tsconfig.json","watch":"node esbuild.config.js --watch","type-check":"tsc --noEmit","prepublishOnly":"npm run build && npm run types"},"_npmUser":{"name":"besnovatyj","email":"metr31@yandex.ru"},"_npmVersion":"11.16.0","description":"Framework-agnostic Nested Sets tree widget (ядро). Цепляется к любому бэкенду через ITreeDataSource.","directories":{},"_nodeVersion":"24.16.0","allowScripts":{"esbuild@0.28.0":true},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.28.0","tsc-alias":"^1.8.16","typescript":"^5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/tree-widget-core_1.3.1_1781094165586_0.22135396260900975","host":"s3://npm-registry-packages-npm-production"}},"1.3.2":{"name":"@besnovatyj/tree-widget-core","version":"1.3.2","description":"Framework-agnostic Nested Sets tree widget (ядро). Цепляется к любому бэкенду через ITreeDataSource.","type":"module","main":"./dist/index.js","types":"./dist/app/index.d.ts","repository":{"type":"git","url":"git+https://github.com/besnovatyj/tree-widget-core.git"},"bugs":{"url":"https://github.com/besnovatyj/tree-widget-core/issues"},"homepage":"https://github.com/besnovatyj/tree-widget-core#readme","exports":{".":{"types":"./dist/app/index.d.ts","import":"./dist/index.esm.js"},"./styles":"./dist/styles.css"},"publishConfig":{"access":"public"},"scripts":{"build":"node esbuild.config.js","watch":"node esbuild.config.js --watch","type-check":"tsc --noEmit","types":"tsc -p tsconfig.json --emitDeclarationOnly --declaration --noEmit false --outDir dist && tsc-alias -p tsconfig.json","prepublishOnly":"npm run build && npm run types"},"keywords":["tree","nested-sets","drag-and-drop","typescript","widget"],"author":{"name":"Besnovatyj"},"license":"MIT","devDependencies":{"esbuild":"^0.28.0","tsc-alias":"^1.8.16","typescript":"^5.9.3"},"engines":{"node":">= 23.3.0","npm":">= 10.0.0"},"module":"./dist/index.esm.js","allowScripts":{"esbuild@0.28.0":true},"gitHead":"0c79aa250c3eb10f79e06615c03abda46d7fd5b3","_id":"@besnovatyj/tree-widget-core@1.3.2","_nodeVersion":"24.16.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-yRuEWJyvm4LOnwnjdWE0Iig77GmUyv80YGbK5Tt2mRlY4UVkl33zenoi+RMfFm+AvMVE6TQf/Z1uEqSqFJWkBQ==","shasum":"9ad160fcf4d227f5507b6d5f320a590f9d050f20","tarball":"https://registry.npmjs.org/@besnovatyj/tree-widget-core/-/tree-widget-core-1.3.2.tgz","fileCount":90,"unpackedSize":848320,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIDG1u/qIFfXJpEWODLiVtGAubkN7TOYlyJGLrojrdoe0AiBxOgO4vrtQjkEkBZjMgLsjSk1MdJbeKdNf0Tqa4JVJwQ=="}]},"_npmUser":{"name":"besnovatyj","email":"metr31@yandex.ru"},"directories":{},"maintainers":[{"name":"besnovatyj","email":"metr31@yandex.ru"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/tree-widget-core_1.3.2_1783527435470_0.4463531303262187"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-10T08:58:31.262Z","modified":"2026-07-08T16:17:15.778Z","1.0.0":"2026-06-10T08:58:31.574Z","1.1.0":"2026-06-10T09:13:26.269Z","1.2.0":"2026-06-10T10:32:23.788Z","1.2.1":"2026-06-10T10:49:33.103Z","1.2.2":"2026-06-10T11:01:56.541Z","1.3.0":"2026-06-10T11:50:50.024Z","1.3.1":"2026-06-10T12:22:45.748Z","1.3.2":"2026-07-08T16:17:15.652Z"},"author":{"name":"Besnovatyj"},"license":"MIT","keywords":["tree","nested-sets","drag-and-drop","typescript","widget"],"description":"Framework-agnostic Nested Sets tree widget (ядро). Цепляется к любому бэкенду через ITreeDataSource.","maintainers":[{"name":"besnovatyj","email":"metr31@yandex.ru"}],"readme":"# @besnovatyj/tree-widget-core\n\nFramework-agnostic Nested Sets tree widget (TypeScript). Ядро цепляется к любому\nбэкенду через интерфейс `ITreeDataSource`; готовая HTTP-реализация\n(`HttpTreeDataSource`) из коробки совместима с `TreeController` пакета\n`besnovatyj/yii2-cms-tree-manager`.\n\n[![Version](https://img.shields.io/badge/version-1.3.1-blue.svg)](./package.json)\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue.svg)](https://www.typescriptlang.org/)\n[![License](https://img.shields.io/badge/license-MIT-green.svg)](./LICENSE)\n\n## ✨ Features\n\n- ✅ **Nested Sets модель** с поддержкой множественных корней\n- ✅ **CRUD операции** - создание, редактирование, удаление узлов\n- ✅ **Drag & Drop** - desktop (HTML5) и mobile (touch с long press), «липкая» цель drop\n- ✅ **Root Drop Zone** - создание корней через drag & drop\n- ✅ **Улучшенная визуализация** - раздвигание узлов для before/after\n- ✅ **Lazy Loading** - подгрузка детей по требованию\n- ✅ **Expand/Collapse** - с сохранением состояния\n- ✅ **Система патчей** - эффективные обновления (explicit/ops)\n- ✅ **Серверные формы** - HTML формы от сервера с валидацией (ошибки полей\n  матчатся и по составным именам вида `FormName[attr]`)\n- ✅ **Доставка ошибок** - доменные сообщения сервера (422 / `success:false`)\n  доезжают до Toast/полей, внутренние ошибки сервера не утекают\n- ✅ **Права доступа** - гранулярный контроль операций (UX-уровень; enforcement — на сервере)\n- ✅ **События** - changed, nodeSelected, beforeRequest, afterRequest, error\n- ✅ **Storage** - LocalStorage/SessionStorage/Memory\n- ✅ **UI компоненты** - Modal, BottomSheet, Toast, Loader, Menu\n- ✅ **Темизация** - CSS переменные, темная тема\n- ✅ **Accessibility** - ARIA атрибуты\n- ✅ **TypeScript Strict** - без runtime-зависимостей\n\n## 📦 Installation\n\n```bash\nnpm install @besnovatyj/tree-widget-core\n```\n\n## 🔌 Два формата подключения\n\n### IIFE (script-тег, глобальная `window.TreeWidget`)\n\n`dist/index.js` — самодостаточный бандл с автоинициализацией контейнеров,\nимеющих атрибут `data-tree-config` (именно его использует Yii2-фасад):\n\n```html\n<link rel=\"stylesheet\" href=\"node_modules/@besnovatyj/tree-widget-core/dist/styles.css\">\n<script src=\"node_modules/@besnovatyj/tree-widget-core/dist/index.js\"></script>\n<script>\n    const widget = TreeWidget.createTreeWidget({ /* ... */ });\n</script>\n```\n\n### ESM (бандлеры / `import`)\n\n`dist/index.esm.js` — то, что отдаёт `exports` пакета:\n\n```typescript\nimport { createTreeWidget } from '@besnovatyj/tree-widget-core';\nimport '@besnovatyj/tree-widget-core/styles';\n\nconst widget = createTreeWidget({\n    widgetId: 'my-tree',\n    container: document.getElementById('tree-container'),\n    dataSource: myDataSource\n});\n\nawait widget.load();\n```\n\n## 🤝 Контракт виджет ↔ бэкенд\n\nВсе фичи виджета работают только с портом `ITreeDataSource`\n(`src/shared/api/tree/ports.ts` — источник истины контракта):\n\n| Метод порта | Endpoint `HttpTreeDataSource` | Экшен TreeController (Yii2-фасад) |\n|---|---|---|\n| `loadRoots()` | — (initialData из конфига) | `index` (данные в страницу) |\n| `loadChildren(id)` | `endpoints.loadChildren` | `load-children` |\n| `createNode(data)` | `endpoints.createNode` | `create` |\n| `updateNode(id, data)` | `endpoints.updateNode` | `update` |\n| `deleteNode(id, mode)` | `endpoints.deleteNode` | `delete` (mode: `subtree`/`reparent`) |\n| `moveNode(...)` | `endpoints.moveNode` | `move` |\n| `toggleStatus(id)` | `endpoints.toggleStatus` | `toggle-status` |\n| `checkIntegrity()` | `endpoints.checkIntegrity` (опц.) | `check-integrity` |\n\nКонтракт ошибок: доменные ошибки приходят как HTTP 422 с осмысленным `message`\n(или HTTP 200 + `success:false` + `message`) и показываются пользователю;\nпрочие статусы показываются нейтрально. Ошибки валидации форм — `errors`\n(`attr` → `[messages]`), раскладываются по полям формы.\n\n## 🚀 Integration Examples\n\n### Yii2 (через HTTP-реализацию порта)\n\n```typescript\nimport { createYii2TreeWidget } from '@besnovatyj/tree-widget-core';\n\nconst widget = createYii2TreeWidget({\n    widgetId: 'my-tree',\n    container: document.getElementById('tree-container'),\n    initialData: window.treeData,\n    endpoints: {\n        loadChildren: '/tree/load-children',\n        createNode: '/tree/create',\n        updateNode: '/tree/update',\n        deleteNode: '/tree/delete',\n        moveNode: '/tree/move',\n        toggleStatus: '/tree/toggle-status'\n    },\n    csrfToken: document.querySelector('meta[name=\"csrf-token\"]')?.content\n});\n\nawait widget.load();\n```\n\n> Имена `Yii2TreeBackend` / `Yii2BackendConfig` — deprecated-алиасы;\n> новые имена: `HttpTreeDataSource` / `HttpDataSourceConfig` (ядро agnostic,\n> от Yii2 в HTTP-реализации — только дефолтный источник CSRF-токена).\n\n### Свой бэкенд (REST/GraphQL/mock)\n\n```typescript\nimport type { ITreeDataSource } from '@besnovatyj/tree-widget-core';\n\nclass RestApiTreeDataSource implements ITreeDataSource {\n    async loadRoots(): Promise<TreeNodeDto[]> {\n        const response = await fetch('/api/tree/roots');\n        return response.json();\n    }\n\n    // ... остальные методы порта\n}\n\nconst widget = createTreeWidget({\n    widgetId: 'my-tree',\n    container: document.getElementById('tree-container'),\n    dataSource: new RestApiTreeDataSource()\n});\n```\n\n## 🛠️ Development\n\n### Scripts\n\n```bash\nnpm run build       # esbuild: dist/index.js (IIFE) + dist/index.esm.js (ESM) + dist/styles.css\nnpm run watch       # build с watch\nnpm run type-check  # tsc --noEmit\nnpm run types       # эмиссия .d.ts в dist (tsc + tsc-alias, пути без @shared/*)\n# npm publish сам выполнит build + types (prepublishOnly)\n```\n\n### Project Structure (FSD)\n\n```\nsrc/\n├── app/                    # Public API (index.ts — entry, автоинициализация)\n├── widgets/               # Widgets\n│   └── tree/             # Tree widget\n├── features/             # Business features\n│   ├── create-node/      # Create nodes\n│   ├── edit-node/        # Edit nodes\n│   ├── delete-node/      # Delete nodes\n│   ├── move-node/        # Move (drag & drop)\n│   └── ...\n├── entities/             # Business entities\n│   └── node/             # Tree node\n├── shared/               # Shared modules\n│   ├── api/             # Transport, HttpError, порт ITreeDataSource + HTTP-реализация\n│   ├── ui/              # UI components\n│   ├── lib/             # Utils (включая applyFieldErrors)\n│   └── config/          # Types & configs\n└── styles/              # CSS styles\n```\n\n### Связанные пакеты (порядок сборки)\n\n1. **этот пакет** — публикуется в npm (`npm publish`);\n2. `besnovatyj/yii2-cms-tree-manager` (composer) — бандлит ESM-сборку ядра в свой\n   `assets/dist/` (esbuild.js в корне пакета) и отдаёт через Yii2 AssetBundle;\n3. `besnovatyj/yii2-nested-sets` (composer) — PHP-ядро Nested Sets, серверная\n   сторона контракта.\n\n## 📝 Example\n\nСм. [example.html](./example.html) — рабочий пример на mock-данных (ESM-сборка).\n\n## 🎨 Theming\n\nВиджет использует CSS переменные:\n\n```css\n:root {\n    --ns-tree-primary: #007bff;\n    --ns-tree-bg: #ffffff;\n    --ns-tree-border: #e0e0e0;\n    /* ... */\n}\n\n/* Dark theme */\n[data-theme=\"dark\"] {\n    --ns-tree-bg: #1e1e1e;\n    --ns-tree-border: #3a3a3a;\n    /* ... */\n}\n```\n\n## 📚 Documentation\n\n- **[Полная документация](./docs/FullDoc.md)** - 22 раздела с примерами\n- [SUPPLEMENTARY](./docs/SUPPLEMENTARY.md)\n\n## 📄 License\n\nMIT License - см. [LICENSE](./LICENSE)\n\n---\n\n**Автор:** Besnovatyj\n**Версия:** 1.3.1\n**Обновлено:** 2026-06-10\n","readmeFilename":"README.md","homepage":"https://github.com/besnovatyj/tree-widget-core#readme","repository":{"type":"git","url":"git+https://github.com/besnovatyj/tree-widget-core.git"},"bugs":{"url":"https://github.com/besnovatyj/tree-widget-core/issues"}}