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

airport-one-widgets

v0.2.38

Published

**Integration guide (v2 embed, domains, telemetry, troubleshooting):** [`docs/widget-embed-integration.md`](../../docs/widget-embed-integration.md) (repository root). **Plan your trip rollout/canary checklist:** [`docs/find-your-flight-rollout-checklist.m

Readme

Airport One Widgets

Integration guide (v2 embed, domains, telemetry, troubleshooting): docs/widget-embed-integration.md (repository root). Plan your trip rollout/canary checklist: docs/find-your-flight-rollout-checklist.md.

Fly My Airport FAB local demos: with the widgets dev server running, open /demo/fly-my-airport-fab.html (see root index.html for the full demo menu).

Airfare Search (v2)

The v2 airfare-search widget is an explicit opt-in contract and does not alias from the v1 flight-search-form tag.

Installation

<script src="https://widgets.flymyairport.com"></script>

Usage

<fma-airfare-search
  data-widget-instance-id="YOUR_INSTANCE_UUID"
></fma-airfare-search>

Required for managed instances:

  • data-widget-instance-id

Airfare Content

Core Purpose:

  • Displays a grid of featured flight deals from a specified origin airport
  • Renders within a Shadow DOM for style isolation and encapsulation
  • Serves as a reusable widget that can be embedded in different contexts

Installation

To include the airfare-content custom element in your project, add the following script tag to your HTML file:

<script src="https://widgets.flymyairport.com"></script>

Usage

To use the fma-airfare-content custom element, simply add the following HTML tag to your markup:

<fma-airfare-content></fma-airfare-content>

Portal-managed instance (v2)

For embeds copied from the Airport One portal, bind the host element to a saved widget instance. At build time, set VITE_WIDGET_PUBLIC_CONFIG_API_BASE_URL to the public widget config API origin (no trailing slash), e.g. the Cloud Run widget-api service that serves GET /v1/widget-instances/{id}/config. The runtime then loads portal-managed defaults from that endpoint.

Instance id on the element (in order):

  1. data-widget-instance-id — preferred; matches portal snippets.
  2. HTML id — if the data attribute is missing or whitespace-only, the trimmed id property is used (ensure it is unique on the page).

Changing either value triggers a new fetch and re-render. Explicit attributes on the element always override values from the public config API and from window.__A1_WIDGET_CONFIG__.

Example:

<fma-airfare-content
  data-widget-instance-id="YOUR_INSTANCE_UUID"
></fma-airfare-content>

The embedding origin must be allowlisted for that instance (see widget-api CORS / embed allowlists). If the API base env var is unset, the script skips the fetch and behaves like a legacy attribute-only embed.

You can customize the behavior and appearance of the element by setting its attributes. The available attributes are listed in the table below:

| Attribute | Type | Default | Description | | ----------------------- | ------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------- | | origin | string | null | The origin airport code | | primary-color | string | #0B89FF | The primary color of the form | | secondary-color | string | #0B89FF | The secondary color of the form | | primary-hover-color | string | — | Primary color on hover (hex). When unset, falls back to primary. | | secondary-hover-color | string | — | Secondary color on hover, e.g. price text (hex). When unset, falls back to secondary. | | destinations | string | null | A comma-separated list of destination codes | | theme | string | light | The theme of the widget - "light" or "dark" | | consent-advertising | string | true | Dynamically turn off/on consent for Advertising - pass "true" or "false" | | consent-analytics | string | true | Dynamically turn off/on consent for Analytics - pass "true" or "false" | | consent-functional | string | true | Dynamically turn off/on consent for Functional - pass "true" or "false" | | data-widget-instance-id | string | — | Portal instance UUID; loads public config when VITE_WIDGET_PUBLIC_CONFIG_API_BASE_URL is set (preferred over id for this purpose). | | id | string | — | Fallback instance id when data-widget-instance-id is absent/empty; must be unique in the document. |

Examples

For example, to set the origin and destination airports, you can use the following markup:

<fma-airfare-content
  origin="ECP"
  destinations="aus,ind"
  primary-color="#0D67BD"
  secondary-color="#e47b26"
></fma-airfare-content>

Consent Management

How to dynamically manage user consent preferences and pass them into the widget

There are two consent categories that can optionally be turned off/on via DOM manipulation and modifying attributes on the widget.

<fma-airfare-content
  origin="ECP"
  primary-color="#0D67BD"
  secondary-color="#e47b26"
></fma-airfare-content>

...

// Call a similar function via your CMP integration to pass in the consent values for Analytics or Advertising
function changeConsent(consentAdvertising, consentAnalytics) {
  // Select the flightWidget element
  var flightWidget = document.getElementsByTagName('fma-airfare-content');

  // Set user's advertising consent from CMP
  flightWidget.setAttribute('consentAdvertising', consentAdvertising); // consentAdvertising param should be a string of "true" or "false"

  // Set user's analytics consent from CMP
  flightWidget.setAttribute('consentAnalytics', 'true') // consentAnalytics param should be a string of "true" or "false"
}

Styling

CSS Parts

The widget uses Shadow DOM for style isolation and provides CSS parts for customization. You can style the widget using the ::part() pseudo-element selector.

Available Parts

| Part Name | Description | | --------------------------------- | -------------------------------------------------------------------------------- | | airfare-content-container | The main container that holds all flight items | | airfare-content-item | Individual flight destination items | | airfare-content-item-disclaimer | The real-time pricing / “Powered by KAYAK” disclaimer below the destination grid |

Styling Examples

/* Style the main container */
fma-airfare-content::part(airfare-content-container) {
  background-color: #f8f9fa;
  border-radius: 8px;
  padding: 16px;
}

/* Style individual flight items */
fma-airfare-content::part(airfare-content-item) {
  text-align: center;
}

fma-airfare-content::part(airfare-content-item):hover {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  transform: translateY(-2px);
}

/* Style the pricing disclaimer */
fma-airfare-content::part(airfare-content-item-disclaimer) {
  font-size: 0.75rem;
  margin-top: 1rem;
}

Carfare Search

Core Purpose:

  • Renders a responsive car rental search form (pick-up/drop-off, dates, time)
  • Supports same-location and different-location drop-off
  • Redirects to FlyMyAirport Cars with the correct query string
  • Encapsulated via Shadow DOM; theme colors configurable

Installation

Use the same script loader as other widgets:

<script src="https://widgets.flymyairport.com"></script>

Usage

Add the fma-carfare-search custom element to your page. If you don't pass an origin, it will default to window.__A1_WIDGET_CONFIG__.iata when present, or to the instance iata from the public config API when data-widget-instance-id / id is set and VITE_WIDGET_PUBLIC_CONFIG_API_BASE_URL is configured (same contract as airfare).

<!-- Minimal -->
<fma-carfare-search></fma-carfare-search>

<!-- With explicit origin and theme -->
<fma-carfare-search origin="FAT" theme="light"></fma-carfare-search>

Available attributes:

| Attribute | Type | Default | Description | | ----------------------- | ------- | ---------------- | ------------------------------------------------------------------------------ | | origin | string | from global | Origin IATA (3 letters). Falls back to window.__A1_WIDGET_CONFIG__.iata. | | primary-color | string | #0B89FF or cfg | Primary theme color (CSS color). | | secondary-color | string | #0B89FF or cfg | Secondary theme color (CSS color). | | theme | string | light | light or dark. | | consent-advertising | boolean | true | Enable/disable Advertising consent within the widget. | | consent-analytics | boolean | true | Enable/disable Analytics consent within the widget. | | consent-functional | boolean | true | Enable/disable Functional consent within the widget. | | data-widget-instance-id | string | — | Portal instance UUID; loads public config when the widget-api base env is set. | | id | string | — | Fallback instance id when the data attribute is absent/empty. |

Examples

<!-- Set colors and origin -->
<fma-carfare-search
  origin="ATW"
  primary-color="#0D67BD"
  secondary-color="#E47B26"
  theme="dark"
></fma-carfare-search>

<!-- Toggle drop-off to a different location in the UI, pick dates & search -->

When the user clicks Search, the widget redirects to:

https://flymyairport.com/from/{fromAirport}/cars?fromAirport={FROM}&toAirport={TO}&tripOption={same-location|different-location}&fromDateTime=YYYY-MM-DDTHH:mm&toDateTime=YYYY-MM-DDTHH:mm

Example redirect from FAT, same-location, 2025-10-01 12:00 → 2025-10-02 12:00:

https://flymyairport.com/from/FAT/cars?fromAirport=FAT&toAirport=FAT&tripOption=same-location&fromDateTime=2025-10-01T12%3A00&toDateTime=2025-10-02T12%3A00

Date/time format and encoding

  • Times are interpreted as local to the pick-up location unless your integration adds its own timezone handling. Pass values without an offset, e.g., 2025-10-01T12:00.
  • Always URL‑encode parameter values. Prefer constructing the query with URLSearchParams to avoid encoding mistakes.
const fromAirport = 'FAT';
const toAirport = 'FAT';
const params = new URLSearchParams({
  fromAirport,
  toAirport,
  tripOption: 'same-location',
  fromDateTime: '2025-10-01T12:00',
  toDateTime: '2025-10-02T12:00',
});
const url = `https://flymyairport.com/from/${encodeURIComponent(fromAirport)}/cars?${params.toString()}`;

Note: The /from/{fromAirport} path segment and the fromAirport query parameter must match. Always keep them in sync.

Consent Management

You can dynamically set consent attributes (kebab-case) on the element at runtime from your CMP integration.

<fma-carfare-search id="carfare-widget" origin="FAT"></fma-carfare-search>

<script>
  function applyConsent({ advertising, analytics, functional }) {
    const el = document.querySelector('#carfare-widget');
    if (!el) return;
    el.setAttribute('consent-advertising', String(!!advertising));
    el.setAttribute('consent-analytics', String(!!analytics));
    el.setAttribute('consent-functional', String(!!functional));
  }

  // Example usage
  applyConsent({ advertising: true, analytics: true, functional: true });
</script>

Consent attributes accept the strings "true" or "false". The widget parses these string values; do not rely on attribute presence/absence semantics for these flags.

Styling

This widget exposes a CSS part for outer layout and two CSS variables for colors. Colors are also applied internally via Tailwind classes.

Available CSS parts:

| Part Name | Description | | -------------------------- | ----------------------------------------- | | carfare-search-container | Wraps the entire car search form and CTA. |

CSS variables (set on the host):

  • --color-primary
  • --color-secondary

Examples:

/* Customize surface/background */
fma-carfare-search::part(carfare-search-container) {
  background: #f8f9fa;
  border-radius: 8px;
  padding: 16px;
}

/* Override theme colors via CSS variables */
fma-carfare-search {
  --color-primary: #0d67bd;
  --color-secondary: #e47b26;
}

Global Config (optional)

If present, the widget will read defaults from window.__A1_WIDGET_CONFIG__:

<script>
  window.__A1_WIDGET_CONFIG__ = {
    iata: 'FAT',
    primaryColor: '#0B89FF',
    secondaryColor: '#0B89FF',
    defaultDestinations: [],
  };
  // origin/primary/secondary from this object are used only when
  // not explicitly set as attributes on the element.
</script>