@arbetsformedlingen/yrkesvaljaren 2.0.11 → 2.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,57 +9,45 @@ En robust och intelligent sökkomponent för svenska yrken, designad för hög p
9
9
 
10
10
  * **Enkelt hitta rätt yrke för användaren** <br>Sökalgoritmen prioriterar exakta träffar, prefix, flerdelade direktträffar och innehåller-träffar. Om inga direktträffar finns kan upp till tre fuzzy-träffar visas. Viktdata används som sekundär sortering.
11
11
  * **Hög prestanda:** <br>Sökningen sker lokalt i webbläsaren mot inläst yrkesdata. Komponenten gör inga sökanrop till Taxonomy API.
12
- * **Flexibel datahantering:** <br>Välj mellan automatiskt uppdaterad data, ett versionerat npm-datapaket eller en egen URL.
12
+ * **Flexibel datahantering:** <br>Versionerat npm-datapaket (rekommenderas), automatiskt uppdaterad data eller en egen URL.
13
13
 
14
14
  ---
15
15
 
16
16
  ### Installation
17
17
 
18
- Yrkesväljaren installeras enkelt via npm:
18
+ Installera komponenten och datapaketet:
19
19
 
20
20
  ```bash
21
- npm install @arbetsformedlingen/yrkesvaljaren
21
+ npm install @arbetsformedlingen/yrkesvaljaren @arbetsformedlingen/yrkesvaljaren-data@31
22
22
  ```
23
23
 
24
- När ingen datakälla anges hämtar komponenten automatiskt den senaste publicerade yrkesdatan från CDN.
24
+ 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. Installera nästa majorversion när du vill byta taxonomiversion.
25
25
 
26
- #### Alternativ: installera ett versionerat datapaket
26
+ Datan registreras med `registerTaxonomy(...)` innan komponenten används. Se [Angular](#användning-i-angular) eller [HTML och andra ramverk](#användning-i-html-och-andra-ramverk).
27
27
 
28
- Om du vill låsa taxonomiversionen vid build time installerar du även ett versionerat datapaket:
29
-
30
- ```bash
31
- npm install @arbetsformedlingen/yrkesvaljaren @taxonomy/yrkesvaljaren-data-v31
32
- ```
33
-
34
- Registrera paketets data i din applikation innan komponenten används:
35
-
36
- ```javascript
37
- import { registerTaxonomy } from '@arbetsformedlingen/yrkesvaljaren';
38
- import {
39
- taxonomyData,
40
- metadata
41
- } from '@taxonomy/yrkesvaljaren-data-v31';
42
-
43
- registerTaxonomy({ data: taxonomyData, metadata });
44
- ```
45
-
46
- `af-taxonomy-url` är ett tredje, avancerat alternativ om du vill peka komponenten mot en egenhostad datafil.
28
+ Utan registrerad data hämtar komponenten den senaste publicerade yrkesdatan från CDN. `af-taxonomy-url` är ett avancerat alternativ om du vill peka komponenten mot en egenhostad datafil.
47
29
 
48
30
  ### Användning i Angular
49
31
 
50
32
  De flesta som använder Yrkesväljaren bygger i Angular. Komponenten är en vanlig webbkomponent, så den fungerar i standalone-komponenter med eller utan zone.js.
51
33
 
52
- Registrera webbkomponenterna i `main.ts` innan appen startar:
34
+ Registrera datan och webbkomponenterna i `main.ts` innan appen startar. Taxonomidatan är cirka 2 MB. Importera den dynamiskt, så hamnar den i en egen chunk. Med en statisk import hamnar den i main-bundlen och `ng build` fastnar på Angulars standardbudget (1 MB).
53
35
 
54
36
  ```ts
55
37
  // src/main.ts
56
38
  import { bootstrapApplication } from '@angular/platform-browser';
57
39
  import { defineCustomElements as defineYv } from '@arbetsformedlingen/yrkesvaljaren/loader';
40
+ import { registerTaxonomy } from '@arbetsformedlingen/yrkesvaljaren';
58
41
  import { appConfig } from './app/app.config';
59
42
  import { App } from './app/app';
60
43
 
61
- defineYv(window);
62
- bootstrapApplication(App, appConfig).catch((err) => console.error(err));
44
+ async function main() {
45
+ const { metadata, taxonomyData } = await import('@arbetsformedlingen/yrkesvaljaren-data');
46
+ registerTaxonomy({ data: taxonomyData, metadata });
47
+ defineYv(window);
48
+ await bootstrapApplication(App, appConfig);
49
+ }
50
+ main().catch((err) => console.error(err));
63
51
  ```
64
52
 
65
53
  Använd sedan komponenten i en standalone-komponent med `CUSTOM_ELEMENTS_SCHEMA` och lyssna på eventet i templaten:
@@ -89,29 +77,10 @@ export class JobPickerComponent {
89
77
 
90
78
  Uppdatera vyn via signals (eller `ChangeDetectorRef`) när ni sätter värden efter en `await`. Annars uppdateras inte vyn i zoneless-appar.
91
79
 
92
- **Låst dataversion i Angular:** taxonomidatan i `@taxonomy/yrkesvaljaren-data-v31` är cirka 2 MB. Importera den dynamiskt i `main.ts`, så hamnar den i en egen chunk. Med en statisk import hamnar den i main-bundlen och `ng build` fastnar på Angulars standardbudget (1 MB).
93
-
94
- ```ts
95
- // src/main.ts
96
- import { bootstrapApplication } from '@angular/platform-browser';
97
- import { defineCustomElements as defineYv } from '@arbetsformedlingen/yrkesvaljaren/loader';
98
- import { registerTaxonomy } from '@arbetsformedlingen/yrkesvaljaren';
99
- import { appConfig } from './app/app.config';
100
- import { App } from './app/app';
101
-
102
- async function main() {
103
- const { metadata, taxonomyData } = await import('@taxonomy/yrkesvaljaren-data-v31');
104
- registerTaxonomy({ data: taxonomyData, metadata });
105
- defineYv(window);
106
- await bootstrapApplication(App, appConfig);
107
- }
108
- main().catch((err) => console.error(err));
109
- ```
110
-
111
80
  Kompletta exempel:
112
81
 
113
- - [`examples/angular-wizard`](examples/angular-wizard): Yrkesväljaren i Reactive Forms via `ControlValueAccessor`.
114
- - [`examples/angular-multi-occupation-skills`](examples/angular-multi-occupation-skills): flera yrken med egna kompetensval via Kompetensväljarens headless-API.
82
+ - [`examples/angular-wizard`](https://gitlab.com/arbetsformedlingen/taxonomy-dev/frontend/yrkesvaljaren/-/tree/main/examples/angular-wizard): Yrkesväljaren i Reactive Forms via `ControlValueAccessor`.
83
+ - [`examples/angular-multi-occupation-skills`](https://gitlab.com/arbetsformedlingen/taxonomy-dev/frontend/yrkesvaljaren/-/tree/main/examples/angular-multi-occupation-skills): flera yrken med egna kompetensval via Kompetensväljarens headless-API.
115
84
 
116
85
  ### Användning i HTML och andra ramverk
117
86
 
@@ -146,6 +115,15 @@ console.log("Valt yrke:", e.detail);
146
115
  </html>
147
116
  ```
148
117
 
118
+ **Utan Angular:** registrera datapaketets data innan komponenten används:
119
+
120
+ ```javascript
121
+ import { registerTaxonomy } from '@arbetsformedlingen/yrkesvaljaren';
122
+ import { taxonomyData, metadata } from '@arbetsformedlingen/yrkesvaljaren-data';
123
+
124
+ registerTaxonomy({ data: taxonomyData, metadata });
125
+ ```
126
+
149
127
  **React:** koppla komponentens event med `addEventListener` via en `ref` i en `useEffect`. Det fungerar i alla React-versioner; en `onAfJobSelected`-prop fungerar inte i React 18.
150
128
 
151
129
  ### Vite
@@ -179,9 +157,9 @@ Yrkesväljaren är uppbyggd med designsystemets tokens, typografi, färger, foku
179
157
  | `af-enable-multiple` | Om satt till `true`, tillåts val av flera yrken. | `boolean` | `false` |
180
158
  | `af-history` | Sparar användarval lokalt i webbläsarens Local Storage och visar historiken på samma domän. | `boolean` | `true` |
181
159
  | `af-required` | Om satt till `true`, måste användaren göra ett val för att fältet ska vara giltigt (obligatoriskt fält). | `boolean` | `false` |
182
- | `af-manual-input` | Om satt till `true`, tillåts användaren att ange ett yrke fritt via fritext som inte finns i listan. Om satt till `false` måste ett fördefinierat yrke väljas. | `boolean` | `false` |
160
+ | `af-manual-input` | Om satt till `true` kan användaren ange ett yrke som fritext när det inte finns i listan. Om satt till `false` måste ett fördefinierat yrke väljas. | `boolean` | `false` |
183
161
  | `af-size` | Storleken på inputfältet. Möjliga värden: `'small'`, `'medium'`, `'large'`. | `string` | `'medium'` |
184
- | `af-popular` | Om satt till `true`, visas sektionen "Populära sökningar" när historiken är tom. | `boolean` | `true` |
162
+ | `af-popular` | Om satt till `true` visas sektionen "Populära sökningar" när historiken är tom. | `boolean` | `true` |
185
163
  | `af-taxonomy-url` | Fullständig, explicit URL till en egenhostad datafil. Utelämna attributet för att använda senaste data automatiskt. | `string` | `undefined` |
186
164
 
187
165
  ### Riktlinjer och rekommendationer
@@ -190,7 +168,7 @@ Tre centrala inställningar styr användarupplevelsen och datakvaliteten i Yrkes
190
168
 
191
169
  #### Obligatorisk (`af-required`)
192
170
  * **Hur man kan resonera:** När `af-required="true"` måste användaren välja minst ett yrke för att fältet ska betraktas som giltigt. Komponenten fungerar som ett standardenligt *Form-Associated Custom Element* (FACE). Det innebär att webbläsaren automatiskt validerar fältet vid formulärinskick, förhindrar att formuläret skickas in om det är tomt, och integrerar med formulärets `validity`-status.
193
- * **När det rekommenderas:** I formulär och flöden där ett yrkesval är ett obligatoriskt steg i ett ärende (t.ex. inskriving, aktivtitetsrapportering).
171
+ * **När det rekommenderas:** I formulär och flöden där ett yrkesval är ett obligatoriskt steg i ett ärende (t.ex. inskrivning och aktivitetsrapportering).
194
172
  * **När det bör undvikas:** I öppna sök- eller filtreringsvyer där användaren ska kunna söka brett, filtrera på andra parametrar (t.ex. enbart ort/geografi) eller frivilligt specificera yrke.
195
173
 
196
174
  #### Tillåt fritext (`af-manual-input`)
@@ -200,9 +178,9 @@ Tre centrala inställningar styr användarupplevelsen och datakvaliteten i Yrkes
200
178
  * **Fritext tillåten (`af-manual-input="true"`):** I öppna fritextprofiler, fritextenkäter eller intresseanmälningar där det är viktigare att fånga upp vad användaren själv kallar sin roll än att få ett taxonomi-ID, eller där man inte vill blockera användare med ovanliga, nischade eller internationella titlar.
201
179
 
202
180
  #### Tillåt historik (`af-history`)
203
- * **Hur man kan resonera:** Sparar gjorda val i webbläsarens localStorage per domän och enhet, och visar dem som "Tidigare val" när användaren fokuserar Yrkesväljaren. Det betyder att historiken kommer att visas på alla tjänster med yrkesväljare på arbetsformedlingen.se (så länge personen använder samma enhet, t.ex sin mobil).
181
+ * **Hur man kan resonera:** Sparar gjorda val i webbläsarens localStorage per domän och enhet, och visar dem som "Tidigare val" när användaren fokuserar Yrkesväljaren. Det betyder att historiken kommer att visas på alla tjänster med yrkesväljare på arbetsformedlingen.se (så länge personen använder samma enhet, t.ex. sin mobil).
204
182
  * **När det rekommenderas:** På alla tjänster mot konsumenter.
205
- * **När det bör undvikas:** På delade publika terminaler eller kioskdatorer (t.ex. på Arbetsförmedlingens servicekontor) där personers tidigare sökningar inte ska sparas eller exponeras för efterföljande besökare på samma dator. Kanske är det inget hjälpsamt stöd för tjänster för Handläggare eftersom de söker måååånga olika yrken.
183
+ * **När det bör undvikas:** På delade publika terminaler eller kioskdatorer (t.ex. på Arbetsförmedlingens servicekontor) där personers tidigare sökningar inte ska sparas eller exponeras för efterföljande besökare på samma dator. I handläggartjänster är historiken sällan till hjälp, eftersom handläggare söker på många olika yrken.
206
184
 
207
185
  ### Välj datakälla
208
186
 
@@ -235,7 +213,7 @@ dataladdning.
235
213
 
236
214
  | Metod | Returvärde | Beskrivning |
237
215
  |:---|:---|:---|
238
- | `setSelection(input)` | `Promise<JobSelectionItem[]>` | Sätter eller rensar ett programmatiskt val. Returnerar komponentens normaliserade selection. |
216
+ | `setSelection(input)` | `Promise<JobSelectionItem[]>` | Sätter eller rensar ett programmatiskt val. Returnerar komponentens normaliserade val. |
239
217
  | `setFocus()` | `Promise<void>` | Flyttar fokus till sökfältet. Används när värdappen till exempel öppnar en modal eller vill fokusera fältet efter ett fel. |
240
218
 
241
219
  #### Formulärvalidering
@@ -363,7 +341,7 @@ För att göra fältet obligatoriskt, använd `af-required`-attributet och stäl
363
341
  ></digi-service-job-selector>
364
342
  ```
365
343
 
366
- När detta är inställt kommer komponenten att visa ett felmeddelande om användaren klickar i och sedan lämnar fältet utan att göra ett giltigt val. Om `af-manual-input` istället är satt till `true` tillåts användaren att ange ett yrke manuellt via fritext.
344
+ När detta är inställt kommer komponenten att visa ett felmeddelande om användaren klickar i och sedan lämnar fältet utan att göra ett giltigt val. Om `af-manual-input` i stället är satt till `true` tillåts användaren att ange ett yrke manuellt via fritext.
367
345
  <br>
368
346
  #### Lyssna på valideringsstatus (`afJobValidationChange`)
369
347
 
@@ -23,6 +23,8 @@ const AfTag = ({ text, breakWords = false, onRemove }) => (index.h("span", { cla
23
23
  onRemove();
24
24
  } }, index.h("span", { class: { 'af-tag__text': true, 'af-tag__text--break': breakWords } }, text), index.h(AfIcon, { name: "x", class: "af-tag__remove-icon" }))));
25
25
 
26
+ /** Max antal tecken i sökfältet och därmed i ett manuellt val. Längsta begrepp i taxonomin är 90 tecken. */
27
+ const SELECTOR_INPUT_MAX_LENGTH = 120;
26
28
  function shouldShowManualInput(state, requireSelection = false) {
27
29
  if (!state || requireSelection)
28
30
  return false;
@@ -428,7 +430,7 @@ const CoreSelector = class {
428
430
  } }), index.h("div", { class: { 'input-area': true, 'has-value': !this.config.showSearchIcon || hasInput || hasTags } }, isSelected && (index.h("span", { class: "selected-text-in-box" }, displayValue)), !isSelected && !hasInput && this.config.placeholder && (index.h("span", { class: "selector-placeholder-overlay", "aria-hidden": "true" }, this.config.placeholder)), index.h("input", { class: {
429
431
  'selector-input-field': true,
430
432
  'visually-hidden-selected': isSelected
431
- }, ref: (el) => this.inputRef = el, id: `${this.componentId}-input`, type: "text", value: displayValue, onInput: (e) => {
433
+ }, ref: (el) => this.inputRef = el, id: `${this.componentId}-input`, type: "text", value: displayValue, maxLength: SELECTOR_INPUT_MAX_LENGTH, onInput: (e) => {
432
434
  if (this.config.disabled)
433
435
  return;
434
436
  this.isKeyboardNavigationActive = false;