@fristil/designsystem 0.4.0 → 0.5.1

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.
Files changed (116) hide show
  1. package/CHANGELOG.md +136 -0
  2. package/README.md +22 -7
  3. package/dist/components/frittstaende/connection-status/connection-status.d.ts +28 -0
  4. package/dist/components/frittstaende/connection-status/connection-status.d.ts.map +1 -0
  5. package/dist/components/frittstaende/connection-status/connection-status.js +22 -0
  6. package/dist/components/frittstaende/connection-status/connection-status.js.map +1 -0
  7. package/dist/components/frittstaende/connection-status/fs-connection-status.d.ts +54 -0
  8. package/dist/components/frittstaende/connection-status/fs-connection-status.d.ts.map +1 -0
  9. package/dist/components/frittstaende/connection-status/fs-connection-status.js +123 -0
  10. package/dist/components/frittstaende/connection-status/fs-connection-status.js.map +1 -0
  11. package/dist/components/frittstaende/session-timeout/fs-session-timeout.d.ts +56 -0
  12. package/dist/components/frittstaende/session-timeout/fs-session-timeout.d.ts.map +1 -0
  13. package/dist/components/frittstaende/session-timeout/fs-session-timeout.js +183 -0
  14. package/dist/components/frittstaende/session-timeout/fs-session-timeout.js.map +1 -0
  15. package/dist/components/frittstaende/session-timeout/session-timeout.d.ts +28 -0
  16. package/dist/components/frittstaende/session-timeout/session-timeout.d.ts.map +1 -0
  17. package/dist/components/frittstaende/session-timeout/session-timeout.js +22 -0
  18. package/dist/components/frittstaende/session-timeout/session-timeout.js.map +1 -0
  19. package/dist/components/frittstaende/toast/fs-toast.d.ts +16 -22
  20. package/dist/components/frittstaende/toast/fs-toast.d.ts.map +1 -1
  21. package/dist/components/frittstaende/toast/fs-toast.js +38 -27
  22. package/dist/components/frittstaende/toast/fs-toast.js.map +1 -1
  23. package/dist/components/frittstaende/toast/toast.d.ts +34 -0
  24. package/dist/components/frittstaende/toast/toast.d.ts.map +1 -0
  25. package/dist/components/frittstaende/toast/toast.js +26 -0
  26. package/dist/components/frittstaende/toast/toast.js.map +1 -0
  27. package/dist/components/ramme/error-summary/error-summary.d.ts +39 -0
  28. package/dist/components/ramme/error-summary/error-summary.d.ts.map +1 -0
  29. package/dist/components/ramme/error-summary/error-summary.js +31 -0
  30. package/dist/components/ramme/error-summary/error-summary.js.map +1 -0
  31. package/dist/components/ramme/error-summary/fs-error-summary.d.ts +16 -42
  32. package/dist/components/ramme/error-summary/fs-error-summary.d.ts.map +1 -1
  33. package/dist/components/ramme/error-summary/fs-error-summary.js +57 -92
  34. package/dist/components/ramme/error-summary/fs-error-summary.js.map +1 -1
  35. package/dist/components/ramme/field/field-core.d.ts +37 -0
  36. package/dist/components/ramme/field/field-core.d.ts.map +1 -1
  37. package/dist/components/ramme/field/field-core.js +37 -0
  38. package/dist/components/ramme/field/field-core.js.map +1 -1
  39. package/dist/components/ramme/field/fs-field.d.ts +39 -40
  40. package/dist/components/ramme/field/fs-field.d.ts.map +1 -1
  41. package/dist/components/ramme/field/fs-field.js +128 -54
  42. package/dist/components/ramme/field/fs-field.js.map +1 -1
  43. package/dist/components/ramme/popover/fs-popover.d.ts +20 -27
  44. package/dist/components/ramme/popover/fs-popover.d.ts.map +1 -1
  45. package/dist/components/ramme/popover/fs-popover.js +68 -54
  46. package/dist/components/ramme/popover/fs-popover.js.map +1 -1
  47. package/dist/components/ramme/popover/popover.d.ts +43 -0
  48. package/dist/components/ramme/popover/popover.d.ts.map +1 -0
  49. package/dist/components/ramme/popover/popover.js +49 -0
  50. package/dist/components/ramme/popover/popover.js.map +1 -0
  51. package/dist/components/ramme/suggestion/fs-suggestion.d.ts +75 -0
  52. package/dist/components/ramme/suggestion/fs-suggestion.d.ts.map +1 -0
  53. package/dist/components/ramme/suggestion/fs-suggestion.js +232 -0
  54. package/dist/components/ramme/suggestion/fs-suggestion.js.map +1 -0
  55. package/dist/components/ramme/suggestion/suggestion.d.ts +97 -0
  56. package/dist/components/ramme/suggestion/suggestion.d.ts.map +1 -0
  57. package/dist/components/ramme/suggestion/suggestion.js +79 -0
  58. package/dist/components/ramme/suggestion/suggestion.js.map +1 -0
  59. package/dist/components/ramme/tabs/fs-tabs.d.ts +31 -36
  60. package/dist/components/ramme/tabs/fs-tabs.d.ts.map +1 -1
  61. package/dist/components/ramme/tabs/fs-tabs.js +62 -84
  62. package/dist/components/ramme/tabs/fs-tabs.js.map +1 -1
  63. package/dist/components/ramme/tabs/tabs.d.ts +50 -0
  64. package/dist/components/ramme/tabs/tabs.d.ts.map +1 -0
  65. package/dist/components/ramme/tabs/tabs.js +54 -0
  66. package/dist/components/ramme/tabs/tabs.js.map +1 -0
  67. package/dist/fs.d.ts +94 -0
  68. package/dist/fs.d.ts.map +1 -1
  69. package/dist/fs.js +42 -0
  70. package/dist/fs.js.map +1 -1
  71. package/dist/index.d.ts +10 -3
  72. package/dist/index.d.ts.map +1 -1
  73. package/dist/index.js +10 -3
  74. package/dist/index.js.map +1 -1
  75. package/dist/jsx/react.d.ts +35 -50
  76. package/dist/jsx/react.d.ts.map +1 -1
  77. package/dist/react.d.ts +142 -1
  78. package/dist/react.d.ts.map +1 -1
  79. package/dist/react.js +77 -2
  80. package/dist/react.js.map +1 -1
  81. package/package.json +15 -18
  82. package/src/components/frittstaende/connection-status/connection-status.css +33 -0
  83. package/src/components/frittstaende/connection-status/connection-status.ts +41 -0
  84. package/src/components/frittstaende/connection-status/fs-connection-status.ts +144 -0
  85. package/src/components/frittstaende/session-timeout/fs-session-timeout.ts +216 -0
  86. package/src/components/frittstaende/session-timeout/session-timeout.css +43 -0
  87. package/src/components/frittstaende/session-timeout/session-timeout.ts +42 -0
  88. package/src/components/frittstaende/toast/fs-toast.ts +39 -30
  89. package/src/components/frittstaende/toast/toast.ts +45 -0
  90. package/src/components/ramme/error-summary/error-summary.ts +55 -0
  91. package/src/components/ramme/error-summary/fs-error-summary.ts +62 -119
  92. package/src/components/ramme/field/field-core.ts +38 -0
  93. package/src/components/ramme/field/fs-field.ts +145 -61
  94. package/src/components/ramme/popover/fs-popover.ts +78 -72
  95. package/src/components/ramme/popover/popover.ts +79 -0
  96. package/src/components/ramme/suggestion/fs-suggestion.ts +265 -0
  97. package/src/components/ramme/suggestion/suggestion.ts +105 -0
  98. package/src/components/ramme/tabs/fs-tabs.ts +67 -98
  99. package/src/components/ramme/tabs/tabs.ts +104 -0
  100. package/dist/components/frittstaende/calendar/fs-calendar.d.ts +0 -52
  101. package/dist/components/frittstaende/calendar/fs-calendar.d.ts.map +0 -1
  102. package/dist/components/frittstaende/calendar/fs-calendar.js +0 -462
  103. package/dist/components/frittstaende/calendar/fs-calendar.js.map +0 -1
  104. package/dist/components/frittstaende/date-field/fs-date-field.d.ts +0 -110
  105. package/dist/components/frittstaende/date-field/fs-date-field.d.ts.map +0 -1
  106. package/dist/components/frittstaende/date-field/fs-date-field.js +0 -264
  107. package/dist/components/frittstaende/date-field/fs-date-field.js.map +0 -1
  108. package/dist/components/frittstaende/suggestion/fs-suggestion.d.ts +0 -133
  109. package/dist/components/frittstaende/suggestion/fs-suggestion.d.ts.map +0 -1
  110. package/dist/components/frittstaende/suggestion/fs-suggestion.js +0 -280
  111. package/dist/components/frittstaende/suggestion/fs-suggestion.js.map +0 -1
  112. package/src/components/frittstaende/calendar/fs-calendar.ts +0 -525
  113. package/src/components/frittstaende/date-field/date-field.css +0 -54
  114. package/src/components/frittstaende/date-field/fs-date-field.ts +0 -309
  115. package/src/components/frittstaende/suggestion/fs-suggestion.ts +0 -333
  116. /package/src/components/{frittstaende → ramme}/suggestion/suggestion.css +0 -0
package/CHANGELOG.md CHANGED
@@ -16,6 +16,142 @@ kommer i et nytt undertall.
16
16
 
17
17
  ## Ikke utgitt
18
18
 
19
+ ## 0.5.1 (2026-09-21)
20
+
21
+ ### Rettet
22
+
23
+ - **React-inngangen døper nå også om `autocomplete` til `autoComplete`.**
24
+ `fs.suggestion()` sender det ut på kontrollen, og React advarte «Invalid DOM
25
+ property `autocomplete`» i konsollen for hvert forslagsfelt. En ny vaktpost
26
+ kaller hver byggefunksjon, teller opp hvert attributtnavn de sender ut, og
27
+ krever at ingen av dem er et navn React staver annerledes uten at
28
+ `react.ts` døper det om.
29
+
30
+ - **`<fs-session-timeout>` bygger dialogen sin først når den skal vises.** Den
31
+ lagde den i `connectedCallback`, altså før React rakk å hydrere, og
32
+ hydreringen feilet med «server rendered HTML didn't match the client». Nå
33
+ gjør den det samme som `<fs-toast>` og `<fs-connection-status>`: ingenting
34
+ står i DOM-en før det trengs.
35
+
36
+ ### Endret
37
+
38
+ - **`fs.toast()` er dokumentert.** Byggefunksjonen fantes, men sto ikke på
39
+ komponentsiden. Den gir tre attributtsett, og det er `region` du sprer på
40
+ `<fs-toast>`, ikke hele objektet.
41
+
42
+
43
+ ## 0.5.0 (2026-09-21)
44
+
45
+ ### Brytende
46
+
47
+ - **Serveren skriver markupen, komponentene fester bare oppførsel.** Seks
48
+ komponenter satte tidligere klasser, roller og tilgjengelighetskoblinger på
49
+ elementer serveren hadde sendt. Det virker ikke i en app med server-rendret
50
+ HTML: Datastars morfing fjerner hvert attributt som ikke står i HTML-en
51
+ serveren nettopp sendte, og React kan kaste bort noder et egendefinert
52
+ element har lagt inn i et tre React eier. Testet med ekte Datastar mistet et
53
+ `<fs-field>` både `aria-describedby`, klassen på ledeteksten og den skjulte
54
+ feilmeldingen etter én patch, og fikk dem ikke tilbake.
55
+
56
+ Markupen skrives nå av nye byggere i `fs`: `fs.errorSummary()`,
57
+ `fs.popover()`, `fs.tabs()`, `fs.suggestion()` og `fs.toast()`. Byggerne
58
+ setter også `data-preserve-attr` for de attributtene komponenten endrer
59
+ underveis, så du slipper å vite om det. Se «Server først» i dokumentasjonen.
60
+
61
+ - **`<fs-calendar>` og `<fs-date-field>` er fjernet.** Nettleserens eget panel
62
+ i `<input type="date">` gjør jobben, og `fs.field()` sammen med
63
+ `fs.input({ type: "date" })` gir et komplett datofelt. Mønstersiden «Dato i
64
+ et skjema» viser oppsettet, med de to forskjellene vi har testet mellom nettleserne.
65
+ `exports`-oppføringene `./calendar`, `./date-field` og `./date-field.css` er
66
+ borte, og det samme er `--fs-calendar-*`- og `--fs-date-field-*`-variablene
67
+ og alle `part`-navnene i kalenderen.
68
+
69
+ - **`<fs-suggestion>` er flyttet fra `frittstående` til `ramme`.** Den lagde
70
+ tidligere hele feltet selv, så det fantes verken ledetekst eller
71
+ inndatafelt før skriptet hadde kjørt, og ingenting ble med i innsendingen.
72
+ Nå skriver serveren feltet og lista med `fs.suggestion()`.
73
+
74
+ - **`<fs-tabs>` har ingen `selected`- eller `label`-attributter lenger.**
75
+ Hvilken fane som er valgt står i markupen serveren sendte. `<fs-error-summary>`
76
+ har ikke lenger `heading`: overskriften skrives av serveren.
77
+
78
+ - **Ingen komponent bruker shadow DOM.** `::part()` er dermed ikke lenger en
79
+ del av det offentlige API-et.
80
+
81
+ - **`<fs-field>` leser tilstanden fra markupen, ikke fra egne attributter.**
82
+ Skrev serveren feltet med `fs.field()`, står `aria-invalid` og
83
+ `data-required` allerede på elementene. Komponenten regnet tidligere ut sitt
84
+ eget svar fra attributtene på verten, fant ingenting der, og fjernet det
85
+ serveren nettopp hadde skrevet. De to halvdelene av API-et kranglet altså
86
+ med hverandre når de ble brukt sammen. Den setter heller ikke lenger
87
+ `aria-hidden` på feilmeldingen: `hidden` tar den allerede ut av
88
+ tilgjengelighetstreet, og attributtet ga hydreringsfeil i React.
89
+
90
+ ### Lagt til
91
+
92
+ - **`<fs-session-timeout>`** varsler før en innlogget økt går ut, med en
93
+ nedtelling som leses opp ved terskler i stedet for hvert sekund, og fokus
94
+ som går tilbake dit brukeren var.
95
+
96
+ - **`<fs-connection-status>`** sier fra når forbindelsen til serveren er
97
+ borte. `navigator.onLine` sier bare at maskinen har et nettverk, så
98
+ `reportFailure()` og `reportSuccess()` lar appen melde fra selv.
99
+
100
+ - **Siden «Server først»** forklarer hvorfor markupen kommer fra serveren, med
101
+ testene bak, og hva det betyr i TanStack Start, React Server Components og
102
+ Datastar.
103
+
104
+ - **Mønstersiden «Dato i et skjema»** viser hvordan du ber om en dato uten en
105
+ datovelger fra oss, med de to forskjellene vi har testet mellom nettleserne:
106
+ WebKit krever skilletegnene, og Chromium tar imot feil rekkefølge som
107
+ gyldig.
108
+
109
+ - **`FIELD_PRESERVED_ATTRIBUTES`** er lista serveren skal skrive som
110
+ `data-preserve-attr` når den ikke kan kalle `fs.field()` selv.
111
+
112
+ ### Rettet
113
+
114
+ - **`<fs-toast duration="0">` lot ikke meldingene bli stående.** Attributtet
115
+ ble lest som «ugyldig» og falt tilbake til seks sekunder, så bare
116
+ `show(…, { duration: 0 })` virket.
117
+
118
+ - **`<fs-error-summary>` fikk ikke fokus når serveren bare tok bort `hidden`.**
119
+ Komponenten så etter endringer i barna, ikke i attributtene, så en
120
+ oppsummering som nettopp ble synlig ble stående uten fokus.
121
+
122
+ - **`<fs-error-summary>` finner nå feltet i sin egen rot.** Oppslaget gikk mot
123
+ `document`, som ikke ser inn i en skyggerot, så lenken ble en vanlig
124
+ ankerlenke uten fokusflytting når skjemaet lå inne i en annen komponent.
125
+
126
+ - **`FIELD_PRESERVED_ATTRIBUTES` dekker alle tre elementene.** Den dekket bare
127
+ kontrollen, men komponenten legger også `fs-label` og markeringene på
128
+ ledeteksten og skjuler feilmeldingen. Serveren må derfor skrive én liste per
129
+ element, og konstanten har nå `label`, `control` og `error`.
130
+
131
+ - **`<fs-popover>` lot seg ikke åpne etter at den var flyttet i DOM-en.**
132
+ Referansen til knappen ble stående, så lytteren ble aldri festet på nytt.
133
+
134
+ - **`fs.popover({ open: true })` sier det nå på verten.** Før satte den bare
135
+ `aria-expanded` på knappen, så markupen meldte at panelet var åpent mens
136
+ komponenten mente det var lukket.
137
+
138
+ - **`<fs-suggestion>` mistet musevalg etter at serveren sendte en ny liste.**
139
+ Alternativene fikk bare lytteren sin når selve feltet var nytt.
140
+
141
+ ### Endret
142
+
143
+ - **React-inngangen døper også om `tabindex` til `tabIndex`,** og dekker de nye
144
+ sammensatte byggerne. `fs.errorSummary()`, `fs.popover()`, `fs.tabs()`,
145
+ `fs.suggestion()` og `fs.toast()` finnes nå også i
146
+ `@fristil/designsystem/react`, der hvert attributtsett er døpt om for seg.
147
+ Pakken har fortsatt ingen avhengighet til React: dette er ren omdøping av
148
+ tre objektnøkler.
149
+
150
+ - **`lit` er ikke lenger en avhengighet.** Etter omleggingen rendrer ingen
151
+ komponent sitt eget innhold, så Lit ble brukt til nesten ingenting.
152
+ Komponentene er vanlige `HTMLElement`-klasser, og pakken har nå ingen
153
+ avhengigheter i det hele tatt.
154
+
19
155
  ## 0.4.0 (2026-09-21)
20
156
 
21
157
  ### Endret
package/README.md CHANGED
@@ -12,9 +12,7 @@ Hele dokumentasjonen, med komponentsider, tokens, mønstre og eksempler for fire
12
12
  npm install @fristil/designsystem
13
13
  ```
14
14
 
15
- Pakken har én avhengighet, `lit`, og den installeres sammen med pakken. Komponentene som er web components er bygd den.
16
-
17
- Den koster rundt 9,8 kB gzippet, og bare for den som registrerer minst én web component. Bruker du bare CSS-komponentene, havner Lit aldri i bunten din: ingenting registreres ved import alene, så den kommer først med når du kaller en `defineFs*`.
15
+ Pakken har ingen avhengigheter. Web-komponentene er vanlige `HTMLElement`-klasser, og ingenting registreres ved import alene, du betaler bare for det du faktisk kaller.
18
16
 
19
17
  ## CSS-komponenter
20
18
 
@@ -54,17 +52,34 @@ import { fs } from "@fristil/designsystem/react"
54
52
  Ingenting registreres ved import alene. Du kaller `defineFs*` selv, så du bestemmer når elementet finnes og hva det skal hete:
55
53
 
56
54
  ```js
57
- import { defineFsDateField } from "@fristil/designsystem/date-field"
55
+ import { defineFsSessionTimeout } from "@fristil/designsystem/session-timeout"
58
56
  import "@fristil/designsystem/tokens.css"
59
- import "@fristil/designsystem/date-field.css"
57
+ import "@fristil/designsystem/session-timeout.css"
60
58
 
61
- defineFsDateField()
59
+ defineFsSessionTimeout()
62
60
  ```
63
61
 
64
62
  ```html
65
- <fs-date-field label="Fødselsdato" value="2026-05-31"></fs-date-field>
63
+ <fs-session-timeout class="fs-session-timeout" warn-at="1500" expires-at="1800"
64
+ data-ignore-morph></fs-session-timeout>
65
+ ```
66
+
67
+ ## Serveren skriver markupen
68
+
69
+ Fristil er bygget for apper der HTML-en kommer fra serveren, enten det er TanStack Start, React Server Components eller Datastar. Ingen komponent rendrer sitt eget innhold i DOM serveren eier, fordi rammeverket rundt da river det bort igjen ved neste oppdatering.
70
+
71
+ Byggerne i `fs` gir markupen, komponentene gir oppførselen, og de to overlapper ikke:
72
+
73
+ ```js
74
+ import { fs } from "@fristil/designsystem"
75
+
76
+ fs.errorSummary({ count: 2, id: "feil" })
77
+ // { container: { class: "fs-error-summary", role: "alert", tabindex: "-1", id: "feil" },
78
+ // title: { class: "fs-error-summary__title" } }
66
79
  ```
67
80
 
81
+ Hele begrunnelsen, med testene bak, står på [Markup og oppførsel](https://fristil.netlify.app/markup-og-oppforsel/).
82
+
68
83
  ## Eget fargetema
69
84
 
70
85
  Kommandolinja lager et fullt tema av merkefargene dine, med kontrastkravene regnet ut i OKLCH:
@@ -0,0 +1,28 @@
1
+ export declare const CONNECTION_STATUS_CLASS: "fs-connection-status";
2
+ export declare const CONNECTION_STATUS_BAR_CLASS: "fs-connection-status__bar";
3
+ export type ConnectionStatusOptions = {
4
+ /** Teksten når forbindelsen er borte. */
5
+ offlineText?: string;
6
+ /** Teksten når den kommer tilbake. Vises en kort stund. */
7
+ onlineText?: string;
8
+ };
9
+ export type ConnectionStatusAttributes = {
10
+ class: typeof CONNECTION_STATUS_CLASS;
11
+ "offline-text"?: string;
12
+ "online-text"?: string;
13
+ "data-ignore-morph": "";
14
+ };
15
+ /**
16
+ * Attributtene for linja som sier fra at forbindelsen er borte.
17
+ *
18
+ * Serveren kan per definisjon ikke fortelle deg at den er utilgjengelig. Er
19
+ * den nede, kommer det ingenting derfra å rendre. Derfor eier komponenten
20
+ * alt innholdet, og `data-ignore-morph` hindrer at en senere patch river det
21
+ * bort i det øyeblikket forbindelsen er tilbake.
22
+ *
23
+ * ```ts
24
+ * <fs-connection-status {...fs.connectionStatus()} />
25
+ * ```
26
+ */
27
+ export declare const connectionStatus: ({ offlineText, onlineText, }?: ConnectionStatusOptions) => ConnectionStatusAttributes;
28
+ //# sourceMappingURL=connection-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection-status.d.ts","sourceRoot":"","sources":["../../../../src/components/frittstaende/connection-status/connection-status.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,uBAAuB,EAAG,sBAA+B,CAAA;AACtE,eAAO,MAAM,2BAA2B,EAAG,2BAAoC,CAAA;AAE/E,MAAM,MAAM,uBAAuB,GAAG;IACpC,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC,KAAK,EAAE,OAAO,uBAAuB,CAAA;IACrC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,mBAAmB,EAAE,EAAE,CAAA;CACxB,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,GAAI,+BAG9B,uBAA4B,KAAG,0BAM9B,CAAA"}
@@ -0,0 +1,22 @@
1
+ import { attributes } from "../../css/shared.js";
2
+ export const CONNECTION_STATUS_CLASS = "fs-connection-status";
3
+ export const CONNECTION_STATUS_BAR_CLASS = "fs-connection-status__bar";
4
+ /**
5
+ * Attributtene for linja som sier fra at forbindelsen er borte.
6
+ *
7
+ * Serveren kan per definisjon ikke fortelle deg at den er utilgjengelig. Er
8
+ * den nede, kommer det ingenting derfra å rendre. Derfor eier komponenten
9
+ * alt innholdet, og `data-ignore-morph` hindrer at en senere patch river det
10
+ * bort i det øyeblikket forbindelsen er tilbake.
11
+ *
12
+ * ```ts
13
+ * <fs-connection-status {...fs.connectionStatus()} />
14
+ * ```
15
+ */
16
+ export const connectionStatus = ({ offlineText, onlineText, } = {}) => attributes({
17
+ class: CONNECTION_STATUS_CLASS,
18
+ "offline-text": offlineText,
19
+ "online-text": onlineText,
20
+ "data-ignore-morph": "",
21
+ });
22
+ //# sourceMappingURL=connection-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection-status.js","sourceRoot":"","sources":["../../../../src/components/frittstaende/connection-status/connection-status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAEhD,MAAM,CAAC,MAAM,uBAAuB,GAAG,sBAA+B,CAAA;AACtE,MAAM,CAAC,MAAM,2BAA2B,GAAG,2BAAoC,CAAA;AAgB/E;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,EAC/B,WAAW,EACX,UAAU,MACiB,EAAE,EAA8B,EAAE,CAC7D,UAAU,CAAC;IACT,KAAK,EAAE,uBAAuB;IAC9B,cAAc,EAAE,WAAW;IAC3B,aAAa,EAAE,UAAU;IACzB,mBAAmB,EAAE,EAAW;CACjC,CAAC,CAAA"}
@@ -0,0 +1,54 @@
1
+ export declare const FS_CONNECTION_STATUS_TAG: "fs-connection-status";
2
+ /**
3
+ * Sier fra når forbindelsen til serveren er borte.
4
+ *
5
+ * Serveren kan per definisjon ikke fortelle deg dette. Er den utilgjengelig,
6
+ * kommer det ingenting derfra. Derfor er dette en frittstående komponent som
7
+ * eier alt innholdet sitt.
8
+ *
9
+ * Den er ikke pynt i en app som henter innhold fra serveren underveis. En
10
+ * side som mister strømmen sin ser helt normal ut, men er frosset, og en
11
+ * bruker som fyller ut et skjema inn i en død forbindelse mister alt.
12
+ *
13
+ * `navigator.onLine` sier bare om maskinen har et nettverk, ikke om serveren
14
+ * svarer. Derfor finnes `reportFailure()` og `reportSuccess()`, som appen
15
+ * kaller når et kall feiler eller lykkes.
16
+ *
17
+ * ```ts
18
+ * const status = document.querySelector("fs-connection-status")
19
+ * try {
20
+ * await fetch("/api/lagre", { method: "POST", body })
21
+ * status.reportSuccess()
22
+ * } catch {
23
+ * status.reportFailure()
24
+ * }
25
+ * ```
26
+ */
27
+ export declare class FsConnectionStatus extends HTMLElement {
28
+ static observedAttributes: string[];
29
+ private bar?;
30
+ private timer?;
31
+ /** Sant når appen har meldt at et kall feilet, uavhengig av navigator. */
32
+ private failing;
33
+ get offlineText(): string;
34
+ get onlineText(): string;
35
+ connectedCallback(): void;
36
+ disconnectedCallback(): void;
37
+ private ensureBar;
38
+ private showOffline;
39
+ private showOnline;
40
+ private handleOffline;
41
+ private handleOnline;
42
+ private emit;
43
+ /** Meld fra at et kall til serveren feilet. */
44
+ reportFailure(): void;
45
+ /** Meld fra at et kall til serveren lyktes igjen. */
46
+ reportSuccess(): void;
47
+ }
48
+ declare global {
49
+ interface HTMLElementTagNameMap {
50
+ "fs-connection-status": FsConnectionStatus;
51
+ }
52
+ }
53
+ export declare function defineFsConnectionStatus(tagName?: "fs-connection-status"): void;
54
+ //# sourceMappingURL=fs-connection-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-connection-status.d.ts","sourceRoot":"","sources":["../../../../src/components/frittstaende/connection-status/fs-connection-status.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,wBAAwB,EAAG,sBAA+B,CAAA;AAQvE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,kBAAmB,SAAQ,WAAW;IACjD,MAAM,CAAC,kBAAkB,WAAkC;IAE3D,OAAO,CAAC,GAAG,CAAC,CAAa;IACzB,OAAO,CAAC,KAAK,CAAC,CAAQ;IACtB,0EAA0E;IAC1E,OAAO,CAAC,OAAO,CAAQ;IAEvB,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,iBAAiB,IAAI,IAAI;IAOzB,oBAAoB,IAAI,IAAI;IAO5B,OAAO,CAAC,SAAS;IAcjB,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,UAAU;IAalB,OAAO,CAAC,aAAa,CAEpB;IAED,OAAO,CAAC,YAAY,CAGnB;IAED,OAAO,CAAC,IAAI;IAIZ,+CAA+C;IAC/C,aAAa,IAAI,IAAI;IAMrB,qDAAqD;IACrD,aAAa,IAAI,IAAI;CAKtB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,sBAAsB,EAAE,kBAAkB,CAAA;KAC3C;CACF;AAED,wBAAgB,wBAAwB,CACtC,OAAO,yBAA2B,GACjC,IAAI,CAIN"}
@@ -0,0 +1,123 @@
1
+ import { CONNECTION_STATUS_BAR_CLASS, CONNECTION_STATUS_CLASS, } from "./connection-status.js";
2
+ export const FS_CONNECTION_STATUS_TAG = "fs-connection-status";
3
+ const STANDARD_OFFLINE = "Ingen forbindelse. Det du skriver blir ikke lagret.";
4
+ const STANDARD_ONLINE = "Forbindelsen er tilbake.";
5
+ /** Hvor lenge «tilbake på nett» blir stående. */
6
+ const KVITTERING_MS = 4000;
7
+ /**
8
+ * Sier fra når forbindelsen til serveren er borte.
9
+ *
10
+ * Serveren kan per definisjon ikke fortelle deg dette. Er den utilgjengelig,
11
+ * kommer det ingenting derfra. Derfor er dette en frittstående komponent som
12
+ * eier alt innholdet sitt.
13
+ *
14
+ * Den er ikke pynt i en app som henter innhold fra serveren underveis. En
15
+ * side som mister strømmen sin ser helt normal ut, men er frosset, og en
16
+ * bruker som fyller ut et skjema inn i en død forbindelse mister alt.
17
+ *
18
+ * `navigator.onLine` sier bare om maskinen har et nettverk, ikke om serveren
19
+ * svarer. Derfor finnes `reportFailure()` og `reportSuccess()`, som appen
20
+ * kaller når et kall feiler eller lykkes.
21
+ *
22
+ * ```ts
23
+ * const status = document.querySelector("fs-connection-status")
24
+ * try {
25
+ * await fetch("/api/lagre", { method: "POST", body })
26
+ * status.reportSuccess()
27
+ * } catch {
28
+ * status.reportFailure()
29
+ * }
30
+ * ```
31
+ */
32
+ export class FsConnectionStatus extends HTMLElement {
33
+ constructor() {
34
+ super(...arguments);
35
+ /** Sant når appen har meldt at et kall feilet, uavhengig av navigator. */
36
+ this.failing = false;
37
+ this.handleOffline = () => {
38
+ this.showOffline();
39
+ };
40
+ this.handleOnline = () => {
41
+ if (this.failing)
42
+ return;
43
+ this.showOnline();
44
+ };
45
+ }
46
+ get offlineText() {
47
+ return this.getAttribute("offline-text") ?? STANDARD_OFFLINE;
48
+ }
49
+ get onlineText() {
50
+ return this.getAttribute("online-text") ?? STANDARD_ONLINE;
51
+ }
52
+ connectedCallback() {
53
+ this.classList.add(CONNECTION_STATUS_CLASS);
54
+ window.addEventListener("offline", this.handleOffline);
55
+ window.addEventListener("online", this.handleOnline);
56
+ if (!navigator.onLine)
57
+ this.showOffline();
58
+ }
59
+ disconnectedCallback() {
60
+ window.removeEventListener("offline", this.handleOffline);
61
+ window.removeEventListener("online", this.handleOnline);
62
+ if (this.timer)
63
+ window.clearTimeout(this.timer);
64
+ this.timer = undefined;
65
+ }
66
+ ensureBar() {
67
+ if (this.bar)
68
+ return this.bar;
69
+ const bar = document.createElement("div");
70
+ bar.className = CONNECTION_STATUS_BAR_CLASS;
71
+ // polite og ikke assertive: beskjeden er viktig, men skal ikke avbryte
72
+ // midt i et ord. Den blir stående til forbindelsen er tilbake.
73
+ bar.setAttribute("role", "status");
74
+ bar.setAttribute("aria-live", "polite");
75
+ this.append(bar);
76
+ this.bar = bar;
77
+ return bar;
78
+ }
79
+ showOffline() {
80
+ if (this.timer)
81
+ window.clearTimeout(this.timer);
82
+ const bar = this.ensureBar();
83
+ bar.dataset.state = "offline";
84
+ bar.textContent = this.offlineText;
85
+ this.emit("connection-lost");
86
+ }
87
+ showOnline() {
88
+ if (!this.bar)
89
+ return;
90
+ const bar = this.bar;
91
+ bar.dataset.state = "online";
92
+ bar.textContent = this.onlineText;
93
+ this.emit("connection-restored");
94
+ this.timer = window.setTimeout(() => {
95
+ bar.remove();
96
+ this.bar = undefined;
97
+ }, KVITTERING_MS);
98
+ }
99
+ emit(navn) {
100
+ this.dispatchEvent(new CustomEvent(navn, { bubbles: true, composed: true }));
101
+ }
102
+ /** Meld fra at et kall til serveren feilet. */
103
+ reportFailure() {
104
+ if (this.failing)
105
+ return;
106
+ this.failing = true;
107
+ this.showOffline();
108
+ }
109
+ /** Meld fra at et kall til serveren lyktes igjen. */
110
+ reportSuccess() {
111
+ if (!this.failing)
112
+ return;
113
+ this.failing = false;
114
+ this.showOnline();
115
+ }
116
+ }
117
+ FsConnectionStatus.observedAttributes = ["offline-text", "online-text"];
118
+ export function defineFsConnectionStatus(tagName = FS_CONNECTION_STATUS_TAG) {
119
+ if (!customElements.get(tagName)) {
120
+ customElements.define(tagName, FsConnectionStatus);
121
+ }
122
+ }
123
+ //# sourceMappingURL=fs-connection-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-connection-status.js","sourceRoot":"","sources":["../../../../src/components/frittstaende/connection-status/fs-connection-status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ export declare const FS_SESSION_TIMEOUT_TAG: "fs-session-timeout";
2
+ /**
3
+ * Varsler før en innlogget økt går ut.
4
+ *
5
+ * Dette er tingen hver store organisasjon bygger selv og gjør feil. Enten
6
+ * kommer det ingen advarsel, og brukeren mister et halvutfylt søknadsskjema,
7
+ * eller så stjeler dialogen fokus midt i en setning, eller så leser
8
+ * skjermleseren nedtellingen hvert sekund.
9
+ *
10
+ * Komponenten er frittstående fordi nedtellingen er klientens klokke. Tallet
11
+ * endrer seg ut fra når brukeren sist rørte tastaturet, og det er ingenting
12
+ * en server kan sende. Den bærer heller ingen verdi inn i en innsending.
13
+ *
14
+ * Dialogen er en ekte `<dialog>` med `showModal()`, så fokusfellen, Escape og
15
+ * topplaget kommer fra nettleseren. Fokus går tilbake dit brukeren var.
16
+ *
17
+ * ```html
18
+ * <fs-session-timeout class="fs-session-timeout" warn-at="1500" expires-at="1800"
19
+ * data-ignore-morph></fs-session-timeout>
20
+ * ```
21
+ *
22
+ * ```ts
23
+ * document.querySelector("fs-session-timeout")
24
+ * .addEventListener("session-extend", () => fetch("/forleng", { method: "POST" }))
25
+ * ```
26
+ */
27
+ export declare class FsSessionTimeout extends HTMLElement {
28
+ static observedAttributes: string[];
29
+ private dialog?;
30
+ private countElement?;
31
+ private liveElement?;
32
+ private ticker?;
33
+ private lastActivity;
34
+ private forrigeFokus;
35
+ /** Sekunder uten aktivitet før varselet kommer. */
36
+ get warnAt(): number;
37
+ /** Sekunder uten aktivitet før økten er ute. */
38
+ get expiresAt(): number;
39
+ connectedCallback(): void;
40
+ disconnectedCallback(): void;
41
+ private build;
42
+ private registerActivity;
43
+ private tick;
44
+ private open;
45
+ private close;
46
+ private emit;
47
+ /** Forlenger økten og lukker varselet. Kall den når serveren har svart. */
48
+ extend(): void;
49
+ }
50
+ declare global {
51
+ interface HTMLElementTagNameMap {
52
+ "fs-session-timeout": FsSessionTimeout;
53
+ }
54
+ }
55
+ export declare function defineFsSessionTimeout(tagName?: "fs-session-timeout"): void;
56
+ //# sourceMappingURL=fs-session-timeout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-session-timeout.d.ts","sourceRoot":"","sources":["../../../../src/components/frittstaende/session-timeout/fs-session-timeout.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,sBAAsB,EAAG,oBAA6B,CAAA;AAmBnE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,gBAAiB,SAAQ,WAAW;IAC/C,MAAM,CAAC,kBAAkB,WAA4B;IAErD,OAAO,CAAC,MAAM,CAAC,CAAmB;IAClC,OAAO,CAAC,YAAY,CAAC,CAAa;IAClC,OAAO,CAAC,WAAW,CAAC,CAAa;IACjC,OAAO,CAAC,MAAM,CAAC,CAAQ;IACvB,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,YAAY,CAA2B;IAE/C,mDAAmD;IACnD,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,gDAAgD;IAChD,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,iBAAiB,IAAI,IAAI;IAazB,oBAAoB,IAAI,IAAI;IAQ5B,OAAO,CAAC,KAAK;IA2Db,OAAO,CAAC,gBAAgB,CAGvB;IAED,OAAO,CAAC,IAAI;IAqBZ,OAAO,CAAC,IAAI;IAUZ,OAAO,CAAC,KAAK;IAQb,OAAO,CAAC,IAAI;IAIZ,2EAA2E;IAC3E,MAAM,IAAI,IAAI;CAKf;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,oBAAoB,EAAE,gBAAgB,CAAA;KACvC;CACF;AAED,wBAAgB,sBAAsB,CAAC,OAAO,uBAAyB,GAAG,IAAI,CAI7E"}