{"_id":"@n-uf/hypr-tiling","_rev":"28-daf7a1dc34a171944571a6b71407d976","name":"@n-uf/hypr-tiling","dist-tags":{"latest":"26.11.6"},"versions":{"26.7.0":{"name":"@n-uf/hypr-tiling","version":"26.7.0","keywords":["react","tiling","dynamic-tiling","split-layout","split-pane","pane-layout","react-layout","dock-layout","window-manager-ui","resizable-panes","drag-and-drop","tiling-window-manager","layout-engine","dashboard","hyprland"],"license":"LicenseRef-PolyForm-Perimeter-1.0.1","_id":"@n-uf/hypr-tiling@26.7.0","maintainers":[{"name":"metelin","email":"metelin@gmail.com"}],"homepage":"https://hypr-tiling.n-uf.com/","bugs":{"url":"https://github.com/n-uf/hypr-tiling/issues"},"dist":{"shasum":"f39d174a61032741f0cc2d1c833e81d9ac2a0607","tarball":"https://registry.npmjs.org/@n-uf/hypr-tiling/-/hypr-tiling-26.7.0.tgz","fileCount":20,"integrity":"sha512-yp9fNJrzUDfgLFjFSHSKoYZPL/2G5W3swxjymXET1EeOoD1ml7yi9A4ctI9uTFytV95awiv0OgjpqQ77MiAXRQ==","signatures":[{"sig":"MEUCIQD977eUnR2Hu2y+okrW169acr5MEOsy2ZRFJKDOBXBg7QIgRUfkK9TdK9EmJalZHsH8snkcSLCDHAHFcfMOrnXlF5c=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2033733},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./engine":{"types":"./dist/engine.d.ts","import":"./dist/engine.mjs","require":"./dist/engine.cjs"},"./devtools":{"types":"./dist/devtools.d.ts","import":"./dist/devtools.mjs","require":"./dist/devtools.cjs"}},"gitHead":"f7201f817bdcbfb7289c711d1e45bb907952a719","private":false,"scripts":{"test":"jest","build":"tsup","check":"pnpm typecheck && pnpm test","release":"if [ \"$npm_config_nobump\" = \"true\" ]; then npm publish --access public; else node ./scripts/calendar-version-bump.mjs --apply && npm publish --access public; fi","api:docs":"node ./scripts/generate-api-docs.mjs","api:check":"api-extractor run --verbose -c api-extractor.index.json && api-extractor run --verbose -c api-extractor.devtools.json && api-extractor run --verbose -c api-extractor.engine.json","typecheck":"tsc --project tsconfig.json","api:update":"api-extractor run --local --verbose -c api-extractor.index.json && api-extractor run --local --verbose -c api-extractor.devtools.json && api-extractor run --local --verbose -c api-extractor.engine.json","prepublishOnly":"pnpm build","check:guardrails":"node ./scripts/check-guardrails.mjs","release:next-version":"node ./scripts/calendar-version-bump.mjs --dry-run"},"_npmUser":{"name":"metelin","email":"metelin@gmail.com"},"repository":{"url":"git+https://github.com/n-uf/hypr-tiling.git","type":"git"},"_npmVersion":"11.16.0","description":"Dynamic tiling for React: a recursive split-tree renderer for drag/drop, resizable, keyboard-controlled panes — inspired by Hyprland.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","dependencies":{"clsx":"^2.1.1","tailwind-merge":"^2.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.2.0","tsup":"^8.5.0","react":"^19.2.7","marked":"^18.0.5","ts-jest":"^29.4.5","react-dom":"^19.2.7","typescript":"^5.9.3","@types/jest":"^30.0.0","@types/node":"^26.0.1","@types/react":"^19","@jest/globals":"^30.2.0","@types/react-dom":"^19","@testing-library/react":"^16.3.2","jest-environment-jsdom":"^30.4.1","@microsoft/api-extractor":"^7.58.9","@microsoft/api-documenter":"^7.30.7"},"peerDependencies":{"react":"^19","react-dom":"^19"},"_npmOperationalInternal":{"tmp":"tmp/hypr-tiling_26.7.0_1783047873583_0.9519053312714394","host":"s3://npm-registry-packages-npm-production"}},"26.7.1":{"name":"@n-uf/hypr-tiling","version":"26.7.1","keywords":["react","tiling","dynamic-tiling","split-layout","split-pane","pane-layout","react-layout","dock-layout","window-manager-ui","resizable-panes","drag-and-drop","tiling-window-manager","layout-engine","dashboard","hyprland"],"license":"LicenseRef-PolyForm-Perimeter-1.0.1","_id":"@n-uf/hypr-tiling@26.7.1","maintainers":[{"name":"metelin","email":"metelin@gmail.com"}],"homepage":"https://hypr-tiling.n-uf.com/","bugs":{"url":"https://github.com/n-uf/hypr-tiling/issues"},"dist":{"shasum":"71b2841294ae34aa25046c85695147ae9d9aa1fe","tarball":"https://registry.npmjs.org/@n-uf/hypr-tiling/-/hypr-tiling-26.7.1.tgz","fileCount":20,"integrity":"sha512-bLP/r7EvVrEpCfG8GoF2tDbw9bV2JWlJrnakZvOs9gkDdHz1jqY3Kda1sWGgv3rGXsbHVbOwFuZsEKa5f7HohA==","signatures":[{"sig":"MEQCICynGr6bhYLhaEdeX7pMB6DvsrC4+qLHk0A7sgsLuJ1fAiAehdL983t8sk46TnaoiOnqkycJxasCugZQTuZ2bkjv9A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2034974},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./engine":{"types":"./dist/engine.d.ts","import":"./dist/engine.mjs","require":"./dist/engine.cjs"},"./devtools":{"types":"./dist/devtools.d.ts","import":"./dist/devtools.mjs","require":"./dist/devtools.cjs"}},"gitHead":"2bae3891b42eb9a051bfc1ac135f3b4a79a0bee2","private":false,"scripts":{"test":"jest","build":"tsup","check":"pnpm typecheck && pnpm test","release":"if [ \"$npm_config_nobump\" = \"true\" ]; then npm publish --access public; else node ./scripts/calendar-version-bump.mjs --apply && npm publish --access public; fi","api:docs":"node ./scripts/generate-api-docs.mjs","api:check":"api-extractor run --verbose -c api-extractor.index.json && api-extractor run --verbose -c api-extractor.devtools.json && api-extractor run --verbose -c api-extractor.engine.json","typecheck":"tsc --project tsconfig.json","api:update":"api-extractor run --local --verbose -c api-extractor.index.json && api-extractor run --local --verbose -c api-extractor.devtools.json && api-extractor run --local --verbose -c api-extractor.engine.json","prepublishOnly":"pnpm build","check:guardrails":"node ./scripts/check-guardrails.mjs","release:next-version":"node ./scripts/calendar-version-bump.mjs --dry-run"},"_npmUser":{"name":"metelin","email":"metelin@gmail.com"},"repository":{"url":"git+https://github.com/n-uf/hypr-tiling.git","type":"git"},"_npmVersion":"11.16.0","description":"Dynamic tiling for React: a recursive split-tree renderer for drag/drop, resizable, keyboard-controlled panes — inspired by Hyprland.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","dependencies":{"clsx":"^2.1.1","tailwind-merge":"^2.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.2.0","tsup":"^8.5.0","react":"^19.2.7","marked":"^18.0.5","ts-jest":"^29.4.5","react-dom":"^19.2.7","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^26.0.1","@types/react":"^19","@jest/globals":"^30.2.0","@types/react-dom":"^19","@testing-library/react":"^16.3.2","jest-environment-jsdom":"^30.4.1","@microsoft/api-extractor":"^7.58.9","@microsoft/api-documenter":"^7.30.7"},"peerDependencies":{"react":"^19","react-dom":"^19"},"_npmOperationalInternal":{"tmp":"tmp/hypr-tiling_26.7.1_1783053435932_0.14202574031384652","host":"s3://npm-registry-packages-npm-production"}},"26.7.2":{"name":"@n-uf/hypr-tiling","version":"26.7.2","keywords":["react","tiling","dynamic-tiling","split-layout","split-pane","pane-layout","react-layout","dock-layout","window-manager-ui","resizable-panes","drag-and-drop","tiling-window-manager","layout-engine","dashboard","hyprland"],"license":"LicenseRef-PolyForm-Perimeter-1.0.1","_id":"@n-uf/hypr-tiling@26.7.2","maintainers":[{"name":"metelin","email":"metelin@gmail.com"}],"homepage":"https://hypr-tiling.n-uf.com/","bugs":{"url":"https://github.com/n-uf/hypr-tiling/issues"},"dist":{"shasum":"8470729b69c422924586bd98d7b87323ad02d157","tarball":"https://registry.npmjs.org/@n-uf/hypr-tiling/-/hypr-tiling-26.7.2.tgz","fileCount":21,"integrity":"sha512-BOdHdWz0RKBgRQ/DaE2TGeYK6KtqHIdbKT/XoUJ5ooaDURVsMrcOH8vfWztKnTvnS5uvV2qVSSu4T4tkYSEv7Q==","signatures":[{"sig":"MEYCIQCorHUJhT2RaaTNVYlt4RJmAOZWqPnH36ER0QcheIMW8wIhAMyABwbhAmU9YqwjLmx2Gy+iggVlYCFxP/hfBjZVfP9+","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2222555},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./engine":{"types":"./dist/engine.d.ts","import":"./dist/engine.mjs","require":"./dist/engine.cjs"},"./devtools":{"types":"./dist/devtools.d.ts","import":"./dist/devtools.mjs","require":"./dist/devtools.cjs"}},"gitHead":"2539355ddf9c084ee1f32aef1baea7bd38684b61","private":false,"scripts":{"test":"jest","build":"tsup","check":"pnpm typecheck && pnpm test","release":"if [ \"$npm_config_nobump\" = \"true\" ]; then npm publish --access public; else node ./scripts/calendar-version-bump.mjs --apply && npm publish --access public; fi","api:docs":"node ./scripts/generate-api-docs.mjs","api:check":"api-extractor run --verbose -c api-extractor.index.json && api-extractor run --verbose -c api-extractor.devtools.json && api-extractor run --verbose -c api-extractor.engine.json","typecheck":"tsc --project tsconfig.json","api:update":"api-extractor run --local --verbose -c api-extractor.index.json && api-extractor run --local --verbose -c api-extractor.devtools.json && api-extractor run --local --verbose -c api-extractor.engine.json","prepublishOnly":"pnpm build","check:guardrails":"node ./scripts/check-guardrails.mjs","release:next-version":"node ./scripts/calendar-version-bump.mjs --dry-run"},"_npmUser":{"name":"metelin","email":"metelin@gmail.com"},"repository":{"url":"git+https://github.com/n-uf/hypr-tiling.git","type":"git"},"_npmVersion":"11.16.0","description":"Dynamic tiling for React: a recursive split-tree renderer for drag/drop, resizable, keyboard-controlled panes — inspired by Hyprland.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","dependencies":{"clsx":"^2.1.1","tailwind-merge":"^2.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.2.0","tsup":"^8.5.0","react":"^19.2.7","marked":"^18.0.5","ts-jest":"^29.4.5","react-dom":"^19.2.7","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^26.0.1","@types/react":"^19","@jest/globals":"^30.2.0","@types/react-dom":"^19","@testing-library/react":"^16.3.2","jest-environment-jsdom":"^30.4.1","@microsoft/api-extractor":"^7.58.9","@microsoft/api-documenter":"^7.30.7"},"peerDependencies":{"react":"^19","react-dom":"^19"},"_npmOperationalInternal":{"tmp":"tmp/hypr-tiling_26.7.2_1785405946424_0.7513475416977877","host":"s3://npm-registry-packages-npm-production"}},"26.9.0":{"name":"@n-uf/hypr-tiling","version":"26.9.0","keywords":["react","tiling","dynamic-tiling","split-layout","split-pane","pane-layout","react-layout","dock-layout","window-manager-ui","resizable-panes","drag-and-drop","tiling-window-manager","layout-engine","dashboard","hyprland"],"license":"LicenseRef-PolyForm-Perimeter-1.0.1","_id":"@n-uf/hypr-tiling@26.9.0","maintainers":[{"name":"metelin","email":"metelin@gmail.com"}],"homepage":"https://hypr-tiling.n-uf.com/","bugs":{"url":"https://github.com/n-uf/hypr-tiling/issues"},"dist":{"shasum":"99c6975de99e8b92557d554af07d41d6477c308b","tarball":"https://registry.npmjs.org/@n-uf/hypr-tiling/-/hypr-tiling-26.9.0.tgz","fileCount":22,"integrity":"sha512-RcFfPhNEPa9GkVMIQbNoZHax5tiE3KPMYjUqeXbwG5zLAgR/C88+bmOZRGoK8FvIqsnwbz00Ug8NQzKEP2/Itw==","signatures":[{"sig":"MEUCIQDlqVN47ThLVOcxZuBV0OSupZOE2rWy/sLcV47mr70x7QIgZfkeMHfqvcKprRHvIgI9TdlfMlubyRTQblfedTg8qwI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIEka8oLFE5EIegCZiPQXKQlIgKAWEFN8C6/VyskU0SjrAiEA/ac68oGtl4UndffBoJ9VuFvhcwJhICjOtvmkybmNCk8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2282679},"main":"./dist/index.cjs","_from":"file:n-uf-hypr-tiling-26.9.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./engine":{"types":"./dist/engine.d.ts","import":"./dist/engine.mjs","require":"./dist/engine.cjs"},"./devtools":{"types":"./dist/devtools.d.ts","import":"./dist/devtools.mjs","require":"./dist/devtools.cjs"}},"private":false,"scripts":{"test":"jest","build":"tsup","check":"pnpm typecheck && pnpm test","release":"if [ \"$npm_config_nobump\" = \"true\" ]; then npm publish --access public; else node ./scripts/calendar-version-bump.mjs --apply && npm publish --access public; fi","api:docs":"node ./scripts/generate-api-docs.mjs","api:check":"api-extractor run --verbose -c api-extractor.index.json && api-extractor run --verbose -c api-extractor.devtools.json && api-extractor run --verbose -c api-extractor.engine.json","typecheck":"tsc --project tsconfig.json","api:update":"api-extractor run --local --verbose -c api-extractor.index.json && api-extractor run --local --verbose -c api-extractor.devtools.json && api-extractor run --local --verbose -c api-extractor.engine.json","check:guardrails":"node ./scripts/check-guardrails.mjs","release:next-version":"node ./scripts/calendar-version-bump.mjs --dry-run"},"_npmUser":{"name":"metelin","email":"metelin@gmail.com"},"_resolved":"/private/var/folders/tg/lzzv01z15z3ftkqbl3tsdvg00000gn/T/01d058e2f148d170c466d91f9bf67225/n-uf-hypr-tiling-26.9.0.tgz","_integrity":"sha512-RcFfPhNEPa9GkVMIQbNoZHax5tiE3KPMYjUqeXbwG5zLAgR/C88+bmOZRGoK8FvIqsnwbz00Ug8NQzKEP2/Itw==","repository":{"url":"git+https://github.com/n-uf/hypr-tiling.git","type":"git"},"_npmVersion":"11.16.0","description":"Dynamic tiling for React: a recursive split-tree renderer for drag/drop, resizable, keyboard-controlled panes — inspired by Hyprland.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","dependencies":{"clsx":"^2.1.1","tailwind-merge":"^2.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.2.0","tsup":"^8.5.0","react":"^19.2.7","marked":"^18.0.5","ts-jest":"^29.4.5","react-dom":"^19.2.7","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^26.0.1","@types/react":"^19","@jest/globals":"^30.2.0","@types/react-dom":"^19","@testing-library/react":"^16.3.2","jest-environment-jsdom":"^30.4.1","@microsoft/api-extractor":"^7.58.9","@microsoft/api-documenter":"^7.30.7"},"peerDependencies":{"react":"^19","react-dom":"^19"},"_npmOperationalInternal":{"tmp":"tmp/hypr-tiling_26.9.0_1789959774955_0.12305512604655977","host":"s3://npm-registry-packages-npm-production"}},"26.9.1":{"name":"@n-uf/hypr-tiling","version":"26.9.1","keywords":["react","tiling","dynamic-tiling","split-layout","split-pane","pane-layout","react-layout","dock-layout","window-manager-ui","resizable-panes","drag-and-drop","tiling-window-manager","layout-engine","dashboard","hyprland"],"license":"LicenseRef-PolyForm-Perimeter-1.0.1","_id":"@n-uf/hypr-tiling@26.9.1","maintainers":[{"name":"metelin","email":"metelin@gmail.com"}],"homepage":"https://hypr-tiling.n-uf.com/","bugs":{"url":"https://github.com/n-uf/hypr-tiling/issues"},"dist":{"shasum":"12c08c433f7820eb1d4154492e6f3db61a0bd936","tarball":"https://registry.npmjs.org/@n-uf/hypr-tiling/-/hypr-tiling-26.9.1.tgz","fileCount":22,"integrity":"sha512-ypHERgWnpM2aEu/Rytyh7KSPUxYM1opTSbR+IytLQbqCdt8Z+4HCQdoqMra3pmyB9jETm8qseFBbNO4gFA9x0w==","signatures":[{"sig":"MEUCIQCZ4YLcgC+cPleIZ3nKB+gy7jqMKQiOn7UHEjSjOJv0XgIgGxcB7wEi//3M3CZD6gyWzmAhyhrcE0CgtHRDsek2rrA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDt2C2h0nDaIHAuLqzBv7+2haUgyR+IgQQRFno6r54cFAIhAK7G94DADII+gg72fUowLFKV+nibxGBNbq6K3JZNvxjL","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2295289},"main":"./dist/index.cjs","_from":"file:n-uf-hypr-tiling-26.9.1.tgz","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./engine":{"types":"./dist/engine.d.ts","import":"./dist/engine.mjs","require":"./dist/engine.cjs"},"./devtools":{"types":"./dist/devtools.d.ts","import":"./dist/devtools.mjs","require":"./dist/devtools.cjs"}},"private":false,"scripts":{"test":"jest","build":"tsup","check":"pnpm typecheck && pnpm test","release":"if [ \"$npm_config_nobump\" = \"true\" ]; then npm publish --access public; else node ./scripts/calendar-version-bump.mjs --apply && npm publish --access public; fi","api:docs":"node ./scripts/generate-api-docs.mjs","api:check":"api-extractor run --verbose -c api-extractor.index.json && api-extractor run --verbose -c api-extractor.devtools.json && api-extractor run --verbose -c api-extractor.engine.json","typecheck":"tsc --project tsconfig.json","api:update":"api-extractor run --local --verbose -c api-extractor.index.json && api-extractor run --local --verbose -c api-extractor.devtools.json && api-extractor run --local --verbose -c api-extractor.engine.json","check:guardrails":"node ./scripts/check-guardrails.mjs","release:next-version":"node ./scripts/calendar-version-bump.mjs --dry-run"},"_npmUser":{"name":"metelin","email":"metelin@gmail.com"},"_resolved":"/private/var/folders/tg/lzzv01z15z3ftkqbl3tsdvg00000gn/T/22502cde55bc0e4ddb85eaaeb47411a3/n-uf-hypr-tiling-26.9.1.tgz","_integrity":"sha512-ypHERgWnpM2aEu/Rytyh7KSPUxYM1opTSbR+IytLQbqCdt8Z+4HCQdoqMra3pmyB9jETm8qseFBbNO4gFA9x0w==","repository":{"url":"git+https://github.com/n-uf/hypr-tiling.git","type":"git"},"_npmVersion":"11.16.0","description":"Dynamic tiling for React: a recursive split-tree renderer for drag/drop, resizable, keyboard-controlled panes — inspired by Hyprland.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","dependencies":{"clsx":"^2.1.1","tailwind-merge":"^2.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.2.0","tsup":"^8.5.0","react":"^19.2.7","marked":"^18.0.5","ts-jest":"^29.4.5","react-dom":"^19.2.7","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^26.0.1","@types/react":"^19","@jest/globals":"^30.2.0","@types/react-dom":"^19","@testing-library/react":"^16.3.2","jest-environment-jsdom":"^30.4.1","@microsoft/api-extractor":"^7.58.9","@microsoft/api-documenter":"^7.30.7"},"peerDependencies":{"react":"^19","react-dom":"^19"},"_npmOperationalInternal":{"tmp":"tmp/hypr-tiling_26.9.1_1790035860057_0.9273557873576002","host":"s3://npm-registry-packages-npm-production"}},"26.9.2":{"name":"@n-uf/hypr-tiling","version":"26.9.2","keywords":["react","tiling","dynamic-tiling","split-layout","split-pane","pane-layout","react-layout","dock-layout","window-manager-ui","resizable-panes","drag-and-drop","tiling-window-manager","layout-engine","dashboard","hyprland"],"license":"LicenseRef-PolyForm-Perimeter-1.0.1","_id":"@n-uf/hypr-tiling@26.9.2","maintainers":[{"name":"metelin","email":"metelin@gmail.com"}],"homepage":"https://hypr-tiling.n-uf.com/","bugs":{"url":"https://github.com/n-uf/hypr-tiling/issues"},"dist":{"shasum":"20b52e553cce6236901e8bd13e0020a558696901","tarball":"https://registry.npmjs.org/@n-uf/hypr-tiling/-/hypr-tiling-26.9.2.tgz","fileCount":22,"integrity":"sha512-90hwqebMrBjfbje6pDkxcB0BWf+9VX8Pf4cIACatVJI8bIzBrpJJhtB1v1KFNQ6cRHE7lDO01/W9v5ZgaoTF4Q==","signatures":[{"sig":"MEQCIQCryuZbc8HJKlhWKuxZb7nuxREwHvaYS6g6njDkgKDhnAIfcSTVSCOH4pu3D+UJs8Ry9pHV9B7kxvZaf1Oq1K1h+A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQD1pmP6M1GnMWIF7b+VK0SW13O8OdYalkqyWNdmfvB6CwIgYEhvV0VDvv4l+fKr06+5Z41EIYDYWulCFEyD4mL9les=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2440363},"main":"./dist/index.cjs","_from":"file:n-uf-hypr-tiling-26.9.2.tgz","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./engine":{"types":"./dist/engine.d.ts","import":"./dist/engine.mjs","require":"./dist/engine.cjs"},"./devtools":{"types":"./dist/devtools.d.ts","import":"./dist/devtools.mjs","require":"./dist/devtools.cjs"}},"private":false,"scripts":{"test":"jest","build":"tsup","check":"pnpm typecheck && pnpm test","release":"if [ \"$npm_config_nobump\" = \"true\" ]; then npm publish --access public; else node ./scripts/calendar-version-bump.mjs --apply && npm publish --access public; fi","api:docs":"node ./scripts/generate-api-docs.mjs","api:check":"api-extractor run --verbose -c api-extractor.index.json && api-extractor run --verbose -c api-extractor.devtools.json && api-extractor run --verbose -c api-extractor.engine.json","typecheck":"tsc --project tsconfig.json","api:update":"api-extractor run --local --verbose -c api-extractor.index.json && api-extractor run --local --verbose -c api-extractor.devtools.json && api-extractor run --local --verbose -c api-extractor.engine.json","check:guardrails":"node ./scripts/check-guardrails.mjs","release:next-version":"node ./scripts/calendar-version-bump.mjs --dry-run"},"_npmUser":{"name":"metelin","email":"metelin@gmail.com"},"_resolved":"/private/var/folders/tg/lzzv01z15z3ftkqbl3tsdvg00000gn/T/d9a832e90db77bfc2eee51c1d56275c0/n-uf-hypr-tiling-26.9.2.tgz","_integrity":"sha512-90hwqebMrBjfbje6pDkxcB0BWf+9VX8Pf4cIACatVJI8bIzBrpJJhtB1v1KFNQ6cRHE7lDO01/W9v5ZgaoTF4Q==","repository":{"url":"git+https://github.com/n-uf/hypr-tiling.git","type":"git"},"_npmVersion":"11.16.0","description":"Dynamic tiling for React: a recursive split-tree renderer for drag/drop, resizable, keyboard-controlled panes — inspired by Hyprland.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","dependencies":{"clsx":"^2.1.1","tailwind-merge":"^2.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.2.0","tsup":"^8.5.0","react":"^19.2.7","marked":"^18.0.5","ts-jest":"^29.4.5","react-dom":"^19.2.7","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^26.0.1","@types/react":"^19","@jest/globals":"^30.2.0","@types/react-dom":"^19","@testing-library/react":"^16.3.2","jest-environment-jsdom":"^30.4.1","@microsoft/api-extractor":"^7.58.9","@microsoft/api-documenter":"^7.30.7"},"peerDependencies":{"react":"^19","react-dom":"^19"},"_npmOperationalInternal":{"tmp":"tmp/hypr-tiling_26.9.2_1790052497361_0.18615290198535228","host":"s3://npm-registry-packages-npm-production"}},"26.9.3":{"name":"@n-uf/hypr-tiling","version":"26.9.3","keywords":["react","tiling","dynamic-tiling","split-layout","split-pane","pane-layout","react-layout","dock-layout","window-manager-ui","resizable-panes","drag-and-drop","tiling-window-manager","layout-engine","dashboard","hyprland"],"license":"LicenseRef-PolyForm-Perimeter-1.0.1","_id":"@n-uf/hypr-tiling@26.9.3","maintainers":[{"name":"metelin","email":"metelin@gmail.com"}],"homepage":"https://hypr-tiling.n-uf.com/","bugs":{"url":"https://github.com/n-uf/hypr-tiling/issues"},"dist":{"shasum":"69a8ddd6cf3a427ffc930bf82a66e1911eb8ac62","tarball":"https://registry.npmjs.org/@n-uf/hypr-tiling/-/hypr-tiling-26.9.3.tgz","fileCount":19,"integrity":"sha512-bOwu5ngSF03szK9JPGQtUYyQDeh80okuIAJIU0xIIBmawIGb7xwESn46frTQWTJkCHGp3yTR3QMiFSI/Hiks+A==","signatures":[{"sig":"MEQCIC4TWQwV4Yn+7bvWynNbKMJEmBEqQ0+ceeBdKRRonpfyAiBSL8Sq4MG5HqZkF/fofyQB5sBCcaMY9XV33qT5D5HKbA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIB/wT/z815wVaIIfvkpdU/DFDP51FcRBYQYNk9ABpGl5AiEAr/KpO6zVgI4R5prwBxIU2E5GJTIApG2J66hR6IfyU5U=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2550715},"main":"./dist/index.cjs","_from":"file:n-uf-hypr-tiling-26.9.3.tgz","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./engine":{"types":"./dist/engine.d.ts","import":"./dist/engine.mjs","require":"./dist/engine.cjs"},"./devtools":{"types":"./dist/devtools.d.ts","import":"./dist/devtools.mjs","require":"./dist/devtools.cjs"}},"private":false,"scripts":{"test":"jest","build":"rm -rf dist && tsup","check":"pnpm typecheck && pnpm test && pnpm build && pnpm test:dist","release":"if [ \"$npm_config_nobump\" = \"true\" ]; then npm publish --access public; else node ./scripts/calendar-version-bump.mjs --apply && npm publish --access public; fi","api:docs":"node ./scripts/generate-api-docs.mjs","api:check":"api-extractor run --verbose -c api-extractor.index.json && api-extractor run --verbose -c api-extractor.devtools.json && api-extractor run --verbose -c api-extractor.engine.json","test:dist":"jest --config jest.dist.config.js","typecheck":"tsc --project tsconfig.json","api:update":"api-extractor run --local --verbose -c api-extractor.index.json && api-extractor run --local --verbose -c api-extractor.devtools.json && api-extractor run --local --verbose -c api-extractor.engine.json","check:guardrails":"node ./scripts/check-guardrails.mjs","release:next-version":"node ./scripts/calendar-version-bump.mjs --dry-run"},"_npmUser":{"name":"metelin","email":"metelin@gmail.com"},"_resolved":"/private/var/folders/tg/lzzv01z15z3ftkqbl3tsdvg00000gn/T/f344d8af21619ab614195ffc11b8fc35/n-uf-hypr-tiling-26.9.3.tgz","_integrity":"sha512-bOwu5ngSF03szK9JPGQtUYyQDeh80okuIAJIU0xIIBmawIGb7xwESn46frTQWTJkCHGp3yTR3QMiFSI/Hiks+A==","repository":{"url":"git+https://github.com/n-uf/hypr-tiling.git","type":"git"},"_npmVersion":"11.16.0","description":"Dynamic tiling for React: a recursive split-tree renderer for drag/drop, resizable, keyboard-controlled panes — inspired by Hyprland.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","dependencies":{"clsx":"^2.1.1","tailwind-merge":"^2.6.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^30.2.0","tsup":"^8.5.0","react":"^19.2.7","marked":"^18.0.5","ts-jest":"^29.4.5","react-dom":"^19.2.7","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^26.0.1","@types/react":"^19","@jest/globals":"^30.2.0","@types/react-dom":"^19","@testing-library/react":"^16.3.2","jest-environment-jsdom":"^30.4.1","@microsoft/api-extractor":"^7.58.9","@microsoft/api-documenter":"^7.30.7"},"peerDependencies":{"react":"^19","react-dom":"^19"},"_npmOperationalInternal":{"tmp":"tmp/hypr-tiling_26.9.3_1790104438173_0.8196206701052595","host":"s3://npm-registry-packages-npm-production"}},"26.9.4":{"name":"@n-uf/hypr-tiling","version":"26.9.4","keywords":["react","tiling","dynamic-tiling","split-layout","split-pane","pane-layout","react-layout","dock-layout","window-manager-ui","resizable-panes","drag-and-drop","tiling-window-manager","layout-engine","dashboard","hyprland"],"license":"LicenseRef-PolyForm-Perimeter-1.0.1","_id":"@n-uf/hypr-tiling@26.9.4","maintainers":[{"name":"metelin","email":"metelin@gmail.com"}],"homepage":"https://hypr-tiling.n-uf.com/","bugs":{"url":"https://github.com/n-uf/hypr-tiling/issues"},"dist":{"shasum":"1b1a8ffdc233bf957a1816e5f7f5c0a2adda5f48","tarball":"https://registry.npmjs.org/@n-uf/hypr-tiling/-/hypr-tiling-26.9.4.tgz","fileCount":18,"integrity":"sha512-n9LYAREB33DWPOvzP5UzHpoARdB0DidhgdxRKpms5D1TzQah96bsfEZYQvaM9DlClxL150UROlaAzC7QMuD32Q==","signatures":[{"sig":"MEUCIG3EzuYexUkqbqYkPBAxbC2K0C1LQQOvUZpF16aZ6MsoAiEAo8+XgzThaoUdI2pb7D2uYH2BYgoC0fbK/3bAvBfNphI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDa7f5LXaQugJq+8fk6yVLFV6JxJ3g+gVToF+hXJrLB3gIhAMbiC5Pmc8o4P4PURYrlQEN961CUPPDMKKaiqDAHWYAq","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3194598},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./engine":{"types":"./dist/engine.d.ts","import":"./dist/engine.mjs","require":"./dist/engine.cjs"},"./devtools":{"types":"./dist/devtools.d.ts","import":"./dist/devtools.mjs","require":"./dist/devtools.cjs"}},"private":false,"scripts":{"test":"jest","build":"rm -rf dist && tsup","check":"pnpm typecheck && pnpm test && pnpm build && pnpm test:dist","release":"if [ \"$npm_config_nobump\" = \"true\" ]; then npm publish --access public; else node ./scripts/calendar-version-bump.mjs --apply && npm publish --access public; fi","api:docs":"node ./scripts/generate-api-docs.mjs","api:check":"api-extractor run --verbose -c api-extractor.index.json && api-extractor run --verbose -c api-extractor.devtools.json && api-extractor run --verbose -c api-extractor.engine.json","test:dist":"jest --config jest.dist.config.js","typecheck":"tsc --project tsconfig.json","api:update":"api-extractor run --local --verbose -c api-extractor.index.json && api-extractor run --local --verbose -c api-extractor.devtools.json && api-extractor run --local --verbose -c api-extractor.engine.json","prepublishOnly":"pnpm build && pnpm test:dist","check:guardrails":"node ./scripts/check-guardrails.mjs","release:next-version":"node ./scripts/calendar-version-bump.mjs --dry-run"},"_npmUser":{"name":"metelin","email":"metelin@gmail.com"},"repository":{"url":"git+https://github.com/n-uf/hypr-tiling.git","type":"git"},"_npmVersion":"11.16.0","description":"Dynamic tiling for React: a recursive split-tree renderer for drag/drop, resizable, keyboard-controlled panes — inspired by Hyprland.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","dependencies":{"clsx":"^2.1.1","tailwind-merge":"^2.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.2.0","tsup":"^8.5.0","react":"^19.2.7","marked":"^18.0.5","ts-jest":"^29.4.5","react-dom":"^19.2.7","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^26.0.1","@types/react":"^19","@jest/globals":"^30.2.0","@types/react-dom":"^19","@testing-library/react":"^16.3.2","jest-environment-jsdom":"^30.4.1","@microsoft/api-extractor":"^7.58.9","@microsoft/api-documenter":"^7.30.7"},"peerDependencies":{"react":"^19","react-dom":"^19"},"_npmOperationalInternal":{"tmp":"tmp/hypr-tiling_26.9.4_1790216086143_0.7980907824377759","host":"s3://npm-registry-packages-npm-production"}},"26.9.5":{"name":"@n-uf/hypr-tiling","version":"26.9.5","keywords":["react","tiling","dynamic-tiling","split-layout","split-pane","pane-layout","react-layout","dock-layout","window-manager-ui","resizable-panes","drag-and-drop","tiling-window-manager","layout-engine","dashboard","hyprland"],"license":"LicenseRef-PolyForm-Perimeter-1.0.1","_id":"@n-uf/hypr-tiling@26.9.5","maintainers":[{"name":"metelin","email":"metelin@gmail.com"}],"homepage":"https://hypr-tiling.n-uf.com/","bugs":{"url":"https://github.com/n-uf/hypr-tiling/issues"},"dist":{"shasum":"ee849a5b5a9e2e093dff2891dafecc6d4588980f","tarball":"https://registry.npmjs.org/@n-uf/hypr-tiling/-/hypr-tiling-26.9.5.tgz","fileCount":18,"integrity":"sha512-RxuUVegwBbqD+yfHlCE/alQuN4Vk1QLqu0wo2Hg9ifKzXbjGu8PM28mtps12EB/SnlmnqN0AkDIcKayuErZ/Qw==","signatures":[{"sig":"MEQCICBfWl5fPO25jTgoclAuj+Ywe+1PMPEgaBYyFvyNGlnPAiASq/rA6Cv9wsh2ufeu/vb8xdZV9ER407/Fsxnl34jq6Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCICSUKS4gHng7DFPDq6Ct94QLzhzkqqcpJAxQ7SFKvpJ2AiAhZ9AlH65xm8+tXmgvQ9Qy/id2sFQAwG3+F2masEoKCQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3217941},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./engine":{"types":"./dist/engine.d.ts","import":"./dist/engine.mjs","require":"./dist/engine.cjs"},"./devtools":{"types":"./dist/devtools.d.ts","import":"./dist/devtools.mjs","require":"./dist/devtools.cjs"}},"gitHead":"3f20249fd13bf977f035827612add61bfdd95f5c","private":false,"scripts":{"test":"jest","build":"rm -rf dist && tsup","check":"pnpm typecheck && pnpm test && pnpm build && pnpm test:dist","release":"if [ \"$npm_config_nobump\" = \"true\" ]; then npm publish --access public; else node ./scripts/calendar-version-bump.mjs --apply && npm publish --access public; fi","api:docs":"node ./scripts/generate-api-docs.mjs","api:check":"api-extractor run --verbose -c api-extractor.index.json && api-extractor run --verbose -c api-extractor.devtools.json && api-extractor run --verbose -c api-extractor.engine.json","test:dist":"jest --config jest.dist.config.js","typecheck":"tsc --project tsconfig.json","api:update":"api-extractor run --local --verbose -c api-extractor.index.json && api-extractor run --local --verbose -c api-extractor.devtools.json && api-extractor run --local --verbose -c api-extractor.engine.json","prepublishOnly":"pnpm build && pnpm test:dist","check:guardrails":"node ./scripts/check-guardrails.mjs","release:next-version":"node ./scripts/calendar-version-bump.mjs --dry-run"},"_npmUser":{"name":"metelin","email":"metelin@gmail.com"},"repository":{"url":"git+https://github.com/n-uf/hypr-tiling.git","type":"git"},"_npmVersion":"11.16.0","description":"Dynamic tiling for React: a recursive split-tree renderer for drag/drop, resizable, keyboard-controlled panes — inspired by Hyprland.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","dependencies":{"clsx":"^2.1.1","tailwind-merge":"^2.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.2.0","tsup":"^8.5.0","react":"^19.2.7","marked":"^18.0.5","ts-jest":"^29.4.5","react-dom":"^19.2.7","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^26.0.1","@types/react":"^19","@jest/globals":"^30.2.0","@types/react-dom":"^19","@testing-library/react":"^16.3.2","jest-environment-jsdom":"^30.4.1","@microsoft/api-extractor":"^7.58.9","@microsoft/api-documenter":"^7.30.7"},"peerDependencies":{"react":"^19","react-dom":"^19"},"_npmOperationalInternal":{"tmp":"tmp/hypr-tiling_26.9.5_1790218555289_0.4601067878606582","host":"s3://npm-registry-packages-npm-production"}},"26.9.6":{"name":"@n-uf/hypr-tiling","version":"26.9.6","keywords":["react","tiling","dynamic-tiling","split-layout","split-pane","pane-layout","react-layout","dock-layout","window-manager-ui","resizable-panes","drag-and-drop","tiling-window-manager","layout-engine","dashboard","hyprland"],"license":"LicenseRef-PolyForm-Perimeter-1.0.1","_id":"@n-uf/hypr-tiling@26.9.6","maintainers":[{"name":"metelin","email":"metelin@gmail.com"}],"homepage":"https://hypr-tiling.n-uf.com/","bugs":{"url":"https://github.com/n-uf/hypr-tiling/issues"},"dist":{"shasum":"d7b6b692e403895637195852c48bcc8a8d0a9cb8","tarball":"https://registry.npmjs.org/@n-uf/hypr-tiling/-/hypr-tiling-26.9.6.tgz","fileCount":18,"integrity":"sha512-aO34zjGCXqCxz+lXYhrzJWTZ0w9IY/MuC2p58MoO4wgzaJFAkgMo071AZiy8zIFJtNYyVMSD+PAb/KF5ajEzcg==","signatures":[{"sig":"MEUCIQCSTzehLzF2udmWfTB8TZGnCuL3Go10U+hq9O2pB8UyywIgB//NwLnR8RyoiIF7hpSP6jBRVIH3cRoEJOzUetfNTQs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQD9HJ+VS9U3pc8dmIc4K9TpoTz+5Y/BAM85rtCWoEP0VwIhAJBVBVYx94qz4fO/GGfAGLs1hTZz1OaPp4q3EMvDByA6","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3227779},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./engine":{"types":"./dist/engine.d.ts","import":"./dist/engine.mjs","require":"./dist/engine.cjs"},"./devtools":{"types":"./dist/devtools.d.ts","import":"./dist/devtools.mjs","require":"./dist/devtools.cjs"}},"gitHead":"82dfd29157736678d354a482ce93e0bca93508ff","private":false,"scripts":{"test":"jest","build":"rm -rf dist && tsup","check":"pnpm typecheck && pnpm test && pnpm build && pnpm test:dist","release":"if [ \"$npm_config_nobump\" = \"true\" ]; then npm publish --access public; else node ./scripts/calendar-version-bump.mjs --apply && npm publish --access public; fi","api:docs":"node ./scripts/generate-api-docs.mjs","api:check":"api-extractor run --verbose -c api-extractor.index.json && api-extractor run --verbose -c api-extractor.devtools.json && api-extractor run --verbose -c api-extractor.engine.json","test:dist":"jest --config jest.dist.config.js","typecheck":"tsc --project tsconfig.json","api:update":"api-extractor run --local --verbose -c api-extractor.index.json && api-extractor run --local --verbose -c api-extractor.devtools.json && api-extractor run --local --verbose -c api-extractor.engine.json","prepublishOnly":"pnpm build && pnpm test:dist","check:guardrails":"node ./scripts/check-guardrails.mjs","release:next-version":"node ./scripts/calendar-version-bump.mjs --dry-run"},"_npmUser":{"name":"metelin","email":"metelin@gmail.com"},"repository":{"url":"git+https://github.com/n-uf/hypr-tiling.git","type":"git"},"_npmVersion":"11.16.0","description":"Dynamic tiling for React: a recursive split-tree renderer for drag/drop, resizable, keyboard-controlled panes — inspired by Hyprland.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","dependencies":{"clsx":"^2.1.1","tailwind-merge":"^2.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.2.0","tsup":"^8.5.0","react":"^19.2.7","marked":"^18.0.5","ts-jest":"^29.4.5","react-dom":"^19.2.7","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^26.0.1","@types/react":"^19","@jest/globals":"^30.2.0","@types/react-dom":"^19","@testing-library/react":"^16.3.2","jest-environment-jsdom":"^30.4.1","@microsoft/api-extractor":"^7.58.9","@microsoft/api-documenter":"^7.30.7"},"peerDependencies":{"react":"^19","react-dom":"^19"},"_npmOperationalInternal":{"tmp":"tmp/hypr-tiling_26.9.6_1790272486551_0.722562897422399","host":"s3://npm-registry-packages-npm-production"}},"26.9.7":{"name":"@n-uf/hypr-tiling","version":"26.9.7","keywords":["react","tiling","dynamic-tiling","split-layout","split-pane","pane-layout","react-layout","dock-layout","window-manager-ui","resizable-panes","drag-and-drop","tiling-window-manager","layout-engine","dashboard","hyprland"],"license":"LicenseRef-PolyForm-Perimeter-1.0.1","_id":"@n-uf/hypr-tiling@26.9.7","maintainers":[{"name":"metelin","email":"metelin@gmail.com"}],"homepage":"https://hypr-tiling.n-uf.com/","bugs":{"url":"https://github.com/n-uf/hypr-tiling/issues"},"dist":{"shasum":"8c42899871ccd82f680120fc7e51ac7a0d7c30f7","tarball":"https://registry.npmjs.org/@n-uf/hypr-tiling/-/hypr-tiling-26.9.7.tgz","fileCount":18,"integrity":"sha512-Chju1wQZcJwH3aXJSLdU4+iixzqkErA+qUiL8uzG9fcVTv4N3eFINLLmg9P+SIazZz9RPdja//GJ/yQ96SM3ww==","signatures":[{"sig":"MEQCIHk9MfzCiKJ3nixeGFbNdFI3p9WM5uqqJVcbvo5oQJPVAiBeEY7uqkNu73vr3FeU8raaIFt2YeQB63p6VqftaRnizw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQD6Tmau2+IYNLflXsDdpSUeHrmMhvZRtoa+QYUt3Y/sugIhALY7pIjxkm5C/wggLHBPA/7OseMfSQLDkUiFnkYcN/na","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3262590},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./engine":{"types":"./dist/engine.d.ts","import":"./dist/engine.mjs","require":"./dist/engine.cjs"},"./devtools":{"types":"./dist/devtools.d.ts","import":"./dist/devtools.mjs","require":"./dist/devtools.cjs"}},"gitHead":"79fa851b125bd4bae9e424931ca282b632837f1b","private":false,"scripts":{"test":"jest","build":"rm -rf dist && tsup","check":"pnpm typecheck && pnpm test && pnpm build && pnpm test:dist","release":"if [ \"$npm_config_nobump\" = \"true\" ]; then npm publish --access public; else node ./scripts/calendar-version-bump.mjs --apply && npm publish --access public; fi","api:docs":"node ./scripts/generate-api-docs.mjs","api:check":"api-extractor run --verbose -c api-extractor.index.json && api-extractor run --verbose -c api-extractor.devtools.json && api-extractor run --verbose -c api-extractor.engine.json","test:dist":"jest --config jest.dist.config.js","typecheck":"tsc --project tsconfig.json","api:update":"api-extractor run --local --verbose -c api-extractor.index.json && api-extractor run --local --verbose -c api-extractor.devtools.json && api-extractor run --local --verbose -c api-extractor.engine.json","prepublishOnly":"pnpm build && pnpm test:dist","check:guardrails":"node ./scripts/check-guardrails.mjs","release:next-version":"node ./scripts/calendar-version-bump.mjs --dry-run"},"_npmUser":{"name":"metelin","email":"metelin@gmail.com"},"repository":{"url":"git+https://github.com/n-uf/hypr-tiling.git","type":"git"},"_npmVersion":"11.16.0","description":"Dynamic tiling for React: a recursive split-tree renderer for drag/drop, resizable, keyboard-controlled panes — inspired by Hyprland.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","dependencies":{"clsx":"^2.1.1","tailwind-merge":"^2.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.2.0","tsup":"^8.5.0","react":"^19.2.7","marked":"^18.0.5","ts-jest":"^29.4.5","react-dom":"^19.2.7","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^26.0.1","@types/react":"^19","@jest/globals":"^30.2.0","@types/react-dom":"^19","@testing-library/react":"^16.3.2","jest-environment-jsdom":"^30.4.1","@microsoft/api-extractor":"^7.58.9","@microsoft/api-documenter":"^7.30.7"},"peerDependencies":{"react":"^19","react-dom":"^19"},"_npmOperationalInternal":{"tmp":"tmp/hypr-tiling_26.9.7_1790278568434_0.5874686535682421","host":"s3://npm-registry-packages-npm-production"}},"26.9.8":{"name":"@n-uf/hypr-tiling","version":"26.9.8","keywords":["react","tiling","dynamic-tiling","split-layout","split-pane","pane-layout","react-layout","dock-layout","window-manager-ui","resizable-panes","drag-and-drop","tiling-window-manager","layout-engine","dashboard","hyprland"],"license":"LicenseRef-PolyForm-Perimeter-1.0.1","_id":"@n-uf/hypr-tiling@26.9.8","maintainers":[{"name":"metelin","email":"metelin@gmail.com"}],"homepage":"https://hypr-tiling.n-uf.com/","bugs":{"url":"https://github.com/n-uf/hypr-tiling/issues"},"dist":{"shasum":"411f9196475ae65ccf1f2ef11416206e581f041d","tarball":"https://registry.npmjs.org/@n-uf/hypr-tiling/-/hypr-tiling-26.9.8.tgz","fileCount":18,"integrity":"sha512-gkpjFHCRdZ3dix1doOhU9nrEXTViXSmFhH4x+7SV6XPYO7dj8RX57hMfxs4V1/h7oFXv6NO4dCOD4VdXvvdhhg==","signatures":[{"sig":"MEUCIC1XX9P50QQuCAdwsnYWKqlRfliZiwtFfOU4EalXn9ulAiEAlriFDJeWuVmit/nKo1UZsMV6xA80Pmmujcd5mP48wcU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQCTWdPlADqF0Yspuw37CoFmfn1aRmCn4B63pNyA/UyfdgIhAJWYgZ+4QbC5ptEZ0QjoSDT9Dcee7phhmtgAZv3VJkh0","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3285080},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./engine":{"types":"./dist/engine.d.ts","import":"./dist/engine.mjs","require":"./dist/engine.cjs"},"./devtools":{"types":"./dist/devtools.d.ts","import":"./dist/devtools.mjs","require":"./dist/devtools.cjs"}},"gitHead":"2b9e796ab4fa67f580c8f42f12ff103fc0734197","private":false,"scripts":{"test":"jest","build":"rm -rf dist && tsup","check":"pnpm typecheck && pnpm test && pnpm build && pnpm test:dist","release":"if [ \"$npm_config_nobump\" = \"true\" ]; then npm publish --access public; else node ./scripts/calendar-version-bump.mjs --apply && npm publish --access public; fi","api:docs":"node ./scripts/generate-api-docs.mjs","api:check":"api-extractor run --verbose -c api-extractor.index.json && api-extractor run --verbose -c api-extractor.devtools.json && api-extractor run --verbose -c api-extractor.engine.json","test:dist":"jest --config jest.dist.config.js","typecheck":"tsc --project tsconfig.json","api:update":"api-extractor run --local --verbose -c api-extractor.index.json && api-extractor run --local --verbose -c api-extractor.devtools.json && api-extractor run --local --verbose -c api-extractor.engine.json","prepublishOnly":"pnpm build && pnpm test:dist","check:guardrails":"node ./scripts/check-guardrails.mjs","release:next-version":"node ./scripts/calendar-version-bump.mjs --dry-run"},"_npmUser":{"name":"metelin","email":"metelin@gmail.com"},"repository":{"url":"git+https://github.com/n-uf/hypr-tiling.git","type":"git"},"_npmVersion":"11.16.0","description":"Dynamic tiling for React: a recursive split-tree renderer for drag/drop, resizable, keyboard-controlled panes — inspired by Hyprland.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","dependencies":{"clsx":"^2.1.1","tailwind-merge":"^2.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.2.0","tsup":"^8.5.0","react":"^19.2.7","marked":"^18.0.5","ts-jest":"^29.4.5","react-dom":"^19.2.7","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^26.0.1","@types/react":"^19","@jest/globals":"^30.2.0","@types/react-dom":"^19","@testing-library/react":"^16.3.2","jest-environment-jsdom":"^30.4.1","@microsoft/api-extractor":"^7.58.9","@microsoft/api-documenter":"^7.30.7"},"peerDependencies":{"react":"^19","react-dom":"^19"},"_npmOperationalInternal":{"tmp":"tmp/hypr-tiling_26.9.8_1790284734686_0.714693889231069","host":"s3://npm-registry-packages-npm-production"}},"26.9.9":{"name":"@n-uf/hypr-tiling","version":"26.9.9","keywords":["react","tiling","dynamic-tiling","split-layout","split-pane","pane-layout","react-layout","dock-layout","window-manager-ui","resizable-panes","drag-and-drop","tiling-window-manager","layout-engine","dashboard","hyprland"],"license":"LicenseRef-PolyForm-Perimeter-1.0.1","_id":"@n-uf/hypr-tiling@26.9.9","maintainers":[{"name":"metelin","email":"metelin@gmail.com"}],"homepage":"https://hypr-tiling.n-uf.com/","bugs":{"url":"https://github.com/n-uf/hypr-tiling/issues"},"dist":{"shasum":"9567e4c712e73880e226166be838fac6f23e2c14","tarball":"https://registry.npmjs.org/@n-uf/hypr-tiling/-/hypr-tiling-26.9.9.tgz","fileCount":18,"integrity":"sha512-bLLhJ7hQORguwxSobYA9aaGNqBFthkp7EjGmCWcLRrzL0TqAYbxjHfDCxIXcf+pU61Lif3MWsI2saDH3D8sphw==","signatures":[{"sig":"MEUCIEOZ0sraA0GXH0+r4lagsEf9zR8W9Wkpav8z5/02sirRAiEA/FDHrrPL1ccWAZcYFSuGIsvL4zsP9Jqi6X+xI0AlqbM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIHljjTa61x2BcOLkdBrAIpUt8/iY+41+w5zU9K2fHV4EAiBATTvp/YJfrCx4MiK00wVvwMQkiNe9cVFUP2HMT6n1vQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3338215},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./engine":{"types":"./dist/engine.d.ts","import":"./dist/engine.mjs","require":"./dist/engine.cjs"},"./devtools":{"types":"./dist/devtools.d.ts","import":"./dist/devtools.mjs","require":"./dist/devtools.cjs"}},"gitHead":"0aded461564074b82bec8cd7f16a14c7600ee9d1","private":false,"scripts":{"test":"jest","build":"rm -rf dist && tsup","check":"pnpm typecheck && pnpm test && pnpm build && pnpm test:dist","release":"if [ \"$npm_config_nobump\" = \"true\" ]; then npm publish --access public; else node ./scripts/calendar-version-bump.mjs --apply && npm publish --access public; fi","api:docs":"node ./scripts/generate-api-docs.mjs","api:check":"api-extractor run --verbose -c api-extractor.index.json && api-extractor run --verbose -c api-extractor.devtools.json && api-extractor run --verbose -c api-extractor.engine.json","test:dist":"jest --config jest.dist.config.js","typecheck":"tsc --project tsconfig.json","api:update":"api-extractor run --local --verbose -c api-extractor.index.json && api-extractor run --local --verbose -c api-extractor.devtools.json && api-extractor run --local --verbose -c api-extractor.engine.json","prepublishOnly":"pnpm build && pnpm test:dist","check:guardrails":"node ./scripts/check-guardrails.mjs","release:next-version":"node ./scripts/calendar-version-bump.mjs --dry-run"},"_npmUser":{"name":"metelin","email":"metelin@gmail.com"},"repository":{"url":"git+https://github.com/n-uf/hypr-tiling.git","type":"git"},"_npmVersion":"11.16.0","description":"Dynamic tiling for React: a recursive split-tree renderer for drag/drop, resizable, keyboard-controlled panes — inspired by Hyprland.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","dependencies":{"clsx":"^2.1.1","tailwind-merge":"^2.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.2.0","tsup":"^8.5.0","react":"^19.2.7","marked":"^18.0.5","ts-jest":"^29.4.5","react-dom":"^19.2.7","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^26.0.1","@types/react":"^19","@jest/globals":"^30.2.0","@types/react-dom":"^19","@testing-library/react":"^16.3.2","jest-environment-jsdom":"^30.4.1","@microsoft/api-extractor":"^7.58.9","@microsoft/api-documenter":"^7.30.7"},"peerDependencies":{"react":"^19","react-dom":"^19"},"_npmOperationalInternal":{"tmp":"tmp/hypr-tiling_26.9.9_1790289628543_0.11981600429605144","host":"s3://npm-registry-packages-npm-production"}},"26.11.0":{"name":"@n-uf/hypr-tiling","version":"26.11.0","keywords":["react","tiling","dynamic-tiling","split-layout","split-pane","pane-layout","react-layout","dock-layout","window-manager-ui","resizable-panes","drag-and-drop","tiling-window-manager","layout-engine","dashboard","hyprland"],"license":"LicenseRef-PolyForm-Perimeter-1.0.1","_id":"@n-uf/hypr-tiling@26.11.0","maintainers":[{"name":"metelin","email":"metelin@gmail.com"}],"homepage":"https://hypr-tiling.n-uf.com/","bugs":{"url":"https://github.com/n-uf/hypr-tiling/issues"},"dist":{"shasum":"43e2cc7e8b3b668126d6579484b4051c18328aa4","tarball":"https://registry.npmjs.org/@n-uf/hypr-tiling/-/hypr-tiling-26.11.0.tgz","fileCount":19,"integrity":"sha512-+O6CzVYXBfFE9IcIeA3Ro5fVg9QyfSIiTP97O121RiC6xY6c6It/qwajiWMnwxiizu7Z8wHLNa1bcV7egCWndA==","signatures":[{"sig":"MEQCIAmDPmer25fThKO0G7XcYLOis0J0icqPzBTFTR/FNK4+AiB5Y1KCc5usjk6TcmTlyQSLBcBgw1fDMopyc71udPXrUA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIFxjzIhRT7iLQEPp4QgnmOWidm+M4gDp5zrha0YOgbzUAiBMn325Ub9+arDnEsA7/EG/m5AlA6Xeor9NAwYyKzOQSw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@n-uf%2fhypr-tiling@26.11.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":3398341},"main":"./dist/index.cjs","_from":"file:/home/runner/work/_temp/package/n-uf-hypr-tiling-26.11.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./engine":{"types":"./dist/engine.d.ts","import":"./dist/engine.mjs","require":"./dist/engine.cjs"},"./devtools":{"types":"./dist/devtools.d.ts","import":"./dist/devtools.mjs","require":"./dist/devtools.cjs"}},"private":false,"scripts":{"test":"jest","build":"rm -rf dist && tsup","check":"pnpm typecheck && pnpm test && pnpm build && pnpm test:dist","api:docs":"node ./scripts/generate-api-docs.mjs","api:check":"api-extractor run --verbose -c api-extractor.index.json && api-extractor run --verbose -c api-extractor.devtools.json && api-extractor run --verbose -c api-extractor.engine.json","test:dist":"jest --config jest.dist.config.js","typecheck":"tsc --project tsconfig.json","api:update":"api-extractor run --local --verbose -c api-extractor.index.json && api-extractor run --local --verbose -c api-extractor.devtools.json && api-extractor run --local --verbose -c api-extractor.engine.json","check:guardrails":"node ./scripts/check-guardrails.mjs","release:next-version":"node ./scripts/calendar-version-bump.mjs --dry-run"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"2a5e1a18-41c3-4cdf-b471-b9c4226b808c"}},"_resolved":"/home/runner/work/_temp/package/n-uf-hypr-tiling-26.11.0.tgz","_integrity":"sha512-+O6CzVYXBfFE9IcIeA3Ro5fVg9QyfSIiTP97O121RiC6xY6c6It/qwajiWMnwxiizu7Z8wHLNa1bcV7egCWndA==","repository":{"url":"git+https://github.com/n-uf/hypr-tiling.git","type":"git"},"_npmVersion":"11.20.0","description":"Dynamic tiling for React: a recursive split-tree renderer for drag/drop, resizable, keyboard-controlled panes — inspired by Hyprland.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.4","dependencies":{"clsx":"^2.1.1","tailwind-merge":"^2.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.2.0","tsup":"^8.5.0","react":"^19.2.7","marked":"^18.0.5","ts-jest":"^29.4.5","react-dom":"^19.2.7","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^26.0.1","@types/react":"^19","@jest/globals":"^30.2.0","@types/react-dom":"^19","@testing-library/react":"^16.3.2","jest-environment-jsdom":"^30.4.1","@microsoft/api-extractor":"^7.58.9","@microsoft/api-documenter":"^7.30.7"},"peerDependencies":{"react":"^19","react-dom":"^19"},"_npmOperationalInternal":{"tmp":"tmp/hypr-tiling_26.11.0_1794121895672_0.709699584506249","host":"s3://npm-registry-packages-npm-production"}},"26.11.1":{"name":"@n-uf/hypr-tiling","version":"26.11.1","keywords":["react","tiling","dynamic-tiling","split-layout","split-pane","pane-layout","react-layout","dock-layout","window-manager-ui","resizable-panes","drag-and-drop","tiling-window-manager","layout-engine","dashboard","hyprland"],"license":"LicenseRef-PolyForm-Perimeter-1.0.1","_id":"@n-uf/hypr-tiling@26.11.1","maintainers":[{"name":"metelin","email":"metelin@gmail.com"}],"homepage":"https://hypr-tiling.n-uf.com/","bugs":{"url":"https://github.com/n-uf/hypr-tiling/issues"},"dist":{"shasum":"672f32841f7678d6eee7bb7c619b8656ba0a8509","tarball":"https://registry.npmjs.org/@n-uf/hypr-tiling/-/hypr-tiling-26.11.1.tgz","fileCount":19,"integrity":"sha512-U/jaSX4J7ToGaiCLOg9qQ6+hnWjx+TSD4i9manU58Zj29FXSFkW8MwheUGc5n78DbXvUUQUT5eUN5cRcNuooEw==","signatures":[{"sig":"MEYCIQC1aNnrpAC3z6dv8IFdw8DmTL48al0qQp2V3xd8QiT3xgIhAP24Pl8WDHFyYXzBghr/UQbm8PBAgjrx/IXaDzrkO51+","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDpaCmdkJGdsHobhrLpKmVGu4WchuSJo3R3cWiU3lohjQIgUSYJO7OSsmuo2NoE9MkO2ZQtixoyKtbPT4K4R44bs2Y=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@n-uf%2fhypr-tiling@26.11.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":3412371},"main":"./dist/index.cjs","_from":"file:/home/runner/work/_temp/package/n-uf-hypr-tiling-26.11.1.tgz","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./engine":{"types":"./dist/engine.d.ts","import":"./dist/engine.mjs","require":"./dist/engine.cjs"},"./devtools":{"types":"./dist/devtools.d.ts","import":"./dist/devtools.mjs","require":"./dist/devtools.cjs"}},"private":false,"scripts":{"test":"jest","build":"rm -rf dist && tsup","check":"pnpm typecheck && pnpm test && pnpm build && pnpm test:dist","api:docs":"node ./scripts/generate-api-docs.mjs","api:check":"api-extractor run --verbose -c api-extractor.index.json && api-extractor run --verbose -c api-extractor.devtools.json && api-extractor run --verbose -c api-extractor.engine.json","test:dist":"jest --config jest.dist.config.js","typecheck":"tsc --project tsconfig.json","api:update":"api-extractor run --local --verbose -c api-extractor.index.json && api-extractor run --local --verbose -c api-extractor.devtools.json && api-extractor run --local --verbose -c api-extractor.engine.json","check:guardrails":"node ./scripts/check-guardrails.mjs","release:next-version":"node ./scripts/calendar-version-bump.mjs --dry-run"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"2a5e1a18-41c3-4cdf-b471-b9c4226b808c"}},"_resolved":"/home/runner/work/_temp/package/n-uf-hypr-tiling-26.11.1.tgz","_integrity":"sha512-U/jaSX4J7ToGaiCLOg9qQ6+hnWjx+TSD4i9manU58Zj29FXSFkW8MwheUGc5n78DbXvUUQUT5eUN5cRcNuooEw==","repository":{"url":"git+https://github.com/n-uf/hypr-tiling.git","type":"git"},"_npmVersion":"11.20.0","description":"Dynamic tiling for React: a recursive split-tree renderer for drag/drop, resizable, keyboard-controlled panes — inspired by Hyprland.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.4","dependencies":{"clsx":"^2.1.1","tailwind-merge":"^2.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.2.0","tsup":"^8.5.0","react":"^19.2.7","marked":"^18.0.5","ts-jest":"^29.4.5","react-dom":"^19.2.7","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^26.0.1","@types/react":"^19","@jest/globals":"^30.2.0","@types/react-dom":"^19","@testing-library/react":"^16.3.2","jest-environment-jsdom":"^30.4.1","@microsoft/api-extractor":"^7.58.9","@microsoft/api-documenter":"^7.30.7"},"peerDependencies":{"react":"^19","react-dom":"^19"},"_npmOperationalInternal":{"tmp":"tmp/hypr-tiling_26.11.1_1794294928586_0.02141018820139695","host":"s3://npm-registry-packages-npm-production"}},"26.11.2":{"name":"@n-uf/hypr-tiling","version":"26.11.2","keywords":["react","tiling","dynamic-tiling","split-layout","split-pane","pane-layout","react-layout","dock-layout","window-manager-ui","resizable-panes","drag-and-drop","tiling-window-manager","layout-engine","dashboard","hyprland"],"license":"LicenseRef-PolyForm-Perimeter-1.0.1","_id":"@n-uf/hypr-tiling@26.11.2","maintainers":[{"name":"metelin","email":"metelin@gmail.com"}],"homepage":"https://hypr-tiling.n-uf.com/","bugs":{"url":"https://github.com/n-uf/hypr-tiling/issues"},"dist":{"shasum":"f8ac9d6c295f25e4dabecc47a8d0570aba069528","tarball":"https://registry.npmjs.org/@n-uf/hypr-tiling/-/hypr-tiling-26.11.2.tgz","fileCount":19,"integrity":"sha512-kca7yeYyOLsiqdPGTXo2Pa7yBsT8MS0/8WxnFJ7jU/fQBmD8Yz38FKdv276lLG75pT6I9pE4h+nqb/MS+NZhFg==","signatures":[{"sig":"MEYCIQDSSnfchUFD5UUeIQD03EWdX0r0LqmQQAt8/kB9EH3mVAIhAPD4XX80v2qOlZTQswRIIpMxmqQm4iqiR+XRhvJjnXI9","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIB3uSr/C4XyjMFwjPv5jke/ZL+nFY/XWRAGmlaRhRZXHAiAmjxFz1uUHOlPBzCBZn0LfLsle2MyJk7L/2XpWGuTnDQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@n-uf%2fhypr-tiling@26.11.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":3413180},"main":"./dist/index.cjs","_from":"file:/home/runner/work/_temp/package/n-uf-hypr-tiling-26.11.2.tgz","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./engine":{"types":"./dist/engine.d.ts","import":"./dist/engine.mjs","require":"./dist/engine.cjs"},"./devtools":{"types":"./dist/devtools.d.ts","import":"./dist/devtools.mjs","require":"./dist/devtools.cjs"}},"private":false,"scripts":{"test":"jest","build":"rm -rf dist && tsup","check":"pnpm typecheck && pnpm test && pnpm build && pnpm test:dist","api:docs":"node ./scripts/generate-api-docs.mjs","api:check":"api-extractor run --verbose -c api-extractor.index.json && api-extractor run --verbose -c api-extractor.devtools.json && api-extractor run --verbose -c api-extractor.engine.json","test:dist":"jest --config jest.dist.config.js","typecheck":"tsc --project tsconfig.json","api:update":"api-extractor run --local --verbose -c api-extractor.index.json && api-extractor run --local --verbose -c api-extractor.devtools.json && api-extractor run --local --verbose -c api-extractor.engine.json","check:guardrails":"node ./scripts/check-guardrails.mjs","release:next-version":"node ./scripts/calendar-version-bump.mjs --dry-run"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"2a5e1a18-41c3-4cdf-b471-b9c4226b808c"}},"_resolved":"/home/runner/work/_temp/package/n-uf-hypr-tiling-26.11.2.tgz","_integrity":"sha512-kca7yeYyOLsiqdPGTXo2Pa7yBsT8MS0/8WxnFJ7jU/fQBmD8Yz38FKdv276lLG75pT6I9pE4h+nqb/MS+NZhFg==","repository":{"url":"git+https://github.com/n-uf/hypr-tiling.git","type":"git"},"_npmVersion":"11.20.0","description":"Dynamic tiling for React: a recursive split-tree renderer for drag/drop, resizable, keyboard-controlled panes — inspired by Hyprland.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.4","dependencies":{"clsx":"^2.1.1","tailwind-merge":"^2.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.2.0","tsup":"^8.5.0","react":"^19.2.7","marked":"^18.0.5","ts-jest":"^29.4.5","react-dom":"^19.2.7","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^26.0.1","@types/react":"^19","@jest/globals":"^30.2.0","@types/react-dom":"^19","@testing-library/react":"^16.3.2","jest-environment-jsdom":"^30.4.1","@microsoft/api-extractor":"^7.58.9","@microsoft/api-documenter":"^7.30.7"},"peerDependencies":{"react":"^19","react-dom":"^19"},"peerDependenciesMeta":{"react":{"optional":true},"react-dom":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/hypr-tiling_26.11.2_1794295351409_0.8117635758167455","host":"s3://npm-registry-packages-npm-production"}},"26.11.3":{"name":"@n-uf/hypr-tiling","version":"26.11.3","keywords":["react","tiling","dynamic-tiling","split-layout","split-pane","pane-layout","react-layout","dock-layout","window-manager-ui","resizable-panes","drag-and-drop","tiling-window-manager","layout-engine","dashboard","hyprland"],"license":"LicenseRef-PolyForm-Perimeter-1.0.1","_id":"@n-uf/hypr-tiling@26.11.3","maintainers":[{"name":"metelin","email":"metelin@gmail.com"}],"homepage":"https://hypr-tiling.n-uf.com/","bugs":{"url":"https://github.com/n-uf/hypr-tiling/issues"},"dist":{"shasum":"e660fdc0386174f74b730e693f7866f71d8bc2e4","tarball":"https://registry.npmjs.org/@n-uf/hypr-tiling/-/hypr-tiling-26.11.3.tgz","fileCount":19,"integrity":"sha512-McQPfpy4egETklr4a3/v8n05G63Iic8/qITEXfXbDHynnFcT0SGurW8+PLPwEpfXdVTtSWY9TOakbgSwe7KCUQ==","signatures":[{"sig":"MEUCIFzxIUblkMK3Rm2DTpfN9cwwZPoSc/7kQuebzZNwuRnfAiEArqEaDDLukmN8fBGAjPBbiKitfV3DolDWUG2thpgX2F4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIGsebQUSpddQKCIzBS6pi1t85Svf6gQ5E7hvfiNsi6PvAiArv5OCz3AwwTTBtHVOkwqbHEQgSksCrB0a9/Nxg9rHEw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@n-uf%2fhypr-tiling@26.11.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":3430613},"main":"./dist/index.cjs","_from":"file:/home/runner/work/_temp/package/n-uf-hypr-tiling-26.11.3.tgz","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./engine":{"types":"./dist/engine.d.ts","import":"./dist/engine.mjs","require":"./dist/engine.cjs"},"./devtools":{"types":"./dist/devtools.d.ts","import":"./dist/devtools.mjs","require":"./dist/devtools.cjs"}},"private":false,"scripts":{"test":"jest","build":"rm -rf dist && tsup","check":"pnpm typecheck && pnpm test && pnpm build && pnpm test:dist","api:docs":"node ./scripts/generate-api-docs.mjs","api:check":"api-extractor run --verbose -c api-extractor.index.json && api-extractor run --verbose -c api-extractor.devtools.json && api-extractor run --verbose -c api-extractor.engine.json","test:dist":"jest --config jest.dist.config.js","typecheck":"tsc --project tsconfig.json","api:update":"api-extractor run --local --verbose -c api-extractor.index.json && api-extractor run --local --verbose -c api-extractor.devtools.json && api-extractor run --local --verbose -c api-extractor.engine.json","check:guardrails":"node ./scripts/check-guardrails.mjs","release:next-version":"node ./scripts/calendar-version-bump.mjs --dry-run"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"2a5e1a18-41c3-4cdf-b471-b9c4226b808c"}},"_resolved":"/home/runner/work/_temp/package/n-uf-hypr-tiling-26.11.3.tgz","_integrity":"sha512-McQPfpy4egETklr4a3/v8n05G63Iic8/qITEXfXbDHynnFcT0SGurW8+PLPwEpfXdVTtSWY9TOakbgSwe7KCUQ==","repository":{"url":"git+https://github.com/n-uf/hypr-tiling.git","type":"git"},"_npmVersion":"11.20.0","description":"Dynamic tiling for React: a recursive split-tree renderer for drag/drop, resizable, keyboard-controlled panes — inspired by Hyprland.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.4","dependencies":{"clsx":"^2.1.1","@n-uf/motion":"26.11.3","tailwind-merge":"^2.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.2.0","tsup":"^8.5.0","react":"^19.2.7","marked":"^18.0.5","ts-jest":"^29.4.5","react-dom":"^19.2.7","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^26.0.1","@types/react":"^19","@jest/globals":"^30.2.0","@types/react-dom":"^19","@testing-library/react":"^16.3.2","jest-environment-jsdom":"^30.4.1","@microsoft/api-extractor":"^7.58.9","@microsoft/api-documenter":"^7.30.7"},"peerDependencies":{"react":"^19","react-dom":"^19"},"peerDependenciesMeta":{"react":{"optional":true},"react-dom":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/hypr-tiling_26.11.3_1794370147762_0.9914575861646048","host":"s3://npm-registry-packages-npm-production"}},"26.11.4":{"name":"@n-uf/hypr-tiling","version":"26.11.4","keywords":["react","tiling","dynamic-tiling","split-layout","split-pane","pane-layout","react-layout","dock-layout","window-manager-ui","resizable-panes","drag-and-drop","tiling-window-manager","layout-engine","dashboard","hyprland"],"license":"LicenseRef-PolyForm-Perimeter-1.0.1","_id":"@n-uf/hypr-tiling@26.11.4","maintainers":[{"name":"metelin","email":"metelin@gmail.com"}],"homepage":"https://hypr-tiling.n-uf.com/","bugs":{"url":"https://github.com/n-uf/hypr-tiling/issues"},"dist":{"shasum":"dc71b000a03df0f78628a8f04df01bbbb270f83a","tarball":"https://registry.npmjs.org/@n-uf/hypr-tiling/-/hypr-tiling-26.11.4.tgz","fileCount":19,"integrity":"sha512-KrIKBYL8fCGJFkKU9x+YlC1JgUHOD7ZeXhW3G3M9lAZjseMIl/12RdpOTgJStyPLSp4twKKatbffP0FUYQ2zyg==","signatures":[{"sig":"MEUCIQD3F5xNrxT0fThnSjFINr4Y/lWVho2UE7qoJhNI88wWRwIgDiYuUWp2DQ2CLfQlYUinwe+FWQKEMwpjfpIw8f93GLg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIA6LJgkBfhH87CEPwlHMvDOcw8IUsTScCG7XE2D+mU5rAiB+4/HP96DzBAqOgWoQ/pq3Eag2GjNnp5IkZemUivpliw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@n-uf%2fhypr-tiling@26.11.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":3398820},"main":"./dist/index.cjs","_from":"file:/home/runner/work/_temp/package/n-uf-hypr-tiling-26.11.4.tgz","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./engine":{"types":"./dist/engine.d.ts","import":"./dist/engine.mjs","require":"./dist/engine.cjs"},"./devtools":{"types":"./dist/devtools.d.ts","import":"./dist/devtools.mjs","require":"./dist/devtools.cjs"}},"private":false,"scripts":{"test":"jest","build":"rm -rf dist && tsup","check":"pnpm typecheck && pnpm test && pnpm build && pnpm test:dist","api:docs":"node ./scripts/generate-api-docs.mjs","api:check":"api-extractor run --verbose -c api-extractor.index.json && api-extractor run --verbose -c api-extractor.devtools.json && api-extractor run --verbose -c api-extractor.engine.json","test:dist":"jest --config jest.dist.config.js","typecheck":"tsc --project tsconfig.json","api:update":"api-extractor run --local --verbose -c api-extractor.index.json && api-extractor run --local --verbose -c api-extractor.devtools.json && api-extractor run --local --verbose -c api-extractor.engine.json","check:guardrails":"node ./scripts/check-guardrails.mjs","release:next-version":"node ./scripts/calendar-version-bump.mjs --dry-run"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"2a5e1a18-41c3-4cdf-b471-b9c4226b808c"}},"_resolved":"/home/runner/work/_temp/package/n-uf-hypr-tiling-26.11.4.tgz","_integrity":"sha512-KrIKBYL8fCGJFkKU9x+YlC1JgUHOD7ZeXhW3G3M9lAZjseMIl/12RdpOTgJStyPLSp4twKKatbffP0FUYQ2zyg==","repository":{"url":"git+https://github.com/n-uf/hypr-tiling.git","type":"git"},"_npmVersion":"11.20.0","description":"Dynamic tiling for React: a recursive split-tree renderer for drag/drop, resizable, keyboard-controlled panes — inspired by Hyprland.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.4","dependencies":{"clsx":"^2.1.1","@n-uf/motion":"26.11.3","tailwind-merge":"^2.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.2.0","tsup":"^8.5.0","react":"^19.2.7","marked":"^18.0.5","ts-jest":"^29.4.5","react-dom":"^19.2.7","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^26.0.1","@types/react":"^19","@jest/globals":"^30.2.0","@types/react-dom":"^19","@testing-library/react":"^16.3.2","jest-environment-jsdom":"^30.4.1","@microsoft/api-extractor":"^7.58.9","@microsoft/api-documenter":"^7.30.7"},"peerDependencies":{"react":"^19","react-dom":"^19"},"peerDependenciesMeta":{"react":{"optional":true},"react-dom":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/hypr-tiling_26.11.4_1794386832074_0.21130507012531596","host":"s3://npm-registry-packages-npm-production"}},"26.11.5":{"name":"@n-uf/hypr-tiling","version":"26.11.5","keywords":["react","tiling","dynamic-tiling","split-layout","split-pane","pane-layout","react-layout","dock-layout","window-manager-ui","resizable-panes","drag-and-drop","tiling-window-manager","layout-engine","dashboard","hyprland"],"license":"LicenseRef-PolyForm-Perimeter-1.0.1","_id":"@n-uf/hypr-tiling@26.11.5","maintainers":[{"name":"metelin","email":"metelin@gmail.com"}],"homepage":"https://hypr-tiling.n-uf.com/","bugs":{"url":"https://github.com/n-uf/hypr-tiling/issues"},"dist":{"shasum":"2d4bbc9387ba7e3217a2cdfb1dc4d8948a19df00","tarball":"https://registry.npmjs.org/@n-uf/hypr-tiling/-/hypr-tiling-26.11.5.tgz","fileCount":19,"integrity":"sha512-QQSnoYaGM1kq5FoH4SXsOIaCzkPSVA9wSJQ00uZeHe85fURyqTcqXSZsTw8TKTlYzov95H5rlILPH15Yfw9/CQ==","signatures":[{"sig":"MEUCIQCud2BX0IvCVs0RLHcUH7k+RYKY3MG9/URWG6LdThANlQIgCuPhQyDXAOuGUkH/GMBguefdEsN+2a8X3o2duVNyO1A=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIHbA5ZjZ9//887d+PvWT3TtcBeH3uwnN3UqgFJMh8oy2AiAgUxs02TamXIM1Rp+zm6VCj51lHUtxcf+H+H5zs+w6OA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@n-uf%2fhypr-tiling@26.11.5","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":3447560},"main":"./dist/index.cjs","_from":"file:/home/runner/work/_temp/package/n-uf-hypr-tiling-26.11.5.tgz","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./engine":{"types":"./dist/engine.d.ts","import":"./dist/engine.mjs","require":"./dist/engine.cjs"},"./devtools":{"types":"./dist/devtools.d.ts","import":"./dist/devtools.mjs","require":"./dist/devtools.cjs"}},"private":false,"scripts":{"test":"jest","build":"rm -rf dist && tsup","check":"pnpm typecheck && pnpm test && pnpm build && pnpm test:dist","api:docs":"node ./scripts/generate-api-docs.mjs","api:check":"api-extractor run --verbose -c api-extractor.index.json && api-extractor run --verbose -c api-extractor.devtools.json && api-extractor run --verbose -c api-extractor.engine.json","test:dist":"jest --config jest.dist.config.js","typecheck":"tsc --project tsconfig.json","api:update":"api-extractor run --local --verbose -c api-extractor.index.json && api-extractor run --local --verbose -c api-extractor.devtools.json && api-extractor run --local --verbose -c api-extractor.engine.json","check:guardrails":"node ./scripts/check-guardrails.mjs","release:next-version":"node ./scripts/calendar-version-bump.mjs --dry-run"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"2a5e1a18-41c3-4cdf-b471-b9c4226b808c"}},"_resolved":"/home/runner/work/_temp/package/n-uf-hypr-tiling-26.11.5.tgz","_integrity":"sha512-QQSnoYaGM1kq5FoH4SXsOIaCzkPSVA9wSJQ00uZeHe85fURyqTcqXSZsTw8TKTlYzov95H5rlILPH15Yfw9/CQ==","repository":{"url":"git+https://github.com/n-uf/hypr-tiling.git","type":"git"},"_npmVersion":"11.20.0","description":"Dynamic tiling for React: a recursive split-tree renderer for drag/drop, resizable, keyboard-controlled panes — inspired by Hyprland.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.4","dependencies":{"clsx":"^2.1.1","@n-uf/motion":"26.11.3","tailwind-merge":"^2.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.2.0","tsup":"^8.5.0","react":"^19.2.7","marked":"^18.0.5","ts-jest":"^29.4.5","react-dom":"^19.2.7","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^26.0.1","@types/react":"^19","@jest/globals":"^30.2.0","@types/react-dom":"^19","@testing-library/react":"^16.3.2","jest-environment-jsdom":"^30.4.1","@microsoft/api-extractor":"^7.58.9","@microsoft/api-documenter":"^7.30.7"},"peerDependencies":{"react":"^19","react-dom":"^19"},"peerDependenciesMeta":{"react":{"optional":true},"react-dom":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/hypr-tiling_26.11.5_1794393823789_0.6625658488077208","host":"s3://npm-registry-packages-npm-production"}},"26.11.6":{"_id":"@n-uf/hypr-tiling@26.11.6","bugs":{"url":"https://github.com/n-uf/hypr-tiling/issues"},"dist":{"shasum":"b791bcc705d8d6813993746dcff49296b12f7fb1","tarball":"https://registry.npmjs.org/@n-uf/hypr-tiling/-/hypr-tiling-26.11.6.tgz","fileCount":19,"integrity":"sha512-NcuW0+loBaTnX+fq/TAoRPb43YStdWEIXHtBqYWTTZ4d6cOz6ZOTtj11H7LxAD9NOOeQM48iAwSqOi1xGnqp5w==","signatures":[{"sig":"MEQCIANfX3kJ7BG3n7gD03XtNlpYv+eQJ0jG5fN/mgECFvY/AiB3TZi0x5oO51+iMsyxLHqpHSnkmHFGJ9z89/4XkIC+3w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIGd80siLpATnpLnwq+z7vpHgkgFll6CpD5VJQzkUnUnUAiEAyKlE9YS0hCCwpyO4M4tt3WNw86daZThVYXFf77IYdyw="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@n-uf%2fhypr-tiling@26.11.6","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":3447635},"main":"./dist/index.cjs","name":"@n-uf/hypr-tiling","_from":"file:/home/runner/work/_temp/package/n-uf-hypr-tiling-26.11.6.tgz","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./engine":{"types":"./dist/engine.d.ts","import":"./dist/engine.mjs","require":"./dist/engine.cjs"},"./devtools":{"types":"./dist/devtools.d.ts","import":"./dist/devtools.mjs","require":"./dist/devtools.cjs"}},"license":"LicenseRef-PolyForm-Perimeter-1.0.1","private":false,"scripts":{"test":"jest","build":"rm -rf dist && tsup","check":"pnpm typecheck && pnpm test && pnpm build && pnpm test:dist","api:docs":"node ./scripts/generate-api-docs.mjs","api:check":"api-extractor run --verbose -c api-extractor.index.json && api-extractor run --verbose -c api-extractor.devtools.json && api-extractor run --verbose -c api-extractor.engine.json","test:dist":"jest --config jest.dist.config.js","typecheck":"tsc --project tsconfig.json","api:update":"api-extractor run --local --verbose -c api-extractor.index.json && api-extractor run --local --verbose -c api-extractor.devtools.json && api-extractor run --local --verbose -c api-extractor.engine.json","check:guardrails":"node ./scripts/check-guardrails.mjs","release:next-version":"node ./scripts/calendar-version-bump.mjs --dry-run"},"version":"26.11.6","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"2a5e1a18-41c3-4cdf-b471-b9c4226b808c"}},"homepage":"https://hypr-tiling.n-uf.com/","keywords":["react","tiling","dynamic-tiling","split-layout","split-pane","pane-layout","react-layout","dock-layout","window-manager-ui","resizable-panes","drag-and-drop","tiling-window-manager","layout-engine","dashboard","hyprland"],"_resolved":"/home/runner/work/_temp/package/n-uf-hypr-tiling-26.11.6.tgz","_integrity":"sha512-NcuW0+loBaTnX+fq/TAoRPb43YStdWEIXHtBqYWTTZ4d6cOz6ZOTtj11H7LxAD9NOOeQM48iAwSqOi1xGnqp5w==","repository":{"url":"git+https://github.com/n-uf/hypr-tiling.git","type":"git"},"_npmVersion":"11.20.0","description":"Dynamic tiling for React: a recursive split-tree renderer for drag/drop, resizable, keyboard-controlled panes — inspired by Hyprland.","directories":{},"maintainers":[{"name":"metelin","email":"metelin@gmail.com"}],"sideEffects":false,"_nodeVersion":"22.23.4","dependencies":{"clsx":"^2.1.1","@n-uf/motion":"26.11.6","tailwind-merge":"^2.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.2.0","tsup":"^8.5.0","react":"^19.2.7","marked":"^18.0.5","ts-jest":"^29.4.5","react-dom":"^19.2.7","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^26.0.1","@types/react":"^19","@jest/globals":"^30.2.0","@types/react-dom":"^19","@testing-library/react":"^16.3.2","jest-environment-jsdom":"^30.4.1","@microsoft/api-extractor":"^7.58.9","@microsoft/api-documenter":"^7.30.7"},"peerDependencies":{"react":"^19","react-dom":"^19"},"peerDependenciesMeta":{"react":{"optional":true},"react-dom":{"optional":true}},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/hypr-tiling_26.11.6_1794555960791_0.9394187109868676"}}},"time":{"created":"2026-07-03T03:04:33.247Z","modified":"2026-11-13T07:46:01.299Z","26.6.1":"2026-06-26T08:17:18.925Z","26.6.3":"2026-06-30T04:00:35.176Z","26.7.0":"2026-07-03T03:04:33.776Z","26.7.1":"2026-07-03T04:37:16.200Z","26.7.2":"2026-07-30T10:05:46.588Z","26.9.0":"2026-09-21T03:02:55.072Z","26.9.1":"2026-09-22T00:11:00.168Z","26.9.2":"2026-09-22T04:48:17.451Z","26.10.0":"2026-09-22T15:46:29.648Z","26.9.3":"2026-09-22T19:13:58.411Z","26.9.4":"2026-09-24T02:14:46.239Z","26.9.5":"2026-09-24T02:55:55.386Z","26.9.6":"2026-09-24T17:54:46.666Z","26.9.7":"2026-09-24T19:36:08.615Z","26.9.8":"2026-09-24T21:18:54.849Z","26.9.9":"2026-09-24T22:40:28.632Z","26.11.0":"2026-11-08T07:11:35.803Z","26.11.1":"2026-11-10T07:15:28.722Z","26.11.2":"2026-11-10T07:22:31.537Z","26.11.3":"2026-11-11T04:09:07.846Z","26.11.4":"2026-11-11T08:47:12.210Z","26.11.5":"2026-11-11T10:43:43.923Z","26.11.6":"2026-11-13T07:46:00.933Z"},"bugs":{"url":"https://github.com/n-uf/hypr-tiling/issues"},"license":"LicenseRef-PolyForm-Perimeter-1.0.1","homepage":"https://hypr-tiling.n-uf.com/","keywords":["react","tiling","dynamic-tiling","split-layout","split-pane","pane-layout","react-layout","dock-layout","window-manager-ui","resizable-panes","drag-and-drop","tiling-window-manager","layout-engine","dashboard","hyprland"],"repository":{"url":"git+https://github.com/n-uf/hypr-tiling.git","type":"git"},"description":"Dynamic tiling for React: a recursive split-tree renderer for drag/drop, resizable, keyboard-controlled panes — inspired by Hyprland.","maintainers":[{"name":"metelin","email":"metelin@gmail.com"}],"readme":"<h1 align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/n-uf/hypr-tiling/main/assets/hypr-tiling-logo-transparent.png\" alt=\"hypr-tiling\" width=\"48\" align=\"center\" />\n  @n-uf/hypr-tiling\n</h1>\n<p align=\"center\">Dynamic tiling for React</p>\n\n> [!CAUTION]\n> ## Not yet stable\n>\n> **hypr-tiling is young and still changing. Its API, theming and saved\n> layout format are not final.**\n>\n> Version numbers are dates (YY.M.R), not semantic versions, so any release\n> may break things, including the layout tree that\n> `createPersistedTilingLayout` saves to `localStorage`: after an upgrade, a\n> saved tree may come back repaired or be replaced by your fallback layout.\n> Pin an exact version and read the\n> [CHANGELOG](https://github.com/n-uf/hypr-tiling/blob/main/packages/hypr-tiling/CHANGELOG.md)\n> before you upgrade. If you need a stable tiling layout library, use\n> [Dockview](https://dockview.dev) or\n> [react-mosaic](https://github.com/nomcopter/react-mosaic).\n\nDynamic tiling for React: a recursive split-tree renderer for drag/drop,\nresizable, keyboard-controlled panes — inspired by\n[Hyprland](https://hypr.land).\n\nReach for it when users need to rearrange dense, multi-panel screens at runtime\n— IDE-like tools, trading and operator consoles, analytics dashboards — while\nyour app keeps strict, controlled ownership of the layout state.\n\n## Quick links\n\n- Documentation homepage: <https://hypr-tiling.n-uf.com/>\n- API report index: [`etc/hypr-tiling.api.md`](https://github.com/n-uf/hypr-tiling/blob/main/packages/hypr-tiling/etc/hypr-tiling.api.md)\n- Repository issues: <https://github.com/n-uf/hypr-tiling/issues>\n\n## Install\n\n```bash\npnpm add @n-uf/hypr-tiling react react-dom\n```\n\n```bash\nnpm install @n-uf/hypr-tiling react react-dom\n```\n\n```bash\nyarn add @n-uf/hypr-tiling react react-dom\n```\n\n`react` and `react-dom` are peer dependencies (version `^19`), optional: `./engine` alone needs neither.\n\n## Versioning\n\nThe package uses calendar-aligned versioning, `YY.M.R` (year, month, release).\nThat scheme cannot signal a SemVer major bump. The library is in active\ndevelopment, and backward compatibility may break between releases. Pin an\nexact version in your manifest and read the per-release notes in\n[`CHANGELOG.md`](./CHANGELOG.md) before upgrading.\n\n## Entry points\n\n| Import | Contents | React |\n|---|---|---|\n| `@n-uf/hypr-tiling` | `TilingRenderer`, theming, the curated public API | yes — `\"use client\"` module |\n| `@n-uf/hypr-tiling/devtools` | observability panel and drag telemetry props | yes — `\"use client\"` module |\n| `@n-uf/hypr-tiling/engine` | the pure layout / workspace-set / keymap engine (`@beta`) | **no** |\n\n`./engine` is React-free and isomorphic: `dist/engine.{mjs,cjs}` is built as a\nstandalone bundle that shares no chunk with the two React entries and never\nimports `react` / `react-dom`, so it is safe to import from server code and\nreact-server layers (Next.js route handlers, Server Components, Node scripts).\nThe invariant is guarded on every build by\n`__tests__/engine-entry-react-free.test.ts` (`pnpm test:dist`: static scan of\nthe emitted bundle for `createContext` / `from \"react\"` markers plus a bare-Node\nimport with `react` made unresolvable) and by the `engine ↛ react` layering rule\nin `scripts/check-guardrails.mjs`.\n\nA host that places its own windows by a layout tree reads the renderer's geometry\nfrom `./engine`: `resolveLayoutGeometry(layout, container, config)` gives every\nshown leaf's rect and every split's box with the ratio in effect, in CSS px and\nunrounded, by the same pass the renderer lays panes out with\n(`resolveLeafRects` gives the leaves alone).\n\n## Compatibility\n\n- React: `^19`\n- React DOM: `^19`\n- Both are optional peers: `./engine` alone needs neither, so an engine-only project installs without them\n- Tailwind scanning: required (`content` glob or v4 `@source`)\n- Runtime: browser DOM (React renderer package)\n\n### Tailwind content requirement\n\nThe renderer styles its **visual** surfaces (pane shells, header, dividers,\nfocus frame, drop indicator) by emitting Tailwind utility class strings (via `clsx` +\n`tailwind-merge`) — those classes only resolve to real styles if Tailwind scans\nthis package's built output and generates the matching CSS. If you do not\nregister the package in your Tailwind `content` glob, those surfaces render\n**unstyled**.\n\n> **Critical chrome ships as CSS, not purge-dependent classes.** The functional\n> chrome the tiler cannot work without — resize-divider `col-resize` /\n> `row-resize` cursors and the focus-outline handling below — is emitted by the\n> renderer as a small stylesheet **scoped to `.hpt-root`** (React 19\n> `<style href>` hoisting), keyed off data attributes rather than Tailwind\n> `cursor-*` utilities. So resize cursors resolve correctly **even if your\n> Tailwind build never scans our dist**. Tailwind scanning affects only the\n> *visual* theme utilities, not these affordances.\n\nAdd `@n-uf/hypr-tiling` to your Tailwind `content` configuration:\n\n```js\n// tailwind.config.js\nexport default {\n  content: [\n    \"./src/**/*.{js,ts,jsx,tsx}\",\n    \"./node_modules/@n-uf/hypr-tiling/dist/**/*.{js,mjs}\",\n  ],\n  // ...\n};\n```\n\nFor Tailwind v4 (CSS-first config), declare the same path as a source in your\nstylesheet:\n\n```css\n@import \"tailwindcss\";\n@source \"../node_modules/@n-uf/hypr-tiling/dist/**/*.{js,mjs}\";\n```\n\nA custom `overlayPortalContainer` does not change that scan: library\n`dragChrome` tokens still come from this package's dist. If the drag cursor\nrenders **host-only** Tailwind utilities (classes declared only in the\nhost app), those still need the host's own `content` / `@source` globs —\nthe portal mount does not pull them into the library scan.\n\n## Quick start\n\nThe renderer is a **controlled component**: you own the layout tree in state and\napply every change it reports through `onLayoutChange`. Nothing about the layout\nis hidden inside the component — the tree is yours to persist, diff, and restore.\n\n```tsx\nimport {\n  TilingRenderer,\n  DEFAULT_TILING_LAYOUT_CONFIG,\n  type TilingLayoutNode,\n  type TilingTile,\n} from \"@n-uf/hypr-tiling\";\nimport { useState } from \"react\";\n\nconst tiles: TilingTile[] = [\n  { id: \"a\", title: \"editor\", content: <Editor /> },\n  { id: \"b\", title: \"preview\", content: <Preview /> },\n];\n\nconst initialLayout: TilingLayoutNode = {\n  kind: \"split\",\n  id: \"root\",\n  axis: \"vertical\",\n  ratio: 0.5,\n  first: { kind: \"leaf\", id: \"l\", tileId: \"a\" },\n  second: { kind: \"leaf\", id: \"r\", tileId: \"b\" },\n};\n\nexport function Workspace(): JSX.Element {\n  const [layout, setLayout] = useState<TilingLayoutNode>(initialLayout);\n  return (\n    <TilingRenderer\n      layout={layout}\n      tiles={tiles}\n      config={DEFAULT_TILING_LAYOUT_CONFIG}\n      onLayoutChange={setLayout}\n    />\n  );\n}\n```\n\n## Programmatic layout API\n\nBecause you own the layout tree, you can mutate it from your own code — not just\nthrough drag/keyboard interaction. The package exports a set of pure layout\nreducers (each takes a layout node and returns a new one, never mutating in\nplace) as supported public API. Use these to script layout changes, build custom\ncommands, or restore persisted arrangements:\n\n| Reducer | Purpose |\n| --- | --- |\n| `findLeafById` | Locate a leaf node within the tree by its id. |\n| `insertLeafAdjacent` | Insert a new leaf next to an existing one along an axis. |\n| `moveLeafToRoot` | Detach a leaf and re-seat it against the layout root. |\n| `moveLeafToSplitContainer` | Move a leaf into a target split container. |\n| `swapLeafTiles` | Exchange the tiles occupying two leaves. |\n| `removeLeafTile` | Remove a leaf and collapse its parent split. |\n| `updateSplitRatio` | Set the ratio of a binary split. |\n| `toggleSplitAxis` | Flip a split between horizontal and vertical. |\n| `setLeafSizing` | Set a leaf's sizing mode (static pixel extent vs. flexible). |\n| `groupLeaves` | Collapse several leaves into one stacked/tabbed group. |\n| `ungroupNode` | Expand a group back into individual leaves. |\n| `collectGroups` | Enumerate the group nodes in a layout. |\n| `isStructurallyValidLayout` | Validate a layout tree's structural invariants. |\n\nAll reducers are re-exported from the package root:\n\n```ts\nimport {\n  findLeafById,\n  insertLeafAdjacent,\n  swapLeafTiles,\n  isStructurallyValidLayout,\n} from \"@n-uf/hypr-tiling\";\n```\n\nOther layout-tree helpers are exported for advanced/internal use, but the\nreducers above are the stable, documented surface for application code.\n\nFor complete generated API signatures, see\n[`etc/hypr-tiling.api.md`](https://github.com/n-uf/hypr-tiling/blob/main/packages/hypr-tiling/etc/hypr-tiling.api.md).\n\n### Persisted layout (optional glue)\n\n`createPersistedTilingLayout` is a **thin persistence adapter**: it persists\nONLY the layout tree (splits, ratios, tileId leaves) to a key/value store\n(`localStorage` by default) and delegates every heal to the engine's first-class\n`assertLayoutIntegrity` / `repairLayout`. Repair is an engine trait, not a\npersistence feature — the integrity APIs stay usable with or without this\nhelper. The storage key, expected tile ids, and fallback tree stay app-owned.\n\n```ts\nimport { createPersistedTilingLayout } from \"@n-uf/hypr-tiling\";\n// also available from \"@n-uf/hypr-tiling/engine\"\n\nconst persisted = createPersistedTilingLayout({\n  storageKey: \"workspace.layout\",\n  expectedTileIds: [\"editor\", \"preview\", \"terminal\"],\n  fallbackLayout: DEFAULT_LAYOUT,\n  config: DEFAULT_TILING_LAYOUT_CONFIG,\n  // storage? — defaults to window.localStorage (in-memory when no DOM)\n  // resolveContainerSize? — defaults to window.innerWidth/innerHeight\n});\n\nconst [layout, setLayout] = useState<TilingLayoutNode>(() => persisted.load());\n// onLayoutChange={(next) => setLayout(persisted.commit(next))}\n// persisted.reset() restores + persists the fallback tree\n```\n\n`load()` reads → structurally validates → checks integrity → returns a repaired\ncopy (or the fallback when nothing is stored / a saved tree fails hard\nintegrity). `commit()` validates → repairs → persists the healed tree.\n\n### Focus-outline handling (SDK-controlled)\n\nBy default the renderer suppresses native UA focus outlines on its own chrome\n(pane roots, tabs, buttons) via a stylesheet **scoped to `.hpt-root`** — it never\ntouches app chrome. Opt out with the `chromeFocusOutline` prop to keep native\nbrowser focus rings:\n\n```tsx\n<TilingRenderer chromeFocusOutline=\"native\" /* … */ />\n// \"suppress\" (default) | \"native\"\n```\n\n### Drag-state chrome (`theme.dragChrome`)\n\nEvery drag surface the renderer paints — the lifted pane's shadow, the drop\nindicator, the drop-target highlight, the pointer-pinned drop-validity badge —\nreads the theme's optional, **partial** `dragChrome` slot. The dragged pane is\nthe real pane (no ghost copy), so it keeps its own at-rest look; omitted tokens\nfall back to the defaults (`resolveDragChrome(theme)`). To make a square, flat\nhost drag square and flat:\n\n```tsx\nconst THEME: TilingTheme = {\n  ...TILING_THEME_REGISTRY[\"clean-flat\"],\n  paneShell: { ...base.paneShell, surface: \"… rounded-none border border-slate-700 bg-slate-900\" },\n  dragChrome: {\n    liftedPane: \"drop-shadow-[0_8px_20px_rgba(0,0,0,0.5)]\", // follows the pane as it is drawn\n    dropIndicator: \"rounded-none border border-dashed border-amber-500 bg-amber-500/15\",\n    cursorBadge: \"rounded-none border\",\n  },\n};\n```\n\n**Theme scoping.** `dragChrome` tokens are literal class strings so\nTailwind's JIT can emit them — that is not a portal constraint. The lifted\npane and the drop indicator render inside the renderer, so they inherit the\nhost's scoped CSS. Only the custom drag cursor portals; host CSS that scopes\ncolours via CSS variables, `data-theme`, or a scoped `dark` class reaches it\nonly if it mounts on the overlay portal container (default `document.body`,\nsee `overlayPortalContainer`):\n\n```tsx\nconst overlayRef = useRef<HTMLDivElement | null>(null);\nreturn (\n  <div data-theme=\"dark\" ref={overlayRef}>\n    <TilingRenderer overlayPortalContainer={() => overlayRef.current} /* … */ />\n  </div>\n);\n```\n\nThe container must not sit under a `transform` / `filter` /\n`backdrop-filter` / `perspective` / `contain: paint` ancestor. Overlay\nz-indexes (220 / 230) are relative to that container's stacking context.\n\n### Stable pane identity (`paneIdentity`)\n\nBy default on a client-only mount, a pane's React instance survives every layout\nedit — drag → drop → settle, swaps, group folds — without remounting: panes\nrender once in a hidden tile-keyed pool and their DOM node is relocated into\nwhichever slot shows their tile. Hooks, state, refs, iframes, and scroll\npositions are preserved. When the renderer hydrates server markup it stays in\nthe legacy in-place mode (`\"slot\"`); pass `paneIdentity=\"stable\"` to opt an SSR\nhost in (server HTML then carries empty pane slots). A drag lifts the real\npane: in stable mode the same instance is held under the pointer and dropped;\nin slot mode the lifted pane is mounted afresh at the lift and again at the\ndrop (state inside the tile does not carry over).\n\n```tsx\n<TilingRenderer paneIdentity=\"stable\" /* \"auto\" (default) | \"stable\" | \"slot\" */ />\n```\n\n### Overlay portal container (theme scoping)\n\nThe custom drag cursor portals to `document.body` by default so its\n`position: fixed` coordinates stay window-relative — immune to ancestor\n`transform` / `filter` / `backdrop-filter` / `contain: paint` containing\nblocks. (The lifted pane does not portal: it is a fixed layer inside the\nrenderer whose containing block is measured, so it escapes the viewport's\nclip and follows scroll and scale.) A host whose theme tokens live on a\nscoped root (CSS variables that the cursor must inherit) can redirect the\nportal:\n\n```tsx\n<TilingRenderer\n  overlayPortalContainer={overlayHost}          // HTMLElement\n  // overlayPortalContainer={() => overlayRef.current}  // thunk, re-read each render\n  /* … */\n/>\n```\n\nThe thunk form is evaluated every render so a late-mounted container is\npicked up without remounting the renderer. `null` / omitted falls back to\n`document.body`.\n\n**Containing-block caveat.** The container must not sit under an ancestor\nwith `transform`, `filter`, `backdrop-filter`, `perspective`,\n`contain: paint` (or `layout` / `strict` / `content`), or `will-change` of\nthose. The cursor uses window-relative client coordinates; a\ncontaining-block ancestor offsets it from the pointer.\n\n### External drop targets\n\nWhen a tile is dragged over host chrome outside the tiling tree (a\nworkspace tab strip, a chat panel), the host reports that hover; the held\npane stays visible over it (it is not clipped by the viewport). On release\nthe host claims the leaf **before** the drag FSM settles: the pane leaves\nthe tree and fades out where it was drawn. This is the standalone subset of\nthe WorkspaceSet drag scope — see\n[`_agent/workspace-set-concept.md`](../../_agent/workspace-set-concept.md)\n§5.5.\n\n```tsx\n<TilingRenderer\n  externalDragHover={\n    tabOver ? { targetId: tabOver.id, point: tabOver.point } : null\n  }\n  onExternalDrop={(leafId, targetId, point, hover, subject) => {\n    // synchronous claim; a dragged tab group is handed over whole\n    for (const member of subject.members) {\n      moveItemToTab(member.id, targetId, point);\n    }\n    if (subject.kind === \"group\") {\n      const groupId = subject.groupId;\n      setLayout((tree) => removeGroupNode(tree, groupId));\n    }\n  }}\n  /* … */\n/>\n```\n\n`removeGroupNode` is imported from `@n-uf/hypr-tiling/engine`. `leafId` is the\ndragged pane (a dragged group's active tab). The fifth argument, `subject`,\nsays what the claim hands over: one pane (`kind: \"pane\"`), or, when the drag\nmoved a tab group, the whole group (`kind: \"group\"`, which narrows `groupId`\nto a string) with every member in tab order in `subject.members`. The host\ntakes every member and takes the group out of its layout; one that takes only\nsome would see the rest flash out and back while the claim settles. A host\nthat ignores `subject` still gets the active pane's leaf id first, as before.\nA workspace tab in set mode takes the whole group on its own\n(`moveGroupToWorkspace`).\n\nOmit `onExternalDrop` (or return `false` from it) and the release cancels:\nthe layout stays as it was at the lift and the pane settles home.\n\n## Workspaces\n\nSeveral layout trees over one tile pool, one active at a time — the\nwindow-manager \"workspace\" (i3 / Hyprland / Sway). The engine owns the set\n(`TilingWorkspaceSet`, pure ops, integrity walker + repair); the renderer\npaints the active tree and switches **without remounting** a pane whose\nleaf exists in both workspaces; the headless tab strip owns the WAI-ARIA\nsemantics, keyboard model and drop-target wiring. Design record:\n[`_agent/workspace-set-concept.md`](../../_agent/workspace-set-concept.md).\n\n```tsx\nimport {\n  TilingRenderer,\n  useTilingWorkspaceTabs,\n  workspaceSetOfLayout,\n  createWorkspace,\n  type TilingWorkspaceSet,\n} from \"@n-uf/hypr-tiling\";\n\nfunction Dashboard() {\n  const [set, setSet] = useState<TilingWorkspaceSet>(() =>\n    workspaceSetOfLayout(initialLayout), // one \"Main\" workspace\n  );\n  const tabs = useTilingWorkspaceTabs({\n    workspaces: set,\n    onWorkspacesChange: setSet,\n    onRenameRequest: (ws) => openRenameDialog(ws), // commit via tab.rename(name)\n    onCloseRequest: (ws) => confirmClose(ws),      // commit via tab.close()\n  });\n  return (\n    <>\n      <div {...tabs.tablistProps}>\n        {tabs.tabs.map((tab) => (\n          <button key={tab.workspace.id} {...tab.tabProps}>\n            {tab.workspace.name}\n          </button>\n        ))}\n        <button onClick={() => tabs.create({ id: crypto.randomUUID(), name: \"New\" })}>+</button>\n      </div>\n      <div {...tabs.panelProps(set.activeId)}>\n        <TilingRenderer\n          workspaces={set}\n          onWorkspacesChange={setSet}\n          tiles={tiles}\n          config={DEFAULT_TILING_LAYOUT_CONFIG}\n          {...tabs.rendererProps} // tabs become native drop targets\n        />\n      </div>\n    </>\n  );\n}\n```\n\n- **Engine ops** (pure, `set → set`): `createWorkspace`, `renameWorkspace`,\n  `deleteWorkspace` (refuses the last; returns `removedTileIds` shown only\n  there), `switchWorkspace`, `cycleWorkspace`, `setWorkspaceLayout`,\n  `moveLeafToWorkspace(set, leafId, to, placement?)`, `showInWorkspace`,\n  `hideFromWorkspace`, tile-keyed `moveTileToWorkspace`, `showTileInWorkspace`,\n  `hideTileFromWorkspace`, `removeTile`, `revealTile`, `resetWorkspaceLayout`,\n  `resetWorkspaceSet`, `workspaceSetEquals`, `queryWorkspaceSet`,\n  `workspaceSetIssues`, `repairWorkspaceSet`. `TilingWorkspacePlacement` adds\n  `{ kind: \"region\"; region: \"start\" | \"end\" }` for reading-order ends.\n  Limits: `TILING_WORKSPACES_MAX` (12), `TILING_WORKSPACE_NAME_MAX_CHARS` (40).\n  A leaf may sit in several trees (`showInWorkspace`); there is no pin table\n  (`TilingLeafPin` did not ship).\n- **Renderer** — `workspaces` + `onWorkspacesChange` replace `layout` +\n  `onLayoutChange`. Uncontrolled focus / maximize are remembered per\n  workspace; a drag in flight is cancelled when the active workspace\n  changes; an empty workspace renders `renderEmptyWorkspace(workspace)`.\n- **`tiles` is the whole pool** — pass every tile any workspace seats.\n  Coverage is checked **per tree**: the active layout is healed against the\n  tiles *it* seats (no empty leaves, no duplicate seats, no seat for a tile\n  missing from the pool); a pool tile shown only elsewhere is never forced\n  into the active tree. Set-wide integrity is the wrapper's job:\n  - `orphanTiles?: \"seat-in-active\" | \"ignore\" | \"report\"` (default\n    `\"report\"`) — a pool tile no workspace seats / a seat whose tile is not\n    in the pool. `\"report\"` leaves the set alone and calls\n    `onIntegrityIssues(issues)` whenever the issue fingerprint changes\n    (once more with `[]` when it clears); `\"seat-in-active\"` runs\n    `repairWorkspaceSet` once per set identity (orphans seated in the\n    active tree with `TILING_DEFAULT_WORKSPACE_PLACEMENT`, unknown seats\n    pruned), emits the repaired set on `onWorkspacesChange`, and reports\n    what it repaired; `\"ignore\"` does neither. `mintLeafId?: (tileId) =>\n    string` names a minted seat (default `` `leaf:${tileId}` ``).\n  - `inactiveWorkspaces?: \"unmount\" | \"keep-mounted\"` (default\n    `\"unmount\"`) — with `paneIdentity: \"stable\"`, `\"keep-mounted\"` parks a\n    pane whose tile is seated only in an inactive workspace in the hidden\n    pool (`display: none`) instead of unmounting it, so an iframe / video /\n    editor survives a round trip. Cost: every retained pane's DOM and React\n    subtree stays alive (memory, hidden-subtree effects). A pane is\n    retained only after its first paint; an empty active workspace still\n    unmounts everything; no-op under `paneIdentity: \"slot\"`.\n  - `renderTile` receives `workspaceId` (the workspace the pane is painted\n    in) and `seatCount` (how many workspaces seat the tile) — single-layout\n    mode reports `TILING_MAIN_WORKSPACE_ID` / `1`.\n- **Drop on a tab** — a `kind: \"workspace-tab\"` `externalDragHover` (what\n  `tabs.rendererProps` resolves for you) settles by `moveLeafToWorkspace`\n  with no host claim; `onMoveLeaf(leafId, from, to)` reports it. With\n  `interaction.workspaces.followMovedLeaf: true` the same\n  `onWorkspacesChange` is already switched to the destination\n  (`onWorkspaceSwitch({ via: \"tab-drop\" })`) — do not switch again from\n  `onMoveLeaf`. Under `paneIdentity: \"stable\"` the dragged pane stays\n  parked in the pool for the whole drag (over empty space, over a tab, into\n  another workspace), so the release reseats the same mount and in-pane\n  local state survives.\n- **Tab strip** — `role=\"tablist\"` / `role=\"tab\"`, roving `tabIndex`,\n  Arrow keys / Home / End move focus, Enter / Space activate, F2 → \n  `onRenameRequest`, Delete → `onCloseRequest`. Unstyled until a theme\n  supplies `workspaceTabs` / `workspaceTab` / `workspaceTabActive` /\n  `workspaceTabDropTarget`.\n\n### Workspace set controller\n\nA persisted document (`value` / `onCommit`) plus in-flight tree overlays.\nTree edits coalesce for `treeDebounceMs` (default 400) and commit as\n`\"tree\"`; `create` / `rename` / `remove` / `switch` commit immediately as\n`\"lifecycle\"`; `moveTile` as `\"move\"`; `reveal` as `\"reveal\"` when\n`changed !== \"none\"`. `readOnly` keeps switches local and commits nothing.\n`maxWorkspaces` caps `create()` (default `TILING_WORKSPACES_MAX`).\n`ctl.flush()` commits pending trees now; `ctl.pending` is `true` while a\ntree debounce is open. Pass `ctl.set` and `ctl.onWorkspacesChange` to both\nthe renderer and the tab strip.\n\n```tsx\nimport {\n  TilingRenderer,\n  useTilingWorkspaceSetController,\n  useTilingWorkspaceTabs,\n} from \"@n-uf/hypr-tiling\";\n\nfunction Dashboard({ persisted, persist, readOnly, tiles }) {\n  const ctl = useTilingWorkspaceSetController({\n    value: persisted,\n    onCommit: (next, reason) => persist(next, reason),\n    readOnly,\n    mintWorkspaceId: () => crypto.randomUUID(),\n    nextWorkspaceName: (existing) => `Workspace ${existing.length + 1}`,\n  });\n  const tabs = useTilingWorkspaceTabs({\n    workspaces: ctl.set,\n    onWorkspacesChange: ctl.onWorkspacesChange,\n    onRenameRequest: (ws) => ctl.rename(ws.id, window.prompt(\"Name\", ws.name) ?? ws.name),\n    onCloseRequest: (ws) => ctl.remove(ws.id),\n  });\n  return (\n    <>\n      <div {...tabs.tablistProps}>\n        {tabs.tabs.map((tab) => (\n          <button key={tab.workspace.id} {...tab.tabProps}>\n            {tab.workspace.name}\n          </button>\n        ))}\n        <button onClick={() => ctl.create()}>+</button>\n      </div>\n      <TilingRenderer\n        workspaces={ctl.set}\n        onWorkspacesChange={ctl.onWorkspacesChange}\n        tiles={tiles}\n        {...tabs.rendererProps}\n      />\n    </>\n  );\n}\n```\n\n### Reset to defaults\n\nTwo modes, both keep the visitor on the workspace they are looking at\n(`activeId` never changes). Pass the seed as `workspaceDefaults` on the\nrenderer (without it, the reset commands are no-ops) and as `defaults` on\nthe controller.\n\n- `resetWorkspaceLayout(set, defaults, workspaceId?)` / `{ kind: \"reset-workspace\"; workspaceId? }`\n  — replace **one** workspace's `layout` and `name` from the seed workspace\n  of the same id (`workspaceId` omitted → `set.activeId`). If the seed has\n  no such id, that workspace's `layout` becomes `null` and its name is kept.\n- `resetWorkspaceSet(set, defaults)` / `{ kind: \"reset-workspaces\" }` —\n  replace the **whole** set from the seed, keeping `set.activeId` when that\n  id exists in the seed.\n- Controller: `ctl.reset(\"workspace\" | \"all\", workspaceId?)` commits\n  immediately (same path as `switch`, not tree-debounced) and returns\n  `false` when nothing changed or `defaults` is omitted. `ctl.atDefaults`\n  is `true` when `reset(\"all\")` would change nothing — every workspace\n  matches the seed, whichever one is active (`false` with no defaults). No\n  default key bindings — host opt-in only.\n\n```tsx\nconst ctl = useTilingWorkspaceSetController({\n  value: persisted,\n  defaults: SEED,\n  onCommit: persist,\n  mintWorkspaceId: () => crypto.randomUUID(),\n  nextWorkspaceName: (existing) => `Workspace ${existing.length + 1}`,\n});\n\n<TilingRenderer\n  workspaces={ctl.set}\n  workspaceDefaults={SEED}\n  onWorkspacesChange={ctl.onWorkspacesChange}\n  tiles={tiles}\n/>;\n```\n\n### Workspace commands & keymap\n\nWorkspace navigation is typed `TilingCommand` surface — same handle as layout\ncommands. Opt in to default chords with `WORKSPACE_KEY_BINDINGS` spread into\n`interaction.keyBindings.bindings` (`Alt+Arrow` cycle, `Alt+1..9` switch by\nindex, `Alt+Shift+Arrow` move focused leaf + follow). Gate dead controls with\n`TilingCommandGates.workspacesEnabled` (`false` in single-layout mode).\n\n```tsx\nimport { TilingRenderer, WORKSPACE_KEY_BINDINGS } from \"@n-uf/hypr-tiling\";\n\n<TilingRenderer\n  workspaces={set}\n  onWorkspacesChange={setSet}\n  onWorkspaceSwitch={({ from, to, via }) => …}\n  interaction={{\n    keyBindings: { bindings: [...WORKSPACE_KEY_BINDINGS] },\n    workspaces: { followMovedLeaf: true },\n  }}\n  commandRef={commandRef}\n  /* … */\n/>;\n```\n\nDispatch from app code: `commandRef.current?.dispatch({ kind: \"switch-workspace\", workspaceId })`,\n`{ kind: \"cycle-workspace\", direction: \"next\" }`, `{ kind: \"move-leaf-to-workspace\", … }`,\n`{ kind: \"reveal-tile\", tileId }`, `{ kind: \"reset-workspace\" }`, `{ kind: \"reset-workspaces\" }`.\n`reveal-tile` prefers the active workspace when it already shows the tile.\nReset commands require `workspaceDefaults` and keep `activeId`.\n\n`onWorkspaceSwitch` fires beside `onWorkspacesChange` when `activeId` changes\nthrough the renderer. `TilingWorkspaceSwitchVia`: `\"key\"` (keymap),\n`\"command\"` (imperative `dispatch`, including a host tab strip that calls\n`switch-workspace`), `\"swipe\"`, `\"spring-load\"`, `\"reveal\"`, `\"tab-drop\"`\n(plain tab release with `followMovedLeaf: true`). `\"tab\"` is reserved (not\nemitted; a strip that dispatches `switch-workspace` is `\"command\"`).\n\n### Workspace switch transition\n\nOpt in with `interaction.workspaces.switch.transition: \"slide\" | \"fade\"`\n(default `\"none\"`). The set-mode wrapper then mounts\n`<WorkspaceTransitionStage>` inside its viewport around the live tree and\ndrives it: the outgoing viewport is frozen as a DOM clone\n(`captureViewClone`) **before** the tree swaps — for renderer-driven\nswitches (command, key, tab, reveal, swipe) and for a host-driven\n`activeId` change alike — and slid or faded against the live incoming\ntree, then dropped. A tracking swipe scrubs the stage from its `progress`;\nreleasing short of the commit threshold settles it back; a committed swipe\nkeeps its capture. `cycle-workspace` keeps its own direction across a\nwrap-around; other switches derive `prev` / `next` from tab order.\n\n```tsx\n<TilingRenderer\n  workspaces={set}\n  onWorkspacesChange={setSet}\n  interaction={{\n    workspaces: { switch: { transition: \"slide\", wheelSwipe: true } },\n  }}\n  /* … */\n/>\n```\n\n`prefers-reduced-motion: reduce` resolves to `\"none\"` (instant, no clone).\nA tainted or oversized `<canvas>` capture falls `\"slide\"` → `\"fade\"`. Theme\ntoken `workspaceTransition` (`durationMs`, `easing`) supplies the timed\ncurve (default 200 ms, `cubic-bezier(0.2, 0.8, 0.2, 1)`). Because the clone is a snapshot,\n`inactiveWorkspaces: \"keep-mounted\"` is not needed for the animation — it\nonly matters for panes whose live state must survive the switch.\n\n`useWorkspaceTransition` / `WorkspaceTransitionStage` stay exported for a\nhost that animates its own viewport (call `begin` before updating\n`activeId`, `scrub(progress)` while tracking, `finish(\"commit\" | \"cancel\")`\nto settle; the viewport needs `position: relative; overflow: hidden`).\n\n### Swipe between workspaces\n\nOpt in per input with `interaction.workspaces.switch` (both off by default):\na horizontal trackpad / wheel burst or a one-finger touch swipe on the\nrenderer cycles to the neighbouring workspace through the same command path\nas the keymap (`onWorkspacesChange` + `onWorkspaceSwitch({ via: \"swipe\" })`).\nThe gesture never arms while a pane drag is in flight, while `Ctrl` is held\n(pinch-zoom), for a mostly vertical delta, or while an inner element under\nthe pointer can still scroll horizontally; the first / last workspace has no\nneighbour on that side unless `wrap: true`. A wheel run is claimed at its\n**sequence start**: if the first sample(s) fail arming, later samples of\nthat run (gaps `< wheelIdleMs`) cannot arm, even if they become horizontal —\nso a vertical scroll's horizontal tail, and trackpad momentum after a\ncommit, stay with the page. While `armed`, the `|dx| > 2·|dy|` ratio must\nhold **cumulatively** across the window (a gradually diagonal path drops\nback to scroll); once `tracking`, vertical drift is tolerated. Optional\n`modifier: \"meta\" | \"alt\" | \"shift\"` requires that key on the arming\nsamples only (release mid-track does not cancel); touch ignores it. When\nenabled the root gets `overscroll-behavior-x: contain` (and\n`touch-action: pan-y` for touch), including when a modifier is set —\nwheel without the modifier still scrolls normally (`preventDefault` only\nwhile `tracking`).\n\n```tsx\n<TilingWorkspaceSwipeScope>\n  <TabStrip />   {/* const { progress, target, phase } = useWorkspaceSwipe(); */}\n  <TilingRenderer\n    workspaces={set}\n    onWorkspacesChange={setSet}\n    interaction={{\n      workspaces: {\n        switch: { wheelSwipe: { modifier: \"meta\" }, touchSwipe: true },\n      },\n    }}\n    /* … */\n  />\n</TilingWorkspaceSwipeScope>\n```\n\n`wheelSwipe` takes `true` or a partial `TilingWorkspaceSwipeConfig`\n(`thresholdPx` 24, `commitFraction` 0.35, `commitVelocityPxMs` 0.6,\n`wheelIdleMs` 120, `lockoutMs` 350, `wrap` false, `modifier` null). `useWorkspaceSwipe()` is\nheadless — `progress` is `-1..1` (negative = towards the previous workspace)\nso a tab indicator can follow the finger; it reads the idle snapshot outside\na `TilingWorkspaceSwipeScope`. With a switch transition on, `phase` stays\n`\"settling\"` until the stage has finished sliding (commit or cancel); with\n`\"none\"` the settle is immediate. The pure FSM (`workspaceSwipeReducer`) and\nthe port contracts ship on `@n-uf/hypr-tiling/engine`.\n\n### Spring-loaded tab drop\n\nOpt in with `interaction.workspaces.springLoad` (off by default; `true`-like\nvalues are `{}` or a partial `{ dwellMs }`, default 500 ms). It needs the\nhost to report the workspace tab under a pane drag as a\n`kind: \"workspace-tab\"` external hover — through `resolveExternalDragHover`\n(point → hover) or the `externalDragHover` prop — the same hover the\nrelease-on-tab drop already uses.\n\n```tsx\n<TilingRenderer\n  workspaces={set}\n  onWorkspacesChange={setSet}\n  onMoveLeaf={(leafId, from, to) => …}\n  onWorkspaceSwitch={(event) => … /* event.via === \"spring-load\" */}\n  resolveExternalDragHover={(point) => tabStrip.hoverAt(point)}\n  interaction={{ workspaces: { springLoad: { dwellMs: 400 } } }}\n  /* … */\n/>\n```\n\nHolding a dragged pane over another workspace's tab for `dwellMs` moves\nthe leaf into that workspace (`moveLeafToWorkspace`, default placement),\nswitches to it (one `onWorkspacesChange`; a `switch.transition` animates it)\nand fires `onMoveLeaf` + `onWorkspaceSwitch({ via: \"spring-load\" })` — then\nthe drag **continues** on the leaf's new seat in the destination tree under\nthe still-held pointer, so the user can place it, spring-load on to a third\nworkspace, or press Escape to settle it back into that seat. The active\nworkspace's own tab never dwells; leaving the tab before the deadline resets\nthe dwell; releasing or cancelling mid-dwell runs the ordinary tab drop /\ncancel. The dwell FSM (`springLoadReducer`) and the drag `REARM` edge ship on\n`@n-uf/hypr-tiling/engine`.\n\n### Migration from a per-workspace `layouts` map\n\nHosts that kept `Record<workspaceId, TilingLayoutNode>` plus `activeId` (and\nremounted the renderer with `key={activeId}`) replace that map with one\n`TilingWorkspaceSet`:\n\n```ts\nconst set: TilingWorkspaceSet = {\n  workspaces: Object.entries(layouts).map(([id, layout]) => ({\n    id,\n    name: names[id] ?? id,\n    layout,\n  })),\n  activeId,\n};\n```\n\nPass `workspaces` + `onWorkspacesChange` (or `useTilingWorkspaceSetController`)\nand drop the remount key. `tiles` is the whole pool — do not slice to the\nactive tree. Tab drop with `followMovedLeaf: true` already switches in the\nsame `onWorkspacesChange` (`via: \"tab-drop\"`) — do not call `switchWorkspace`\nfrom `onMoveLeaf`.\n\n## Tab groups\n\n`grouping.enable` (default on) lets a drag merge panes into a stacked group.\nThe built-in strip is the canonical chrome: with `grouping.showGroupTabStrip`\nleft at its default `true`, a group of two or more members paints a tab row\n(`role=\"tablist\"`) above the pane header. Tabs are content-width and\nleft-aligned inside a rounded rail — they never stretch to fill the row\n(they shrink only when the rail overflows, min-width 56px, ellipsis, full\ntitle in the `title` attribute). The active pill uses the quiet group tokens\nby default; inactive tabs use `tabColor` at full opacity (hover uses\n`tabHoverColor`). Arrow keys, Home, and End move the active member (the\nsame `group-tab-jump` path as a click). The right end ejects the active member\n(`remove-from-group`, a sibling split) and ungroups. `groupTabStrip.showEject`\nand `groupTabStrip.showUngroup` both default to `true`; set either to `false`\nto hide that control.\n\nWhen a group member is maximized and the pane strip is shown, the group row\nis the nested tier: 4px shorter than the `height` token, indented ~18px,\n`data-nested=\"true\"` / `--hpt-tab-strip-nested: true`, a `└` tick in\n`controlColor` before the rail, and the `nestedTabActive*` tokens on the\nactive pill. A standalone group strip is not nested.\n\n`placement: \"bottom\"` draws that same row under the pane body. Either\nplacement subtracts the rendered strip height from the member content box so\nthe body does not clip. The strip sits in the group's own stacking context\n(same layer as the pane header, not an overlay). The pill transition is\n`none` under `prefers-reduced-motion`. `accent` is the keyboard\n`:focus-visible` outline colour.\n\n| `groupTabStrip` field | Default | What it does |\n| --- | --- | --- |\n| `placement` | `\"top\"` | `\"top\"` above the header, `\"bottom\"` under the body |\n| `height` | `28` | Strip height in CSS pixels; subtracted from the content box |\n| `showUngroup` | `true` | Ungroup control at the right end |\n| `showEject` | `true` | Eject the active member at the right end |\n| `theme` | dark row, quiet pill | CSS-value tokens (see below); omitted tokens keep the group default |\n| `renderTabLabel` | tile title | `(member) => ReactNode`; `member` is `{ id, tileId, title, active }` |\n\nTheme tokens (`TilingGroupTabStripTheme`, all optional CSS values):\n\n| Token | Group default | Pane default | What it does |\n| --- | --- | --- | --- |\n| `background` | `rgba(0, 0, 0, 0.45)` | same | Strip row background |\n| `borderColor` | `rgba(255, 255, 255, 0.1)` | same | Strip hairline bottom border |\n| `tabColor` | `rgb(148, 163, 184)` | same | Inactive pill label |\n| `tabHoverColor` | `rgb(226, 232, 240)` | same | Inactive pill label on hover |\n| `tabActiveColor` | `rgb(255, 251, 235)` | `rgb(12, 13, 16)` | Active pill label (standalone) |\n| `tabBackground` | `transparent` | same | Inactive pill background |\n| `tabActiveBackground` | `rgba(255, 255, 255, 0.08)` | `rgb(252, 211, 77)` | Active pill background (standalone) |\n| `accent` | `rgb(252, 211, 77)` | same | `:focus-visible` outline |\n| `fontFamily` | `ui-monospace, SFMono-Regular, Menlo, monospace` | same | Pill label font |\n| `fontSize` | `10px` | same | Pill label size |\n| `letterSpacing` | `0.08em` | same | Pill label tracking |\n| `radius` | `0px` | same | Pill corner radius; rail is `radius + 2` |\n| `gap` | `2px` | same | Gap between pills in the rail |\n| `paddingX` | `6px` | same | Strip row horizontal padding |\n| `controlColor` | `rgb(168, 162, 158)` | same | Eject / ungroup / nest-tick |\n| `controlHoverColor` | `rgb(254, 243, 199)` | same | Controls on hover |\n| `railBackground` | `rgba(255, 255, 255, 0.02)` | same | Rounded rail fill |\n| `railBorderColor` | `borderColor` | same | Rail 1px border; omitted follows `borderColor` |\n| `nestedTabActiveBackground` | `rgba(255, 255, 255, 0.08)` | same | Active pill fill on the nested group tier |\n| `nestedTabActiveColor` | `tabActiveColor` | same | Active pill label on the nested group tier |\n\nThey resolve like `dragChrome` (partial over the strip's default set —\n`TILING_GROUP_TAB_STRIP_THEME_DEFAULTS` or\n`TILING_PANE_TAB_STRIP_THEME_DEFAULTS`) and apply as inline styles plus\n`--hpt-group-tab-*` custom properties on the strip (`hpt-tab-strip`; group\nalso `hpt-group-tab-strip`, pane also `hpt-pane-tab-strip`). The rail is\n`.hpt-tab-strip-rail`.\n\nA drop on a strip tab resolves `group-merge` and inserts the dragged leaf at\nthat tab's index (the hovered member shifts right). A drop on the strip past\nthe last tab appends. Host targets do not insert by index.\n\n```tsx\ninteraction={{\n  grouping: {\n    showGroupTabStrip: true,\n    groupTabStrip: {\n      placement: \"top\",\n      theme: { background: \"#0c0d10\", accent: \"rgb(252, 211, 77)\" },\n    },\n  },\n}}\n```\n\nHosts that still set `grouping.showGroupTabStrip: false` can paint their own\nchips. Attach `args.groupDropTargetRef` to the element that should mean\n\"drop here to group with this pane\" — a title bar, a chip row, or both (the\nsame callback may be attached to more than one element). That hit is the\nsecondary path: it resolves the same `group-merge` commit, but it always\nappends.\n\nA pointer over that element during a drag resolves `group-merge`. The target\nis a loose leaf → a new group `{target, source}` with the source active. The\ntarget is already a group → the source is appended and made active. The drag\nsource's own target is skipped, and so is a target whose group already\ncontains the source; those hits fall through to the pane body. The whole hit\nis off when `grouping.enable` is false. It works with the built-in strip\nshown or hidden.\n\nWhile the pointer is over a group-merge target — the built-in strip, or a\nhost element (`fallbackReason: \"host-group-drop-target\"`) — the **target**\npane's `preview` is `{ mode: \"group-merge\", role: \"drop-target-result-shadow\",\n… }`. Other panes, including the drag source, keep `preview: null` for that\nintent. Hosts paint a merge ring from `preview.mode === \"group-merge\"`. Live\ndrag mode still suppresses the per-tile preview.\n\nPrecedence, highest first: the built-in strip, then the host element (it wins\nover the centre swap and over any edge band the element covers), then\nuncovered edge bands (`edge-insert`), then the pane centre (`swap`).\n\n```tsx\n<header ref={args.groupDropTargetRef} onPointerDown={args.onHandlePointerDown}>\n  {args.tile.title}\n</header>\n```\n\n### Multi-select grouping\n\nWith `paneSwitching.multiSelectGrouping` (default on) and `grouping.enable`,\nAlt/Opt+click on a pane header toggles panes into a transient multi-selection\n(`isMultiSelectGroupingEnabled`, `isMultiSelected`, `onToggleMultiSelect`).\n`multiSelectionCount` is the number of leaves currently multi-selected in the\nactive workspace (`0` when none). Every pane of that workspace reports the\nsame count, including panes that are not themselves selected, so a host can\nshow Cancel when the count is `1`. When at least two are selected and grouping\nwould change the layout, `canGroupMultiSelection` is true and\n`onGroupMultiSelection(clickedLeafId)` folds them into one tabbed group at the\nclicked pane's slot. Escape clears the selection; hosts can call\n`onClearMultiSelection()` from their own Cancel control to run the same clear\npath without walking every pane's toggle. Inactive retained panes report\n`multiSelectionCount: 0`.\n\n## Maximize\n\nMaximize is a non-destructive render mode: the focused pane fills the tiling\nviewport and siblings are hidden; the layout tree is not rewritten. Restore\nwith a second maximize, `Escape`, or the header control.\n\n`maximize.keepGroupTabStrip` (default `true`) keeps the group's tab strip\nwhen the maximized leaf is a group member. The renderer paints the GROUP\nnode at viewport size and overrides `activeMemberId` to the maximized leaf\nat render time (no `onLayoutChange`). The strip height is subtracted from\nthe maximized member. When the pane strip is also shown, that group row is\nthe nested tier (see Tab groups). `grouping.showGroupTabStrip: false` still\nhides the strip. Set `keepGroupTabStrip: false` to fill the viewport with\nthe leaf alone (the previous grouped-maximize look).\n\n```tsx\ninteraction={{\n  maximize: { enable: true, keepGroupTabStrip: true },\n}}\n```\n\n## Pane switching\n\n`paneSwitching.showTabStrip` governs the top-level pane strip (every outer\npane, a group as one tab). `true` (default) always paints it; `false` hides\nit; `\"maximized\"` paints it only while a pane is maximized. Cycle / jump\nshortcuts work regardless. Clicking a tab calls `activateLeaf`, which\nswitches the maximized pane while maximized.\n\n`paneSwitching.tabStrip` themes that strip with the same tokens as\n`grouping.groupTabStrip` (`TilingGroupTabStripTheme`, `--hpt-group-tab-*`),\nresolved over `TILING_PANE_TAB_STRIP_THEME_DEFAULTS` (solid active pill).\nThe strip root is `hpt-tab-strip hpt-pane-tab-strip`. Tabs are content-width\nin a rail; they never stretch.\n\n| `tabStrip` field | Default | What it does |\n| --- | --- | --- |\n| `placement` | `\"top\"` | `\"top\"` above the viewport, `\"bottom\"` after it |\n| `height` | group-strip height (`28`) | Strip height in CSS pixels |\n| `theme` | pane-strip solid pill | Same CSS-value tokens as `groupTabStrip.theme`; omitted tokens keep the pane defaults |\n| `renderTabLabel` | tile title | `(tab) => ReactNode`; `tab` is `{ leafId, tileId, title, active, maximized, ordinal, groupId, memberCount }` |\n\nThe lab chrome (wordmark, theme picker, accent picker, content toggle)\nrenders only when `showTabStrip === true` and those lab hooks are passed\n(`onThemeChange` / `onTileAccentChange` / `showContentToggle`).\n`\"maximized\"` is the lean strip only.\n\n```tsx\ninteraction={{\n  paneSwitching: {\n    showTabStrip: \"maximized\",\n    tabStrip: {\n      placement: \"top\",\n      theme: { background: \"#0c0d10\", accent: \"rgb(252, 211, 77)\" },\n    },\n  },\n}}\n```\n\n## Features\n\n- **Drag/drop rearrange** — Hyprland-style live drag; the move commits on\n  release, resolving to swap, edge-insert, split-container-insert, or\n  group-merge (built-in strip, or a host `groupDropTargetRef` when the strip\n  is hidden).\n- **Resizable split dividers** — drag dividers, or pin a pane to a measured pixel\n  extent (static) versus ratio-distributed (flexible).\n- **Group / stack tabs** — collapse several leaves into one slot as a stacked\n  group with a tab strip; only the active member renders.\n- **Maximize** — promote any pane to fill the viewport and restore it back.\n- **Keyboard-driven focus** — directional focus, a pane switcher\n  (cycle / jump / overlay), keyboard move-mode, and master/group commands behind\n  a remappable keymap.\n- **Theming engine** — three built-in themes (`neon-terminal`, `clean-flat`,\n  `mosaic`), eight accent hues, a themeable drag state (`dragChrome`),\n  `overlayPortalContainer` for a theme-scoped drag cursor, and live theme\n  switching with no remount.\n- **Titlebar-only pane collapse** — opt-in `paneTitleBarControls.collapse`\n  pins a pane to its chrome extent; `resizeFloor` defaults to `\"chrome\"`;\n  `onPaneCollapsedChange` / `minBBoxPx` travel with the leaf.\n- **Workspaces** — several layout trees over one tile pool\n  (`TilingWorkspaceSet`): set ops, `useTilingWorkspaceSetController`,\n  `useTilingWorkspaceTabs` + native tab drop, `WORKSPACE_KEY_BINDINGS`,\n  swipe / slide-fade transition / spring-load. See Workspaces above.\n- **Held drag** — the real pane is lifted and held under the pointer; a drop\n  indicator at the exact landing rect or snap-to-slot (`dragPreview`,\n  `dragPreviewMakesRoom`).\n- **External drop** — host-reported `externalDragHover`, and `onExternalDrop`\n  claim-before-settle.\n  In set mode a `kind: \"workspace-tab\"` hover is an engine-owned drop target.\n- **Stable pane identity** — host pane content survives drag → drop → settle\n  and every other tree edit without remounting (`paneIdentity`).\n- **Persisted layout adapter** — `createPersistedTilingLayout` saves the tree\n  (localStorage by default) and heals it through `assertLayoutIntegrity` /\n  `repairLayout`.\n- **Self-healing drag recovery** — a frame-deadline backstop, an idle watchdog,\n  transient-style teardown, and a `visibilitychange` reconcile so a drag never\n  strands the tree mid-transition.\n\n## Use cases\n\nAny screen with several panes the user rearranges:\n\n- **Dashboards** — metrics panes that share one screen.\n- **IDE-like tools** — editor, preview, and terminal, rearranged live.\n- **Trading consoles** — dense, keyboard-driven panels in one viewport.\n- **Content sites** — SEO tiles — this homepage is one.\n\n## Roadmap\n\nThese are **planned** directions, not shipped. React + DOM only today.\n\n- **Framework-agnostic core** — a dependency-free vanilla TypeScript core so the\n  tiling engine runs without any framework: the layout tree, the drag/FLIP state\n  machine, and the self-healing recovery logic decoupled from React, ready to\n  drive any view layer.\n- **First-class adapters for every major framework** — React ships today;\n  planned official adapters for Vue, Svelte, Solid, Angular, and standard Web\n  Components, each a thin binding over the same vanilla core so behavior stays\n  identical across frameworks.\n- **Canvas rendering backend** — an optional canvas / GPU-accelerated render path\n  for very high pane counts and animation-heavy scenes where DOM reflow is the\n  bottleneck; the semantic DOM path stays the default and canvas is opt-in for\n  density.\n- **Rust + WebAssembly core** — porting the hot layout, drag, and geometry math\n  to a Rust → WebAssembly core for deterministic, high-frame-rate behavior,\n  unlocking more window-manager-like UX: snap zones,\n  persistent session layouts, fully keyboard-driven tiling, and\n  per-monitor-style multi-viewport arrangements.\n\n## Contributing\n\nhypr-tiling is built in the open and welcomes collaboration — framework\nadapters, rendering backends, bug reports, and ideas from the roadmap above are\nall welcome. To get involved, email\n[metelin@gmail.com](mailto:metelin@gmail.com).\n\n## Links\n\n- Homepage: <https://hypr-tiling.n-uf.com>\n- Repository: <https://github.com/n-uf/hypr-tiling>\n- Issues: <https://github.com/n-uf/hypr-tiling/issues>\n\n## License\n\nSource-available under\n[PolyForm Perimeter 1.0.1](https://polyformproject.org/licenses/perimeter/1.0.1)\n— business use allowed, but no competing product built from this software.\n","readmeFilename":"README.md"}