npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@get-set/gs-popover

v1.0.2

Published

Get-Set Popover

Readme

@get-set/gs-popover

A rich, accessible, beautifully animated popover — usable four ways from the exact same core:

  1. window.GSPopover(selectorOrElement, params) — the native factory
  2. $(selector).GSPopover(params) — the jQuery plugin
  3. element.GSPopover(params) — the HTMLElement.prototype method
  4. <GSPopover>…</GSPopover> — the React component (with a typed ref handle)

All four targets share one positioning engine, one animation catalog, one set of constants / helpers / types, and one stylesheet, so behavior is identical no matter how you mount it.


Features

  • 12 placements (top/bottom/left/right × -start/center/-end) plus auto, with flip and shift middleware that keeps the popover in the viewport.
  • 4 trigger modesclick, hover (interactive), focus, manual, with configurable open/close delays.
  • Animation catalog — fade, scale/zoom, slide (4 directions), flip, shift-away, shift-toward, perspective, blur, bounce (respects prefers-reduced-motion).
  • Arrow that points at the trigger, header / title, body, footer, and an optional × close button.
  • Dismissal — outside-click and Esc (each independently toggleable), in-content close handlers.
  • Focus management — optional focus trap, autofocus, explicit initial focus, and focus return to the trigger on close.
  • Theminglight / dark / auto, accent color, RTL, sameWidth (match the trigger width), maxWidth / minWidth, per-part class overrides.
  • Optional backdrop with color + blur.
  • Accessiblerole, aria-haspopup, aria-expanded, aria-labelledby, tabindex, keyboard support.
  • React-only gsx — per-instance scoped styles injected on mount and removed on unmount.
  • Zero runtime dependencies; React + ReactDOM are optional peers.

Compatibility

| Target | Entry | | ----------------- | ---------------------------------- | | Browser / <script> / jQuery / prototype | dist-js/bundle.js (UMD-ish window.GSPopover) | | Bundler import | dist/components/GSPopover.js (React) | | Bundler require | dist-js/bundle.js (native) | | Types | dist/components/GSPopover.d.ts |

React is an optional peer (^16.8 || ^17 || ^18 || ^19). The native targets work with no framework at all.


Project layout

GSPopover.ts              native factory + window.GSPopoverConfigue registry
components/GSPopover.tsx   React component (forwardRef + handle + gsx)
actions/                  init / open / close / destroy / refresh / animate / focusTrap
helpers/                  position (flip/shift) / layout / content / uihelpers
constants/                placements / animations / defaultParams
types/                    params / ref / global.d.ts
styles/                   GSPopover.css + .scss
components/styles/         GSPopover.css + .scss + GSPopoverCSS.ts (inlined)
example.html              native showcase

Install

npm i @get-set/gs-popover

Build & test

npm install
npm run build      # build:js (webpack bundle) + build:react (tsc)
npm test           # vitest (logic + native + React)

npm run build produces:

  • dist-js/bundle.js — the native bundle. A webpack BannerPlugin appends an IIFE that registers $.fn.GSPopover (when jQuery is present) and HTMLElement.prototype.GSPopover.
  • dist/ — the React component + shared modules compiled with type declarations.

Usage — Native JS

<link rel="stylesheet" href="node_modules/@get-set/gs-popover/styles/GSPopover.css" />
<script src="node_modules/@get-set/gs-popover/dist-js/bundle.js"></script>

<button id="help">Help</button>
<div id="tip" hidden>The quick brown fox.</div>

<script>
  // The factory accepts a CSS SELECTOR STRING …
  const pop = GSPopover('#tip', {
    reference: 'tip',
    trigger: '#help',
    placement: 'bottom',
    title: 'Quick help',
    closeButton: true,
    animation: 'scale'
  });

  // … OR a DOM ELEMENT / collection as the first argument.
  const el = document.getElementById('tip');
  GSPopover(el, { trigger: '#help' });

  pop.openPopover();
  pop.closePopover();
  pop.toggle();
</script>

Selector or element. The first argument may be a CSS selector string or an HTMLElement. This matters because the jQuery and prototype adapters call the factory with an element — a selector-only factory would silently break them.

Instance methods (registry)

Every native instance is registered in window.GSPopoverConfigue keyed by its reference:

const pop = window.GSPopoverConfigue.instance('tip');
pop.openPopover();
pop.getPlacement(); // 'bottom' (or the flipped side)
pop.update();       // recompute position against the trigger
pop.destroy();      // tear down + free the slot

Usage — jQuery

Loading the bundle after jQuery registers $.fn.GSPopover:

<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script src="node_modules/@get-set/gs-popover/dist-js/bundle.js"></script>

<script>
  $('#tip').GSPopover({
    trigger: '#help',
    placement: 'top-start',
    animation: 'slide-up'
  });
</script>

$(sel).GSPopover(params) calls new window.GSPopover(thisElement, params) for every matched element.


Usage — Prototype

The bundle also adds HTMLElement.prototype.GSPopover:

document.querySelector('#tip').GSPopover({
  trigger: '#help',
  trigger_mode: 'hover'
});

Usage — React

The component wraps a trigger child. The popover renders into a document.body portal when open.

import { useRef } from 'react';
import GSPopover, { GSPopoverHandle } from '@get-set/gs-popover';
import '@get-set/gs-popover/styles/GSPopover.css';

function Example() {
  const ref = useRef<GSPopoverHandle>(null);

  return (
    <GSPopover
      ref={ref}
      placement="bottom"
      triggerMode="click"
      title="Quick help"
      closeButton
      animation="scale"
      theme="auto"
      body={<p>The quick brown fox jumps over the lazy dog.</p>}
      onPlacement={(p) => console.log('resolved', p)}>
      <button>Help</button>
    </GSPopover>
  );
}
  • The single child element becomes the trigger + anchor (it is cloned with a ref). Pass an explicit trigger (selector / element / ref) to anchor elsewhere.
  • Body content can be supplied as the body prop (React nodes) or the content prop (HTML string).
  • Controlled: pass open. Uncontrolled: use defaultOpen and/or the ref handle.

gsx — scoped styles (React-only)

<GSPopover
  reference="fancy"
  gsx={{ '.gs-popover': { borderRadius: '16px' }, '.gs-popover-title': { color: 'crimson' } }}>
  <button>Open</button>
</GSPopover>

gsx is injected as a <style data-key="…"> scoped to that instance via [data-key='…'] and removed automatically on unmount.


Options / props

The same options work in native params and React props (React additionally accepts triggerMode as an alias of trigger_mode, the body node prop, and gsx).

| Name | Type | Default | Description | | ---- | ---- | ------- | ----------- | | reference | string | auto GUID | Stable key used by the registry. | | trigger | string \| HTMLElement \| RefObject | wrapped child (React) | Anchor / trigger element(s). | | trigger_mode / triggerMode | 'click' \| 'hover' \| 'focus' \| 'manual' | 'click' | How the popover opens. | | closeHandler | string \| HTMLElement \| RefObject | — | In-content element(s) that close on click. | | placement | GSPopoverPlacement | 'bottom' | One of the 12 placements or 'auto'. | | flip | boolean | true | Flip to the opposite side when there is no room. | | shift | boolean | true | Shift along the cross axis to stay in view. | | offset | number \| { main?: number; cross?: number } | 8 | Distance from the trigger. | | boundaryPadding | number | 8 | Viewport padding kept while flipping/shifting. | | sameWidth | boolean | false | Match the popover width to the trigger. | | reposition | boolean | true | Keep positioned on scroll / resize. | | openDelay | number | 0 | Delay (ms) before opening on hover/focus. | | closeDelay | number | 100 | Delay (ms) before closing on hover-leave/blur. | | interactive | boolean | true | Stay open while the pointer is over the popover (hover mode). | | title | string | — | Header title (escaped). Renders the header. | | header | string | — | Full header HTML (overrides title). | | content | string | — | Body HTML string (native; React uses body/children). | | body (React) | ReactNode | — | Body content as React nodes. | | footer | string \| false | — | Footer HTML. false = no footer. | | arrow | boolean | true | Show the arrow pointing at the trigger. | | closeButton | boolean | false | Show the built-in × close button. | | maxWidth | number \| string | 320 | Clamp the popover width. | | minWidth | number \| string | — | Lower bound on the width. | | dismissOnOutsideClick | boolean | true | Close on outside click. | | dismissOnEsc | boolean | true | Close on Escape. | | animation | GSPopoverAnimation \| false | 'scale' | Entrance animation (false disables motion). | | exitAnimation | GSPopoverAnimation \| false | mirrors animation | Separate exit animation. | | animationDuration | number \| { enter?: number; exit?: number } | 200 | Duration(s) in ms. | | animationEasing | string | cubic-bezier(.16,1,.3,1) | Easing for enter/exit. | | reducedMotion | 'auto' \| boolean | 'auto' | Honor prefers-reduced-motion. | | backdrop | boolean | false | Render a dimming backdrop behind the popover. | | backdropColor | string | — | Backdrop color. | | backdropBlur | boolean \| number \| string | false | Backdrop blur (true=4px). | | trapFocus | boolean | false | Trap Tab focus inside the popover. | | autofocus | boolean | false | Auto-focus the first focusable element on open. | | initialFocus | string \| HTMLElement \| RefObject \| false | — | Explicit element to focus (false = the container). | | returnFocus | boolean | true | Restore focus to the trigger on close. | | theme | 'light' \| 'dark' \| 'auto' | 'auto' | Visual theme. | | accentColor | string | — | Accent color (CSS var --gsp-accent). | | rtl | boolean | false | Right-to-left layout. | | customClass | GSPopoverCustomClass | — | Per-part class overrides. | | className | string | — | Extra class on the popover root. | | role | string | 'dialog' | ARIA role for the popover. | | gsx (React) | NestedCSS | — | Per-instance scoped styles. | | open (React) | boolean | — | Controlled open state. | | defaultOpen (React) | boolean | false | Uncontrolled initial open state. | | beforeOpen | () => void \| boolean | — | Return false to cancel opening. | | afterOpen | () => void | — | Fired after the open transition. | | beforeClose | (reason?) => void \| boolean | — | Return false to cancel closing. | | afterClose | (reason?) => void | — | Fired after the popover fully closes. | | onOpen (React) | () => void | — | Open callback. | | onClose (React) | (reason?) => void | — | Close callback. | | onPlacement | (placement) => void | — | Fired after each reposition with the resolved placement. |

GSPopoverCustomClass parts

popover, arrow, header, title, closeButton, body, footer, backdrop.


Variant catalogs

Placement catalog

auto, top, top-start, top-end, bottom, bottom-start, bottom-end, left, left-start, left-end, right, right-start, right-end.

auto chooses the side with the most available space. With flip enabled (the default), any placement that overflows is flipped to its opposite side when that side has more room; shift then nudges the popover along the cross axis to stay inside boundaryPadding.

Animation catalog

| Name | Effect | | ---- | ------ | | fade | Opacity only. | | scale / zoom | Scale from 0.9 + fade (aliases). | | slide / slide-up | Rise + fade (aliases). | | slide-down | Drop + fade. | | slide-left | Slide in from the right + fade. | | slide-right | Slide in from the left + fade. | | flip | 3D rotateX hinge + scale. | | shift-away | Scale up slightly on exit. | | shift-toward | Scale down slightly on exit. | | perspective | Z-depth tilt. | | blur | Blur + scale + fade. | | bounce | Springy overshoot. | | none | No-op (also the reduced-motion fallback). |

animation: false disables motion entirely. Set exitAnimation for a different exit, and animationDuration / animationEasing to tune timing.

Trigger-mode catalog

| Mode | Behavior | | ---- | -------- | | click | Toggle on trigger click; dismiss on outside click / Esc. | | hover | Open on mouseenter/focus, close on leave/blur (interactive). | | focus | Open on focus, close on blur. | | manual | Wires nothing — you drive open/close via the API/handle. |

Theme catalog

| Theme | Behavior | | ----- | -------- | | light | Forces the light palette. | | dark | Forces the dark palette. | | auto | Follows prefers-color-scheme. |


Imperative API

React GSPopoverHandle (via ref)

| Method | Description | | ------ | ----------- | | open() | Open the popover. | | close(reason?) | Close the popover (optional dismissal reason). | | toggle() | Toggle the open state. | | isOpen() | boolean — current open state. | | setContent(node) | Replace the body content (React node). | | update() | Reposition against the trigger. | | getPlacement() | The currently-resolved placement (after any flip). | | destroy() | Close + unregister the instance. |

Native instance (returned by the factory)

| Method | Description | | ------ | ----------- | | openPopover() | Open the popover. | | closePopover(reason?) | Close the popover. | | toggle() | Toggle the open state. | | isOpen() | boolean — current open state. | | update() | Reposition against the trigger. | | getPlacement() | The currently-resolved placement. | | setContent(content) | Replace the body (HTML string or element). | | refresh() | Rebuild from (possibly updated) params. | | destroy() | Tear down listeners + DOM and free the registry slot. |

Registry — window.GSPopoverConfigue

window.GSPopoverConfigue.references; // Array<{ key, ref }>
window.GSPopoverConfigue.instance(key); // -> ref | undefined

Both the native factory and the React component register here, so instance(reference) resolves an instance created either way.


Dismissal reasons

close callbacks receive one of: 'outside', 'esc', 'close-button', 'trigger', 'reference-hidden', 'manual'.


License

ISC © Get-Set