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

@opendevstack/ods-selector-widget

v0.0.2

Published

A flexible and customizable web component for displaying platform navigation and resource links

Readme

ODS Selector Widget

A flexible and customizable web component for displaying platform navigation and resource links. Built with Stencil, this component provides a clean interface for organizing and accessing multiple platform resources in a project-based context.

Features

  • 🎨 Fully Customizable: Extensive CSS custom properties for theming
  • 🔌 Framework Agnostic: Works both with Angular and React
  • 🔄 Dynamic Content: Fetches platform data from a service URL
  • 🦴 Loading States: Built-in skeleton loader and error handling
  • 🔗 Platform Selector: Dedicated platform icons with enable/disable states
  • 📑 Sectioned Layout: Organize links into logical sections with tooltips
  • 🔀 Multiple Link Types: Support for platform, project (internal), and external links with appropriate icons

Table of Contents

Installation

NPM

npm install @opendevstack/ods-selector-widget

Usage

Angular

1. Import the Component

For Angular with NgModule (traditional setup):

In your app.module.ts:

import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { defineCustomElements } from '@opendevstack/ods-selector-widget/loader';

import { AppComponent } from './app.component';

defineCustomElements(window);

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [],
  bootstrap: [AppComponent],
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule { }

For Angular with Standalone Components:

In your main.ts:

import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { defineCustomElements } from '@opendevstack/ods-selector-widget/loader';

defineCustomElements(window);

bootstrapApplication(AppComponent, {
  providers: []
});

In your app.component.ts:

import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';

@Component({
  selector: 'app-root',
  standalone: true,
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  // Component logic
}

2. Configure Angular (if needed)

Note: If you encounter the error ✘ [ERROR] No loader is configured for ".map" files, you need to update your angular.json configuration.

Add the following to your architect.build.options in angular.json:

{
  "architect": {
    "build": {
      "options": {
        "customWebpackConfig": {
          "loader": {
            ".map": "empty"
          }
        }
      }
    }
  }
}

3. Use in Template

<ods-selector-widget
  project="My Project"
  service-url="https://api.example.com/platforms/{{project}}">
</ods-selector-widget>

React

The following code demonstrates how to integrate the ODS Selector Widget into a React application with TypeScript.

import { defineCustomElements } from '@opendevstack/ods-selector-widget/loader';

// Call this once in your app initialization
defineCustomElements(window);

function App() {
  return (
    <div>
      <ods-selector-widget
        project="My Project"
        service-url="https://api.example.com/platforms/${project}"
      />
    </div>
  );
}

export default App;

Key Points:

  • defineCustomElements(window): Registers the custom web component with the browser. This must be called once before rendering any <ods-selector-widget> elements.
  • project attribute: Sets the project name for the widget.
  • service-url attribute: Defines the API endpoint. Use ${project} as a template variable that gets replaced with the project name.

For better TypeScript support in React:

To enable TypeScript support for the custom element, add this to your type declarations file:

// Add to your declarations file (e.g., custom-elements.d.ts)
declare module 'react' {
  namespace JSX {
    interface IntrinsicElements {
      'ods-selector-widget': {
        project?: string;
        'service-url'?: string;
      };
    }
  }
}

Configure React + Vite (if needed)

Note: If you encounter the error No loader is configured for ".map" files in a React + Vite project, update your vite.config.js or vite.config.ts to exclude .map files from dependency optimization.

Add the following to your Vite config:

// vite.config.js or vite.config.ts
export default {
  optimizeDeps: {
    exclude: ['*.map']
  }
}

Properties

| Property | Attribute | Type | Default | Description | |----------|-----------|------|---------|-------------| | project | project | string | undefined | The project name displayed in the widget header | | serviceUrl | service-url | string | undefined | The service URL to fetch platform data. Use ${project} as a placeholder that will be replaced with the project name |

Example

<ods-selector-widget
  project="PROJECT1"
  service-url="https://api.myapp.com/platforms/${project}">
</ods-selector-widget>

API Response Format

The component expects the service URL to return JSON data in the following format:

{
  "sections": [
    {
      "section": "Select your platform",
      "tooltip": "",
      "links": [
        {
          "label": "Platform One",
          "url": "https://platform1.com",
          "abbreviation": "P1",
          "type": "platform"
        },
        {
          "label": "Platform Two",
          "url": "https://platform2.com",
          "abbreviation": "P2",
          "type": "platform",
          "disabled": true
        },
        {
          "label": "Platform Three",
          "url": "https://platform3.com",
          "abbreviation": "P3",
          "type": "platform",
          "disabled": true
        }
      ]
    },
    {
      "section": "Documentation",
      "tooltip": "Access project documentation and guides",
      "links": [
        {
          "label": "API Reference",
          "url": "https://docs.example.com/api",
          "tooltip": "Complete API documentation",
          "type": "external"
        },
        {
          "label": "Getting Started",
          "url": "https://docs.example.com/getting-started",
          "tooltip": "Quick start guide",
          "type": "project"
        }
      ]
    },
    {
      "section": "Tools",
      "tooltip": "Development and monitoring tools",
      "links": [
        {
          "label": "Dashboard",
          "url": "https://dashboard.example.com",
          "tooltip": "Project dashboard",
          "type": "external"
        }
      ]
    }
  ]
}

API Response Schema

  • sections (array): Array of content sections to display. Each section can contain either platform links or regular resource links.
    • section (string): Section title
    • tooltip (string, optional): Tooltip text for the section header
    • links (array): Array of links in this section
      • label (string): Link display text
      • url (string): Link destination URL
      • type (string): Link type - "platform", "project", or "external"
        • "platform": Renders as platform selector icons (when all links in a section are platform type)
        • "project": Renders as list item with internal link arrow icon
        • "external": Renders as list item with external link squared arrow icon
      • tooltip (string, optional): Tooltip text for the link (shown on hover for non-platform links)
      • abbreviation (string, optional): Short text shown in platform icon (required for type: "platform")
      • disabled (boolean, optional): If true, the platform link is disabled and shown as non-clickable (only applicable for type: "platform")

Rendering Behavior

The component automatically adapts its rendering based on the link types within each section:

  • Platform Section: If all links in a section have type: "platform", they are rendered as clickable platform icons in a horizontal layout. This is typically used for the main platform selector section.

  • Link List Section: If a section contains any non-platform links (type: "project" or type: "external"), all links in that section are rendered as a vertical list with appropriate arrow icons split in two columns.

Example:

{
  "sections": [
    {
      "section": "Platforms",
      "links": [
        { "label": "Platform 1", "url": "...", "abbreviation": "P1", "type": "platform" },
        { "label": "Platform 2", "url": "...", "abbreviation": "P2", "type": "platform" }
      ]
    }
  ]
}

The example above renders as platform icons

{
  "sections": [
    {
      "section": "Resources",
      "links": [
        { "label": "Documentation", "url": "...", "type": "external" },
        { "label": "Dashboard", "url": "...", "type": "project" }
      ]
    }
  ]
}

The example above renders as a list with arrow/squared arrow icons.

Styling

The component uses CSS custom properties (CSS variables) for easy theming. You can override these in your stylesheet:

Available CSS Custom Properties

ods-selector-widget {
  /* Font family */
  --ods-selector-widget-font-family: 'Inter', sans-serif;

  /* Primary colors */
  --ods-selector-widget-color-primary: #08312A;
  --ods-selector-widget-color-white: #FFF;
  --ods-selector-widget-color-border: #5C5B59;
  --ods-selector-widget-color-shadow: rgba(0, 0, 0, 0.05);
  --ods-selector-widget-color-shadow-hover: rgba(0, 0, 0, 0.25);

  /* Header colors */
  --ods-selector-widget-header-bg: #CCFAE5;
  --ods-selector-widget-header-text: #08312A;

  /* Platform icon colors */
  --ods-selector-widget-platform-icon-bg: #08312A;
  --ods-selector-widget-platform-icon-text: white;
  --ods-selector-widget-first-platform-bg: #008E4C;
  --ods-selector-widget-first-platform-text: #ffffff;
  --ods-selector-widget-second-platform-bg: #5E71FF;
  --ods-selector-widget-second-platform-text: #ffffff;
  --ods-selector-widget-third-platform-bg: #00C86B;
  --ods-selector-widget-third-platform-text: #ffffff;

  /* Disabled state colors */
  --ods-selector-widget-disabled-bg: #E5E3DE;
  --ods-selector-widget-disabled-text: #898885;

  /* Section colors */
  --ods-selector-widget-section-text: #08312A;
  --ods-selector-widget-divider-color: #D3D3D3;

  /* Link colors */
  --ods-selector-widget-link-text: #08312A;
  --ods-selector-widget-link-hover: #6B8375;

  /* Error section colors */
  --ods-selector-widget-error-text: #051D19;
  --ods-selector-widget-error-button-border: #08312A;
  --ods-selector-widget-error-button-text: #08312A;
  --ods-selector-widget-error-button-hover-text: #6B8375;
  --ods-selector-widget-error-button-hover-border: #6B8375;

  /* Tooltip colors */
  --ods-selector-widget-tooltip-bg: #051D19;
  --ods-selector-widget-tooltip-text: #fff;

  /* Skeleton loader colors */
  --ods-selector-widget-skeleton-bg: #F6F5F3;
  --ods-selector-widget-skeleton-shimmer: #e4e3e2;
}

Example: Custom Theme

ods-selector-widget {
  --ods-selector-widget-font-family: "YourCustomFont", sans-serif;
  --ods-selector-widget-color-primary: #2563eb;
  --ods-selector-widget-header-bg: #dbeafe;
  --ods-selector-widget-header-text: #1e40af;
  --ods-selector-widget-first-platform-bg: #10b981;
  --ods-selector-widget-second-platform-bg: #8b5cf6;
  --ods-selector-widget-third-platform-bg: #f59e0b;
}

Publishing to npm

Prerequisites

  • An npmjs.com account with access to the @opendevstack scope.
  • You must be logged in to the npm registry: npm login

Steps

1. Build the package

The dist/ and loader/ directories (declared in the files field of package.json) are generated by the build step and must be up to date before publishing.

npm run build

2. Bump the version

Update the version field in package.json following Semantic Versioning, then record the change in CHANGELOG.md.

# patch: bug fixes  →  0.2.0 → 0.2.1
npm version patch

# minor: new backwards-compatible features  →  0.2.0 → 0.3.0
npm version minor

# major: breaking changes  →  0.2.0 → 1.0.0
npm version major

npm version automatically updates package.json and creates a git tag.

3. Run tests

Make sure all tests pass before publishing.

npm test

4. Publish

The package is scoped to @opendevstack, so you need to explicitly opt in to publishing it as a public package:

npm publish --access public

What gets published

Only the contents of the files array in package.json are included in the tarball:

| Directory | Contents | |-----------|----------| | dist/ | Compiled component bundles, type declarations, and collection manifest | | loader/ | Custom Elements loader for lazy-loading in Angular/React apps |

You can preview the exact file list without publishing by running:

npm pack --dry-run

Development

  • Node.js (v14 or higher)
  • npm (v6 or higher)

Setup

# Clone the repository
git clone https://github.com/opendevstack/ods-selector-widget.git
cd ods-selector-widget

# Install dependencies
npm install

Available Scripts

# Start development server with live reload
npm start

# Build for production
npm run build

# Run tests
npm test

# Run tests in watch mode
npm run test.watch

# Generate a new component
npm run generate

Project Structure

ods-selector-widget/
├── src/
│   ├── components/
│   │   └── ods-selector-widget/
│   │       ├── ods-selector-widget.tsx    # Component logic
│   │       ├── ods-selector-widget.css    # Component styles
│   │       ├── ods-selector-widget.spec.ts # Unit tests
│   │       └── ods-selector-widget.e2e.ts  # E2E tests
│   ├── index.html    # Demo page
│   └── index.ts      # Entry point
├── dist/             # Build output
├── www/              # Dev server output
└── stencil.config.ts # Stencil configuration

Testing

The component includes both unit and end-to-end tests:

# Run all tests
npm test

# Run only unit tests
npm run test -- --spec

# Run only e2e tests
npm run test -- --e2e

# Generate coverage report
npm test -- --coverage

Browser Support

This component works in all modern browsers that support:

  • Custom Elements V1
  • Shadow DOM
  • ES Modules

For older browsers, you may need to include polyfills.

Contributing

Contributions are welcome! Please follow these guidelines:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Contribution Guidelines

  • Write clear, descriptive commit messages
  • Add tests for new features
  • Update documentation as needed
  • Follow the existing code style
  • Ensure all tests pass before submitting PR

License

This project is licensed under the Apache License - see the LICENSE file for details.

Support

If you encounter any issues or have questions:

Acknowledgments

Built with Stencil - A toolchain for building reusable, scalable Design Systems.