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

@arbetsformedlingen/kompetensvaljaren

v2.3.0

Published

Fristående webbkomponent för att välja kompetenser.

Downloads

324

Readme

Kompetensväljaren (digi-service-skill-selector)

Kompetensväljaren är en webbkomponent för att välja kompetenser. Hela kompetenskatalogen är sökbar, och kompetenser som hör till det valda yrket prioriteras. Den laddar en liten basfil (kv-base.v1.json) och hämtar yrkesspecifik data (kontextshards) först när den behövs.

Beskrivning

  • Hitta rätt kompetens för yrket Hela kompetenskatalogen är sökbar. När ett yrke är valt, till exempel från Yrkesväljaren, prioriteras kompetenser som hör till yrket.
  • Hög prestanda Sökningen sker lokalt i webbläsaren. Komponenten laddar en liten basfil och hämtar yrkesdata först när den behövs.
  • Flexibel datahantering Versionerat npm-datapaket (rekommenderas), automatiskt uppdaterad data eller en egen URL.
  • Headless-API Samma sökning finns som funktion för klienter som bygger ett eget gränssnitt.

Installation

Installera komponenten och datapaketet:

npm install @arbetsformedlingen/kompetensvaljaren @arbetsformedlingen/kompetensvaljaren-data@31

Datapaketets majorversion är taxonomiversionen: 31.x.y innehåller taxonomi v31. Med ^31.0.0 i package.json får du rättningar av v31-datan men byter aldrig taxonomiversion av misstag.

Välj läge

  1. Låst version (rekommenderas) Datapaketet registreras via registerSkills(await loadBase()).
  2. Senaste Utan registrerad data hämtar komponenten senaste datan från CDN.
  3. Egen URL Avancerat läge. Peka af-data-url mot en egen hostad kv-base.v1.json.

Användning i Angular

Exemplet kopplar ihop Kompetensväljaren med Yrkesväljaren och låser datan för båda till taxonomi v31:

npm install @arbetsformedlingen/kompetensvaljaren @arbetsformedlingen/kompetensvaljaren-data@31 @arbetsformedlingen/yrkesvaljaren @arbetsformedlingen/yrkesvaljaren-data@31

Registrera datan och båda komponenterna i main.ts innan appen startar:

// src/main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { defineCustomElements as defineYv } from '@arbetsformedlingen/yrkesvaljaren/loader';
import { defineCustomElements as defineKv } from '@arbetsformedlingen/kompetensvaljaren/loader';
import { registerSkills } from '@arbetsformedlingen/kompetensvaljaren';
import { registerTaxonomy } from '@arbetsformedlingen/yrkesvaljaren';
import { loadBase } from '@arbetsformedlingen/kompetensvaljaren-data';
import { appConfig } from './app/app.config';
import { App } from './app/app';

async function main() {
  // Yrkesdatan (cirka 2 MB) importeras dynamiskt så att den hamnar i en egen chunk.
  const { metadata, taxonomyData } = await import('@arbetsformedlingen/yrkesvaljaren-data');
  registerTaxonomy({ data: taxonomyData, metadata });
  registerSkills(await loadBase({ basePath: '/assets/kv-v31/' }));
  defineYv(window);
  defineKv(window);
  await bootstrapApplication(App, appConfig);
}

main().catch((err) => console.error(err));

Kopiera KV-datan som assets med en regel i angular.json (projects.<projekt>.architect.build.options.assets):

{
  "glob": "**/*",
  "input": "node_modules/@arbetsformedlingen/kompetensvaljaren-data/dist",
  "output": "/assets/kv-v31/"
}

Koppla sedan Yrkesväljaren till Kompetensväljaren i en standalone-komponent:

// src/app/skills.component.ts
import { Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, signal, viewChild } from '@angular/core';
import type { KvSelection } from '@arbetsformedlingen/kompetensvaljaren';

type SkillSelectorElement = HTMLElement & { setOccupationSelection(selection: unknown): Promise<string[]> };

@Component({
  selector: 'app-skills',
  standalone: true,
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  template: `
    <digi-service-job-selector af-label="Välj yrke" (afJobSelected)="onJobSelected($event)"></digi-service-job-selector>
    <digi-service-skill-selector #kv af-label="Välj dina kompetenser" (afKompetensSelection)="onSkills($event)"></digi-service-skill-selector>
    <p>Valda kompetenser: {{ skills().length }}</p>
  `,
})
export class SkillsComponent {
  private readonly kv = viewChild.required<ElementRef<SkillSelectorElement>>('kv');
  readonly skills = signal<KvSelection[]>([]);

  onJobSelected(event: Event): void {
    void this.kv().nativeElement.setOccupationSelection((event as CustomEvent).detail);
  }

  onSkills(event: Event): void {
    this.skills.set((event as CustomEvent<KvSelection[] | null>).detail ?? []);
  }
}

Bygger ni ett eget gränssnitt i stället för webbkomponenten, använd headless-sökningen. Ett komplett Angular-exempel finns i examples/angular-multi-occupation-skills.

Användning

Låst version

Registrera datapaketets base-data innan komponenten renderas. Komponenten ska inte mountas förrän registerSkills(...) är klar.

<script type="module">
  import { defineCustomElements as defineSkillSelector } from "@arbetsformedlingen/kompetensvaljaren/loader";
  import { registerSkills } from "@arbetsformedlingen/kompetensvaljaren";
  import { loadBase } from "@arbetsformedlingen/kompetensvaljaren-data";

  defineSkillSelector(window);
  registerSkills(await loadBase());
</script>

<digi-service-skill-selector
  af-label="Välj dina kompetenser"
  af-occupation-id="GPNi_fJR_B2B"
></digi-service-skill-selector>

I vissa devservrar och bundlers behöver datapaketets JSON exponeras som en publik asset. Om filen ligger på en annan sökväg än datapaketets bundle kan loadBase() få en explicit URL:

registerSkills(await loadBase({ basePath: "https://d3hng02m5bee8m.cloudfront.net/kompetensvaljaren/latest/" }));

Det hämtar kv-base.v1.json från den angivna basePath-URL:en. Kontextshards hämtas relativt samma basefil. När bundlern hanterar paketassets korrekt räcker registerSkills(await loadBase()).

Senaste från CDN

Om ni inte registrerar någon data manuellt försöker komponenten först ladda af-data-url. Om ingen URL anges laddar komponenten Senaste. Om en explicit URL anges och den inte kan laddas går komponenten till felläge i stället för att tyst byta dataset.

<digi-service-skill-selector
  af-label="Välj dina kompetenser"
></digi-service-skill-selector>

CloudFront-URL för Senaste är:

https://d3hng02m5bee8m.cloudfront.net/kompetensvaljaren/latest/kv-base.v1.json

Shards ska ligga relativt till denna:

https://d3hng02m5bee8m.cloudfront.net/kompetensvaljaren/latest/shards/kv-context-222.v1.json

Direkt från Yrkesväljaren

Kompetensväljaren kan ta Yrkesväljarens afJobSelected.detail direkt:

const yv = document.querySelector('digi-service-job-selector');
const kv = document.querySelector('digi-service-skill-selector');

yv.addEventListener('afJobSelected', (event) => {
  kv.setOccupationSelection(event.detail);
});

occupation-name använder sitt eget Concept ID. job-title använder sitt kopplade related occupation-name. Vid flera val blir det första mappningsbara yrket primär kontext och resterande unika yrken extra kontext. Noll val ([]) eller inga mappningsbara val rensar tidigare yrkeskontext.

Lågnivå-API:t af-occupation-id/af-input-ids finns kvar för konsumenter som redan har taxonomi-ID:n. KV:s datapaket fortsätter att vara byggt kring occupation-name och ssyk-level-4; jobbtitlar läggs inte in i KV-data.

Mer detaljer finns i guiden för YV → KV.

Vite

Kompetensväljaren använder en Stencil-loader som hämtar komponenternas entry-filer dynamiskt. I Vite ska loader-paketet därför undantas från dependency optimizer, annars kan Vite flytta loadern till .vite/deps och de dynamiska importerna får fel sökväg.

// vite.config.js
export default {
  optimizeDeps: {
    exclude: [
      '@arbetsformedlingen/kompetensvaljaren/loader',
    ],
  },
};

Designsystem-kompatibilitet

Kompetensväljaren är uppbyggd med designsystemets tokens, typografi, färger, fokusramar och ikoner och kommer att uppdateras automatiskt för dig som har designsystemet installerat. Den använder de förväntade attributen för att styla etikett, felmeddelande osv, men har inga komponentberoenden till designsystemet. För den som inte har designsystemet installerat används inbyggda fallbacks för att bibehålla utseendet.

Avancerat: Egen URL

Om du inte registrerar data manuellt kan komponenten i stället ladda kv-base.v1.json via af-data-url. Detta är ett avancerat läge för team som själva vill styra hosting och caching. Om den URL:en inte kan laddas går komponenten till felläge i stället för att tyst byta dataset.

https://d3hng02m5bee8m.cloudfront.net/kompetensvaljaren/latest/kv-base.v1.json

Publikt API

| Property | Attribut | Typ | Standard | Beskrivning | | --- | --- | --- | --- | --- | | afOccupationId | af-occupation-id | string | '' | Primär kontext. Kan vara ett Concept ID för occupation-name eller ssyk-level-4. | | afInputIds | af-input-ids | string \| string[] | [] | Extra kontext-id:n. Strängvärden kan vara kommaseparerade eller en JSON-array. Implementationens parser begränsar inte antalet id:n. | | label | af-label | string | 'Sök eller välj dina kompetenser' | Etikett för fältet. | | placeholder | af-placeholder | string | 'Skriv för att söka...' | Ledtext i sökfältet. | | size | af-size | 'small' \| 'medium' \| 'large' | 'medium' | Storlek på komponenten. | | value | (ingen) | string[] | [] | Valda kompetens-id:n. Ska sättas som JavaScript-property, inte som HTML-attribut. | | popular | af-popular | boolean | true | Visar initiala vanliga eller kontextuella kompetenser när sökningen är tom. | | afStayOpen | af-stay-open | boolean | false | Håller förslagslistan (dropdown) öppen direkt utan att komponenten behöver fokus (t.ex. i modal eller popup). | | dataUrl | af-data-url | string | '' | Avancerat läge. URL till kv-base.v1.json. |

Metoder

setOccupationSelection(selection) tar Yrkesväljarens afJobSelected.detail direkt och returnerar de normaliserade occupation-name-ID:n som används som KV-kontext.

Sökbeteende

Tom sökning visar mostCommonSkills, eller en kontextlista om ett giltigt yrkes-id har angetts. Vid textsökning är hela kompetenskatalogen sökbar. Direkta textträffar rangordnas före fuzzy-träffar. Fuzzy-sökning kan lägga till kandidater som inte direktmatchar. Yrkeskontext och förberäknade vikter påverkar ordningen inom sökmodellens rangordning. Svenska tecken viks inte ihop, så exempelvis vard och vård behandlas olika.

Programmatisk värdesättning (value)

Förval eller dynamisk värdesättning av valda kompetenser görs via JavaScript-propertyn value som tar en array av Concept ID:n.

const skillSelector = document.querySelector('digi-service-skill-selector');

// Vänta tills komponenten är redo om den nyss lagts till i DOM:en
skillSelector.componentOnReady().then(() => {
  // Sätt valda kompetenser
  skillSelector.value = ['dmF5_zy7_Utt', 'abc1_def_ghi'];

  // Rensa valda kompetenser
  // skillSelector.value = [];
});

Ogiltiga värden, exempelvis okända id:n, dubletter, tomma strängar eller annat än en strängarray, avvisas genom att det senaste giltiga värdet återställs och ett fel skrivs med console.error. Programmatisk ändring av value skickar inte afKompetensSelection.

Event-output

afKompetensSelection skickas efter användarval, borttagning och rensning. Eventet returnerar en array med platta kompetensobjekt, eller null när urvalet har blivit tomt:

[
  {
    "taxonomy/type": "skill",
    "taxonomy/id": "dmF5_zy7_Utt",
    "taxonomy/preferred-label": "Berglastning"
  }
]

Headless-sökning

Samma kompetenssökning utan webbkomponent, för klienter med eget gränssnitt:

import { searchCompetences } from '@arbetsformedlingen/kompetensvaljaren';

// GQSf_fnq_kjF = Truckförare
const competences = await searchCompetences({
  query: 'truck',
  occupationId: 'GQSf_fnq_kjF',
});

Skicka Yrkesväljarens event-output utan egen mappning:

import { searchCompetences } from '@arbetsformedlingen/kompetensvaljaren';

const yv = document.querySelector('digi-service-job-selector');
yv.addEventListener('afJobSelected', async (event) => {
  const fromYv = await searchCompetences({
    query: 'truck',
    occupationSelection: event.detail,
  });
  // Visa fromYv i klientens gränssnitt.
});

query, occupationId och occupationSelection är valfria. Använd antingen occupationId eller occupationSelection i ett anrop. Det senare tar hela afJobSelected.detail (en array), eller ett enskilt YV-val när klienten söker kompetenser separat för varje yrke. Samma normalisering och kontextordning används av headless och setOccupationSelection(...).

Inledande och avslutande blanksteg i query och occupationId tas bort; en tom sträng behandlas som ett utelämnat värde. occupationId ska vara ett Concept ID för occupation-name eller ssyk-level-4 som finns i det dataset som används. För YV-val används occupation-name.id eller job-title.related.id när related.type är occupation-name. manual-input och jobbtitlar utan ett kopplat occupation-name bidrar inte med någon yrkeskontext. Om ingen kontext återstår används den globala sökningen.

| Indata | Beteende | | --- | --- | | Endast söktext | Global kompetenssökning. | | Giltigt yrkes-ID och söktext | Kompetenssökning med yrkesprioritering. | | Endast giltigt yrkes-ID | Prioriterad kompetenslista enligt KV:s sökpolicy. | | Varken söktext eller yrkes-ID | KV:s fallbacklista med vanliga kompetenser. | | Okänt, icke-tomt yrkes-ID, med eller utan söktext | Anropets Promise avvisas med ett Error vars meddelande innehåller Okänt occupationId. | | Okänt kontext-ID i YV-val | Anropets Promise avvisas på samma sätt, även om andra val är giltiga. | | Både occupationId och occupationSelection | Anropets Promise avvisas eftersom kontexten är tvetydig. |

Ett okänt ID ger ingen resultatlista och utlöser ingen global fallback. Även fel vid laddning av basdata eller kontextshards avvisar anropets Promise. Klienten behöver hantera dessa fel med try/catch eller .catch() och kan då visa att sökningen misslyckades. En lyckad sökning utan träffar ger däremot [].

Registrerad data via registerSkills(...) används i första hand. Annars laddas samma Senaste-dataset som för webbkomponenten, med kontextshards vid behov. Ett ID måste alltså finnas i den registrerade versionen eller i Senaste, beroende på vilket läge klienten använder.

Resultatet är Promise<KvPublicSelection[]>, med samma publika taxonomiform som eventet afKompetensSelection och samma sökpolicy som webbkomponenten. Resultaten returneras i sökmotorns ordning, med högst 20 kompetenser. KV äger data, sökmotor, fuzzy-policy, shards, cache och maxantal. API:t hanterar inte gränssnitt, användarval, förslag eller analys/spårning.

Ett Angular-exempel med flera yrken och separata kompetensval visar hur klienten kan koppla ett yrkesval per headless-anrop.