{"_id":"@affino/popover-core","_rev":"2-321108d3c6ead2c0b2ca8762f8edde19","name":"@affino/popover-core","dist-tags":{"latest":"1.1.0"},"versions":{"1.0.0":{"name":"@affino/popover-core","version":"1.0.0","keywords":["popover","headless","surface","controller","ui-core"],"author":{"name":"Anton Pavlov","email":"a.pavlov@affino.dev"},"license":"MIT","_id":"@affino/popover-core@1.0.0","maintainers":[{"name":"affino","email":"anton.pavlov.personal@gmail.com"}],"homepage":"https://affino.dev","bugs":{"url":"https://github.com/affinio/affinio/issues"},"dist":{"shasum":"05fddef248050369a3a5c0268ad3bb51193a3b00","tarball":"https://registry.npmjs.org/@affino/popover-core/-/popover-core-1.0.0.tgz","fileCount":12,"integrity":"sha512-bPOVpRZ2DajkrDw8lXw+8gOx7SvwjHpCdKlz74eKJtG7LNDlm/wwTG5mC3xA57KsRS9SwEnX8N0CJi2q4GfQLQ==","signatures":[{"sig":"MEUCIQDfTDpF5x2G7KOxBWCzCPliq/M7VMvK5h79v8cj4akdYwIgAl+m7NBQH3OQUwUvxgSgJL09nW4c4E5c7M2GXl9MikU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":18096},"main":"dist/index.js","type":"module","_from":"file:affino-popover-core-1.0.0.tgz","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"test":"vitest run","build":"tsc -p tsconfig.json"},"_npmUser":{"name":"affino","email":"anton.pavlov.personal@gmail.com"},"_resolved":"/tmp/8d018f74198284b7791a9ba5b155e2bd/affino-popover-core-1.0.0.tgz","_integrity":"sha512-bPOVpRZ2DajkrDw8lXw+8gOx7SvwjHpCdKlz74eKJtG7LNDlm/wwTG5mC3xA57KsRS9SwEnX8N0CJi2q4GfQLQ==","repository":{"url":"git+https://github.com/affinio/affinio.git#main","type":"git"},"_npmVersion":"10.8.2","description":"Headless popover controller powered by @affino/surface-core","directories":{},"sideEffects":false,"_nodeVersion":"20.19.6","dependencies":{"@affino/surface-core":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.0.15","@vitest/coverage-v8":"^4.0.15"},"_npmOperationalInternal":{"tmp":"tmp/popover-core_1.0.0_1769943391484_0.11100342033482469","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@affino/popover-core","version":"1.1.0","author":{"name":"Anton Pavlov","email":"a.pavlov@affino.dev"},"type":"module","description":"Headless popover controller powered by @affino/surface-core","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"main":"dist/index.js","types":"dist/index.d.ts","sideEffects":false,"repository":{"type":"git","url":"git+https://github.com/affinio/affinio.git#main"},"homepage":"https://affino.dev","keywords":["popover","headless","surface","controller","ui-core"],"license":"MIT","dependencies":{"@affino/surface-core":"^1.1.0","@affino/overlay-kernel":"^0.2.0"},"devDependencies":{"@vitest/coverage-v8":"^4.0.15","vitest":"^4.0.15"},"bugs":{"url":"https://github.com/affinio/affinio/issues"},"module":"dist/index.js","scripts":{"build":"tsc -p tsconfig.json","test":"vitest run"},"_id":"@affino/popover-core@1.1.0","_integrity":"sha512-cURD9EpEKijS+IUWtQ+boKo2k9FAmcmMmdmNCV2UcLbKAtAWyX2YhEZvpnjdIqUekHut4xN+n7YOeTNNfzQmjQ==","_resolved":"/tmp/25f2ec362c19706a0c493baf1862a4dd/affino-popover-core-1.1.0.tgz","_from":"file:affino-popover-core-1.1.0.tgz","_nodeVersion":"20.20.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-cURD9EpEKijS+IUWtQ+boKo2k9FAmcmMmdmNCV2UcLbKAtAWyX2YhEZvpnjdIqUekHut4xN+n7YOeTNNfzQmjQ==","shasum":"753fabdd78cf5413957b3004e8245db064c650c0","tarball":"https://registry.npmjs.org/@affino/popover-core/-/popover-core-1.1.0.tgz","fileCount":12,"unpackedSize":27849,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDmU3xHvXhjBFvisTfksG3CN4WgiZKDjwvx2y8HKNXDLwIhAInmftfbN2OqtwnUTGE5sURVFYhMmBOEozI2j9ELHgu2"}]},"_npmUser":{"name":"affino","email":"anton.pavlov.personal@gmail.com"},"directories":{},"maintainers":[{"name":"affino","email":"anton.pavlov.personal@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/popover-core_1.1.0_1771104593650_0.18131336668639597"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-01T10:56:31.328Z","modified":"2026-02-14T21:29:53.912Z","1.0.0":"2026-02-01T10:56:31.638Z","1.1.0":"2026-02-14T21:29:53.791Z"},"bugs":{"url":"https://github.com/affinio/affinio/issues"},"author":{"name":"Anton Pavlov","email":"a.pavlov@affino.dev"},"license":"MIT","homepage":"https://affino.dev","keywords":["popover","headless","surface","controller","ui-core"],"repository":{"type":"git","url":"git+https://github.com/affinio/affinio.git#main"},"description":"Headless popover controller powered by @affino/surface-core","maintainers":[{"name":"affino","email":"anton.pavlov.personal@gmail.com"}],"readme":"# @affino/popover-core\n\nHeadless popover controller built on top of `@affino/surface-core`. It keeps ARIA wiring, toggle semantics, and positioning helpers in sync with the rest of the Affino floating surfaces so adapters can stay tiny.\n\n## Highlights\n\n- Deterministic open / close orchestration with shared surface timers\n- Trigger + content prop helpers for instant ARIA wiring\n- Optional modal mode and escape / interact-outside guards\n- Optional integration with `@affino/overlay-kernel` so Escape / pointer closes respect global stacking rules\n- Arrow + positioning helpers that reuse `computePosition()`\n\n## Install\n\n```bash\npnpm add @affino/popover-core\n# or\nyarn add @affino/popover-core\n# or\nnpm install @affino/popover-core\n```\n\n## Usage\n\n```ts\nimport { PopoverCore } from \"@affino/popover-core\"\n\nconst popover = new PopoverCore({ id: \"filters\", closeOnEscape: true })\n\nconst triggerProps = popover.getTriggerProps()\nconst panelProps = popover.getContentProps({ role: \"dialog\" })\n\nbuttonEl.addEventListener(\"click\", triggerProps.onClick!)\npanelEl.addEventListener(\"keydown\", panelProps.onKeyDown!)\n\npopover.open()\n```\n\n- Trigger props already expose `aria-haspopup`, `aria-expanded`, and `aria-controls` so DOM stays declarative.\n- Content props include `role`, `aria-modal`, and Escape handling.\n- Call `popover.computePosition(anchorRect, panelRect)` anytime layout shifts.\n- Use `popover.getArrowProps({ anchorRect, popoverRect, position })` to align decorative arrows.\n\n## API\n\n### `new PopoverCore(options?, callbacks?)`\n\n| Option | Type | Default | Description |\n| --- | --- | --- | --- |\n| `id` | `string` | auto | Stable identifier forwarded to trigger/content ids |\n| `role` | `'dialog' | 'menu' | 'listbox' | 'tree' | 'grid'` | `dialog` | Controls `aria-haspopup` + content role |\n| `modal` | `boolean` | `false` | Toggles `aria-modal=\"true\"` and lets adapters apply scroll locking |\n| `closeOnEscape` | `boolean` | `true` | Close the surface when Escape fires from trigger or panel |\n| `closeOnInteractOutside` | `boolean` | `true` | Let adapters close when pointer / focus leaves the surface |\n| `overlayKind` | `OverlayKind` | `\"popover\"` | Overlay kind forwarded to `@affino/overlay-kernel` for stack semantics |\n| `overlayManager` | `OverlayManager` | `undefined` | Inject a kernel instance so pointer / Escape closes are mediated by the stack |\n| `getOverlayManager` | `() => OverlayManager \\| null \\| undefined` | `undefined` | Lazy resolver for the same manager, handy when adapters own the instance |\n| `overlayEntryTraits` | `PopoverOverlayTraits` | `{}` | Override owner / modal / priority traits forwarded to the kernel |\n| `openDelay` / `closeDelay` | `number` | `80 / 150` | Forwarded to the shared surface timers |\n\nCallbacks mirror `SurfaceCallbacks` and add `onInteractOutside(event)` so analytics hooks can observe outside clicks before the controller closes.\n\n### Trigger helpers\n\n```ts\nconst triggerProps = popover.getTriggerProps({ type: \"button\" })\n```\n\nReturns:\n\n- `id`, `aria-haspopup`, `aria-controls`, `aria-expanded`\n- `onClick` (toggles the surface)\n- `onKeyDown` (Space/Enter toggle, Escape closes)\n\n### Content helpers\n\n```ts\nconst panelProps = popover.getContentProps({ role: \"dialog\", tabIndex: -1 })\n```\n\nReturns:\n\n- `id`, `role`, `aria-modal`, `tabIndex`, `data-state`\n- `onKeyDown` (Escape closes when enabled)\n\n### Arrow helper\n\n```ts\nconst arrow = popover.getArrowProps({ anchorRect, popoverRect, position, options: { size: 12 } })\n```\n\nJust like tooltips, this helper outputs `data-placement`, `data-align`, and inline styles so CSS can stay declarative.\n\n## Adapter guidance\n\n- Pair with `@affino/overlay-host` to teleport panels into a managed stacking context.\n- Close on outside pointer / focus targets when `popover.shouldCloseOnInteractOutside()` returns `true`.\n- When `popover.isModal()` is `true`, lock scroll using `createScrollLockController()` from the overlay host package.\n\n```ts\nif (popover.shouldCloseOnInteractOutside() && !panel.contains(event.target)) {\n  popover.interactOutside({ event, target: event.target })\n}\n```\n\nThe controller stays DOM-agnostic so it can power Vue, React, or vanilla adapters from the same package.\n","readmeFilename":"README.md"}