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

@startinblox/solid-tems-shared

v2.0.0

Published

Startin'blox TEMS shared libraries

Readme

TEMS Shared Components

npm stable latest

Shared libraries and utilities for the TEMS (Trusted European Media data Space) ecosystem. Provides base component classes, data utilities, mock data, and Orbit integration helpers for building federated data space applications.

Table of Contents

  1. Key Features
  2. Architecture
  3. Utilities
  4. Base Classes
  5. Mock Data
  6. Installation
  7. Quick Start
  8. Development
  9. Documentation
  10. License

Key Features

Component Base Classes

  • OrbitComponent: Full Orbit integration with data fetching, caching, and routing awareness
  • ComponentObjectHandler: Single resource display without data fetching
  • ComponentObjectsHandler: Array/collection of resources without data fetching
  • TemsObjectHandler/TemsObjectsHandler: TEMS-specific resource handlers

Data Utilities

  • Filtering: Multiple filter generators for value, type, date interval, named value, and ID filtering
  • Sorting: Generic sort function supporting nested keys, numbers, strings, and dates
  • Data Building: Helper functions for constructing and transforming data structures

UI Helpers

  • FormatDate: Date formatting using Intl API
  • AvatarSvg: SVG-based avatar generation with initials
  • TabsManager: Tab navigation management
  • OfferKindHandler: Handle different offer kinds and actions

Orbit Integration

  • Cache Invalidation: Setup cache invalidation on resource changes
  • Component Subscriptions: Subscribe to component events and lifecycle hooks
  • On Save Reset: Setup reset functionality after save operations
  • Request Navigation: Navigation wrapper with route-based routing

Mock Data

  • Comprehensive mock data for testing: services, data offers, media objects, assets, licenses, locations, providers, users, organizations, and more

Architecture

Component Base Classes

ComponentObjectHandler: Display a single resource. Used for single item/detail views, within OrbitComponent, no data fetching needed.

ComponentObjectsHandler: Display an array/collection of resources. Used for lists/grids, within OrbitComponent, no data fetching needed.

OrbitComponent: Full Orbit integration with data fetching. Extends ComponentObjectsHandler. Used for fetching data from URL (data-src), caching/updates, routing awareness, Orbit interaction, single object and list display.

Utilities

Data Utilities

| Function | Description | |----------|-------------| | sort(arr, key, order) | Sort arrays by nested keys, numbers, strings, or dates | | filterGenerator | Create custom filter functions | | filterObjectByValue | Filter objects by property value | | filterObjectByType | Filter objects by @type property | | filterObjectByNamedValue | Filter by named value (e.g., foaf:name) | | filterObjectById | Filter by @id property | | filterObjectByInterval | Filter by numeric interval | | filterObjectByDateAfter | Filter objects by date after a threshold | | filterObjectByDateInterval | Filter by date interval | | dataBuilder | Build and transform data structures | | checkValueInIntervalRecursive | Recursive interval checking |

UI Helpers

| Function | Description | |----------|-------------| | formatDate(date) | Format dates using Intl API | | AvatarSvg(name, size) | Generate SVG avatar with initials | | TabsManager | Tab navigation management | | offerKindHandler | Handle offer kind display | | offerKindActionHandler | Handle offer kind actions | | uniq() | Generate unique IDs |

Orbit Integration Helpers

| Function | Description | |----------|-------------| | setupCacheInvalidation(component, { keywords }) | Setup cache invalidation on resource changes | | setupCacheOnResourceReady(component) | Setup cache operations when resource is ready | | setupComponentSubscriptions(component) | Subscribe to component events | | setupOnSaveReset(component) | Setup reset after save operations | | requestNavigation(route, resource) | Navigation wrapper |

Base Classes

OrbitComponent

Key features:

  • cherryPickedProperties: Declarative data fetching
  • _getProxyValue(url): Fetch and transform resources
  • _responseAdaptator(response): Custom transformations
  • gatekeeper(): Route-aware rendering optimization
  • orbit property: Orbit integration
  • setupCacheInvalidation(): Cache invalidation

Usage:

import OrbitComponent from '@helpers/components/orbitComponent';

@customElement('my-component')
export class MyComponent extends OrbitComponent {
  cherryPickedProperties: PropertiesPicker[] = [
    { key: "name", value: "name" },
    { key: "created_at", value: "created_at", cast: formatDate },
    { key: "categories", value: "categories", expand: true, cast: (c) => sort(c, "name") },
  ];
}

ComponentObjectHandler

Used for displaying a single resource without data fetching:

import { ComponentObjectHandler } from '@helpers/components/componentObjectHandler';

@customElement('my-single-item')
export class MySingleItem extends ComponentObjectHandler {
  render() {
    return html`<p>${this.resource?.name}</p>`;
  }
}

ComponentObjectsHandler

Used for displaying collections without data fetching:

import { ComponentObjectsHandler } from '@helpers/components/componentObjectsHandler';

@customElement('my-list')
export class MyList extends ComponentObjectsHandler {
  render() {
    return html`
      <ul>
        ${this.resources?.map(r => html`<li>${r.name}</li>`)}
      </ul>
    `;
  }
}

Mock Data

Available mock data for testing:

| Mock | Description | |------|-------------| | asset.mock.ts | Asset objects | | dataOffer.mock.ts | Data offer definitions | | image.mock.ts | Image objects | | licence.mock.ts | License information | | location.mock.ts | Location data | | namedResource.mock.ts | Named resources | | object.mock.ts | Generic objects | | offers.mock.ts | Offer catalog | | orbit.mock.ts | Orbit configuration | | organisation.mock.ts | Organization data | | provider.mock.ts | Provider information | | service.mock.ts | Service definitions | | sentiment.mock.ts | Sentiment analysis data | | user.mock.ts | User profiles | | mediaObject.mock.ts | Generic media objects | | 3DObject.mock.ts | 3D object models | | mediaobjects/ | Specialized media objects (civilSociety, factChecking, etc.) |

Installation

npm install @startinblox/solid-tems-shared

Quick Start

Use TEMSOrbit instead of Orbit in your component.d.ts

import type { TemsLiveOrbit } from "@startinblox/solid-tems-shared";

...

export declare global {
  interface Window {
    orbit: TemsLiveOrbit;
    sibStore: { getData: ProxyValue<Resource | Container>; [key: string]: any };
    sibRouter: { [key: string]: any };
  }
}

Using Base Classes

import OrbitComponent from '@helpers/components/orbitComponent';
import { formatDate } from '@helpers/ui/formatDate';
import { sort } from '@helpers/datas/sort';

@customElement('my-catalog')
export class MyCatalog extends OrbitComponent {
  cherryPickedProperties = [
    { key: "name", value: "name" },
    { key: "createdAt", value: "created_at", cast: formatDate },
  ];

  render() {
    if (!this.data) return html`<p>Loading...</p>`;
    return html`
      <div>
        ${this.data.map(item => html`<div>${item.name}</div>`)}
      </div>
    `;
  }
}

Using Data Utilities

import { filterObjectByType } from '@helpers/datas/filterObjectByType';
import { sort } from '@helpers/datas/sort';

const resources = [
  { "@type": "Offer", name: "Offer 1" },
  { "@type": "Asset", name: "Asset 1" },
  { "@type": "Offer", name: "Offer 2" }
];

const offers = filterObjectByType(resources, "Offer");
const sortedOffers = sort(offers, "name", "asc");

Using UI Helpers

import { formatDate } from '@helpers/ui/formatDate';
import { AvatarSvg } from '@helpers/ui/avatarSvg';

const date = new Date();
const formatted = formatDate(date);

const avatar = new AvatarSvg("John Doe", 40);

Setting Up Cache Invalidation

import setupCacheInvalidation from '@helpers/components/setupCacheInvalidation';

@customElement('my-component')
export class MyComponent extends OrbitComponent {
  _afterAttach() {
    super._afterAttach();
    setupCacheInvalidation(this, { keywords: ["service", "asset"] });
  }
}

Using Internationalization

<script type="module">
  import '@startinblox/solid-tems-shared';
</script>

<script>
  // Change locale at runtime
  window.setLocale("fr");  // Switch to French
  window.getLocale();      // Get current locale
</script>

Development

Watch Mode (Hot Reload)

npm run watch

Run Tests (Vitest)

npm test                   # Run all tests
npm run test:open          # Run tests in browser (Playwright)
npm run test:watch         # Watch mode for tests
npm run test:coverage      # Run tests with coverage

Build for Production

npm run build

Preview Production Build

npm run serve

Linting & Formatting

npx biome check .                    # Check for issues
npx biome check . --write            # Auto-fix and format

Documentation

For Developers

Component Conventions

Naming:

  • Web component elements: kebab-case (e.g., my-component)
  • Class names: PascalCase (e.g., MyComponent)
  • Properties/attributes: kebab-case in HTML, camelCase in JS
  • Private methods: prefix with _ (e.g., _afterAttach)

Lit Decorators:

  • @customElement("element-name") - Define web component
  • @property({ attribute: "data-src", reflect: true }) - Public attributes reflecting to DOM
  • @property({ attribute: false, type: Object }) - Object properties (no attribute reflection)
  • @state() - Private reactive state

Event Handlers:

All event handlers must prevent default behavior:

_handleEvent(e: Event) {
  e.preventDefault();
  // handler logic
}

Style Import:

import ComponentStyle from "@styles/component.scss?inline";
static styles = css`${unsafeCSS(ComponentStyle)}`;

Import Paths

Use configured aliases in your code:

import OrbitComponent from '@helpers/components/orbitComponent';
import { sort } from '@helpers/datas/sort';
import { formatDate } from '@helpers/ui/formatDate';
import setupCacheInvalidation from '@helpers/components/setupCacheInvalidation';

Orbit Integration

  • Import @src/initializer before @customElement decorator
  • Use gatekeeper() to prevent unnecessary renders
  • Check this.orbit exists before using Orbit features
  • Get component references via this.orbit?.getComponent("component-name")
  • Wait for readiness with addEventListener("ready", ...)

Cherry-Picked Properties Pattern

cherryPickedProperties: PropertiesPicker[] = [
  { key: "name", value: "name" },
  { key: "created_at", value: "created_at", cast: formatDate },
  { key: "categories", value: "categories", expand: true, cast: (c) => sort(c, "name") },
];

Error Handling

Try-catch in async methods, log errors only in dev mode:

try {
  // code
} catch (e) {
  if (import.meta.env.DEV) console.error(e);
}

License

MIT


TEMS Project - Co-funded by the European Union