{"_id":"@cujuju/solidjs-anchored-popover","_rev":"2-9e3c7d2e812384466f4793cfded5b598","name":"@cujuju/solidjs-anchored-popover","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@cujuju/solidjs-anchored-popover","version":"0.1.0","keywords":["solidjs","popover","anchored","floating-ui","tooltip","menu","flyout"],"author":{"name":"Cujuju"},"license":"MIT","_id":"@cujuju/solidjs-anchored-popover@0.1.0","maintainers":[{"name":"cujuju","email":"cujuju@pm.me"}],"homepage":"https://github.com/Cujuju/solidjs-toolkit/tree/main/packages/anchored-popover","bugs":{"url":"https://github.com/Cujuju/solidjs-toolkit/issues"},"dist":{"shasum":"71a99c7c767f4eac592c8939e1472e7fb627ce14","tarball":"https://registry.npmjs.org/@cujuju/solidjs-anchored-popover/-/solidjs-anchored-popover-0.1.0.tgz","fileCount":12,"integrity":"sha512-ui0jWQxUfKla8TAJ1LsVzrgGkBS8Vs9aHZ+jG1PA2zg7ZBlJ+zSCpSbRIgNZRHFpqJ+QcWnyEmRqMhlnMzj05Q==","signatures":[{"sig":"MEQCIG896VHXWtiHzVefjryGwpuRmTNOc9gYDGjhoXrR4QchAiBua9itLIePy1rfsI95w3z+SiSDSFTcx5xBdIycIFn1ug==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":91887},"main":"./dist/index.js","type":"module","_from":"file:cujuju-solidjs-anchored-popover-0.1.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"solid":"./src/index.ts","types":"./dist/index.d.ts","import":"./dist/index.js"},"./styles.css":"./src/styles.css"},"scripts":{"test":"vitest run","build":"vite build","test:watch":"vitest"},"_npmUser":{"name":"cujuju","email":"cujuju@pm.me"},"_resolved":"C:\\Users\\shawn\\AppData\\Local\\Temp\\ca25b5fcd0eaa74cd728cc35a0127a64\\cujuju-solidjs-anchored-popover-0.1.0.tgz","_integrity":"sha512-ui0jWQxUfKla8TAJ1LsVzrgGkBS8Vs9aHZ+jG1PA2zg7ZBlJ+zSCpSbRIgNZRHFpqJ+QcWnyEmRqMhlnMzj05Q==","repository":{"url":"git+https://github.com/Cujuju/solidjs-toolkit.git","type":"git","directory":"packages/anchored-popover"},"_npmVersion":"11.12.1","description":"Anchored popover primitive for SolidJS — HTML Popover API in manual mode, 8 placements, viewport clamping, parent/child popover coordination, wireable dismiss-skip.","directories":{},"sideEffects":["**/*.css"],"_nodeVersion":"25.8.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^24.0.0","vitest":"^3.2.4","vite-plugin-solid":"^2.11.12","@cujuju/solidjs-hooks":"2.0.0","@solidjs/testing-library":"^0.8.0","@testing-library/jest-dom":"^6.9.1"},"peerDependencies":{"solid-js":">=1.7.0","@cujuju/solidjs-hooks":"^2.0.0"},"_npmOperationalInternal":{"tmp":"tmp/solidjs-anchored-popover_0.1.0_1778524277836_0.7815315281851862","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@cujuju/solidjs-anchored-popover","version":"0.1.1","description":"Anchored popover primitive for SolidJS — HTML Popover API in manual mode, 8 placements, viewport clamping, parent/child popover coordination, wireable dismiss-skip.","type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","solid":"./src/index.ts","import":"./dist/index.js"},"./styles.css":"./src/styles.css"},"sideEffects":["**/*.css"],"license":"MIT","author":{"name":"Cujuju"},"repository":{"type":"git","url":"git+https://github.com/Cujuju/solidjs-toolkit.git","directory":"packages/anchored-popover"},"homepage":"https://github.com/Cujuju/solidjs-toolkit/tree/main/packages/anchored-popover","bugs":{"url":"https://github.com/Cujuju/solidjs-toolkit/issues"},"keywords":["solidjs","popover","anchored","floating-ui","tooltip","menu","flyout"],"peerDependencies":{"solid-js":">=1.7.0","@cujuju/solidjs-hooks":"^2.0.0"},"devDependencies":{"@solidjs/testing-library":"^0.8.0","@testing-library/jest-dom":"^6.9.1","jsdom":"^24.0.0","vite-plugin-solid":"^2.11.12","vitest":"^3.2.4","@cujuju/solidjs-hooks":"^2.0.0"},"publishConfig":{"access":"public"},"scripts":{"test":"vitest run","test:watch":"vitest","build":"vite build"},"_id":"@cujuju/solidjs-anchored-popover@0.1.1","_integrity":"sha512-ANz/99LSpW65Yw8eQV8zpw4TQONLtTPVfEjX2CV8CQkNzIqfwh5X/k3Tzs2S+FIZaj/9QYHDwEiEsMwwxQTZOw==","_resolved":"/tmp/f6a7f33fd549cdef19a187d97f7c3056/cujuju-solidjs-anchored-popover-0.1.1.tgz","_from":"file:cujuju-solidjs-anchored-popover-0.1.1.tgz","_nodeVersion":"24.18.0","_npmVersion":"12.0.1","dist":{"integrity":"sha512-ANz/99LSpW65Yw8eQV8zpw4TQONLtTPVfEjX2CV8CQkNzIqfwh5X/k3Tzs2S+FIZaj/9QYHDwEiEsMwwxQTZOw==","shasum":"143d12be9ff2885ce6679de04f9263429a2c9fd1","tarball":"https://registry.npmjs.org/@cujuju/solidjs-anchored-popover/-/solidjs-anchored-popover-0.1.1.tgz","fileCount":12,"unpackedSize":91888,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCICdHTpYKnn153SdbMuBB1c+V9cTEZ2QoLBvjCZuGFxurAiEAl68gZ/ESccDB9I5LLHjPP4zfNbNN2xtEHlqTVabVINc="}]},"_npmUser":{"name":"cujuju","email":"cujuju@pm.me"},"directories":{},"maintainers":[{"name":"cujuju","email":"cujuju@pm.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/solidjs-anchored-popover_0.1.1_1784888177845_0.31580787399231136"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-11T18:31:17.688Z","modified":"2026-07-24T10:16:18.181Z","0.1.0":"2026-05-11T18:31:18.005Z","0.1.1":"2026-07-24T10:16:17.995Z"},"bugs":{"url":"https://github.com/Cujuju/solidjs-toolkit/issues"},"author":{"name":"Cujuju"},"license":"MIT","homepage":"https://github.com/Cujuju/solidjs-toolkit/tree/main/packages/anchored-popover","keywords":["solidjs","popover","anchored","floating-ui","tooltip","menu","flyout"],"repository":{"type":"git","url":"git+https://github.com/Cujuju/solidjs-toolkit.git","directory":"packages/anchored-popover"},"description":"Anchored popover primitive for SolidJS — HTML Popover API in manual mode, 8 placements, viewport clamping, parent/child popover coordination, wireable dismiss-skip.","maintainers":[{"name":"cujuju","email":"cujuju@pm.me"}],"readme":"# @cujuju/solidjs-anchored-popover\n\nAnchored popover primitive for SolidJS. Uses the HTML Popover API in manual\nmode, with a custom outside-click dismiss that excludes the anchor from\n\"outside\" — so clicking the trigger toggles cleanly without racing the UA's\nlight-dismiss handler.\n\n## Install\n\n```sh\npnpm add @cujuju/solidjs-anchored-popover @cujuju/solidjs-hooks\n```\n\nPeer dependencies: `solid-js >= 1.7.0`, `@cujuju/solidjs-hooks ^2.0.0`.\n\n## Usage\n\n```tsx\nimport { createSignal } from 'solid-js';\nimport AnchoredPopover from '@cujuju/solidjs-anchored-popover';\n\nfunction Example() {\n  const [open, setOpen] = createSignal(false);\n  const [anchor, setAnchor] = createSignal<HTMLButtonElement>();\n\n  return (\n    <>\n      <button ref={setAnchor} onClick={() => setOpen((o) => !o)}>\n        Open\n      </button>\n      <AnchoredPopover\n        open={open}\n        anchor={anchor}\n        onDismiss={() => setOpen(false)}\n        placement=\"below-start\"\n        class=\"my-popover\"\n        role=\"menu\"\n        aria-label=\"My menu\"\n      >\n        <div>Menu items go here</div>\n      </AnchoredPopover>\n    </>\n  );\n}\n```\n\n## Props\n\n| Prop | Type | Description |\n|---|---|---|\n| `open` | `Accessor<boolean>` | Reactive open state. |\n| `anchor` | `Accessor<HTMLElement \\| null \\| undefined>` | Element to anchor against. Excluded from outside-click dismiss. |\n| `onDismiss` | `() => void` | Fires on outside pointerdown or Escape. |\n| `placement` | `AnchoredPlacement` | One of `below-start`, `below-end`, `above-start`, `above-end`, `right-start`, `right-end`, `left-start`, `left-end`. Default `below-start`. |\n| `offsetPx` | `number` | Gap between anchor and popover edge. Default 4. |\n| `viewportMarginPx` | `number` | Min gap between popover and viewport edge after clamp. Default 8. |\n| `class` | `string` | Class applied to the content element. |\n| `role` | `string` | ARIA role on the content element. |\n| `aria-label` | `string` | ARIA label on the content element. |\n| `id` | `string` | id on the content element. |\n| `shellClass` | `string` | Class applied to the SHELL (the `[popover]` element). For `::backdrop` styles only — do NOT use for layout. |\n| `shellStyle` | `Accessor<Record<string, string>>` | Inline styles applied to the shell. Useful for CSS vars that need shell scope. Diff-cleared on key removal. |\n| `centered` | `boolean` | Center popover horizontally in viewport (vertical placements only). |\n| `horizontalAnchor` | `Accessor<HTMLElement>` | Secondary anchor for the side axis (right/left placements). Excluded from dismiss too. |\n| `parentPopoverRef` | `Accessor<HTMLElement>` | Parent popover to re-promote after our show (for nested popovers). |\n| `shouldSuppressDismiss` | `(target: Element) => boolean` | Predicate consulted on every outside click. Return true to suppress dismiss (e.g. for Portal'd nested popovers). |\n\n## Two-element shape\n\nThe popover renders as a SHELL (`[popover=\"manual\"]`, no author class) wrapping\na CONTENT element (carries `class`, `role`, `aria-label`, `id`). This separation\nis load-bearing: the UA's `[popover]:not(:popover-open) { display: none }`\nrule wins on the shell because no author CSS competes. An author class on the\nshell with `display: flex` would defeat closed-state hiding (the cascade trap).\n\nPass `shellClass` only for `::backdrop` styles and shell-scoped CSS variables.\n\n## Nested popovers (parent/child)\n\nFor a popover hosted inside another popover (e.g. a submenu inside a menu, or\na side panel that lives inside an outer flyout), wire the relationship:\n\n```tsx\n<AnchoredPopover\n  open={subOpen}\n  anchor={triggerRow}\n  horizontalAnchor={parentPanelEl}\n  parentPopoverRef={parentShellEl}\n  placement=\"right-start\"\n  offsetPx={-3}   // negative under-tucks the child under the parent's edge\n  shouldSuppressDismiss={(t) => !!t.closest('[data-my-popover-stack]')}\n>\n  ...\n</AnchoredPopover>\n```\n\n`shouldSuppressDismiss` handles dismiss coordination across sibling Portal'd\nsurfaces — when the user clicks something logically owned by another popover\nbut Portal'd elsewhere in the DOM tree.\n\n## License\n\nMIT\n","readmeFilename":"README.md"}