@fristil/designsystem 0.2.0

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 (314) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/LICENSE +21 -0
  3. package/README.md +101 -0
  4. package/dist/cli.d.ts +31 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +261 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/components/css/accordion/accordion.d.ts +37 -0
  9. package/dist/components/css/accordion/accordion.d.ts.map +1 -0
  10. package/dist/components/css/accordion/accordion.js +31 -0
  11. package/dist/components/css/accordion/accordion.js.map +1 -0
  12. package/dist/components/css/alert/alert.d.ts +35 -0
  13. package/dist/components/css/alert/alert.d.ts.map +1 -0
  14. package/dist/components/css/alert/alert.js +29 -0
  15. package/dist/components/css/alert/alert.js.map +1 -0
  16. package/dist/components/css/avatar/avatar.d.ts +40 -0
  17. package/dist/components/css/avatar/avatar.d.ts.map +1 -0
  18. package/dist/components/css/avatar/avatar.js +30 -0
  19. package/dist/components/css/avatar/avatar.js.map +1 -0
  20. package/dist/components/css/badge/badge.d.ts +24 -0
  21. package/dist/components/css/badge/badge.d.ts.map +1 -0
  22. package/dist/components/css/badge/badge.js +24 -0
  23. package/dist/components/css/badge/badge.js.map +1 -0
  24. package/dist/components/css/breadcrumbs/breadcrumbs.d.ts +25 -0
  25. package/dist/components/css/breadcrumbs/breadcrumbs.d.ts.map +1 -0
  26. package/dist/components/css/breadcrumbs/breadcrumbs.js +23 -0
  27. package/dist/components/css/breadcrumbs/breadcrumbs.js.map +1 -0
  28. package/dist/components/css/button/button.d.ts +26 -0
  29. package/dist/components/css/button/button.d.ts.map +1 -0
  30. package/dist/components/css/button/button.js +25 -0
  31. package/dist/components/css/button/button.js.map +1 -0
  32. package/dist/components/css/card/card.d.ts +36 -0
  33. package/dist/components/css/card/card.d.ts.map +1 -0
  34. package/dist/components/css/card/card.js +28 -0
  35. package/dist/components/css/card/card.js.map +1 -0
  36. package/dist/components/css/checkbox/checkbox.d.ts +32 -0
  37. package/dist/components/css/checkbox/checkbox.d.ts.map +1 -0
  38. package/dist/components/css/checkbox/checkbox.js +27 -0
  39. package/dist/components/css/checkbox/checkbox.js.map +1 -0
  40. package/dist/components/css/dialog/dialog.d.ts +30 -0
  41. package/dist/components/css/dialog/dialog.d.ts.map +1 -0
  42. package/dist/components/css/dialog/dialog.js +28 -0
  43. package/dist/components/css/dialog/dialog.js.map +1 -0
  44. package/dist/components/css/divider/divider.d.ts +28 -0
  45. package/dist/components/css/divider/divider.d.ts.map +1 -0
  46. package/dist/components/css/divider/divider.js +22 -0
  47. package/dist/components/css/divider/divider.js.map +1 -0
  48. package/dist/components/css/error-text/error-text.d.ts +24 -0
  49. package/dist/components/css/error-text/error-text.d.ts.map +1 -0
  50. package/dist/components/css/error-text/error-text.js +18 -0
  51. package/dist/components/css/error-text/error-text.js.map +1 -0
  52. package/dist/components/css/fieldset/fieldset.d.ts +55 -0
  53. package/dist/components/css/fieldset/fieldset.d.ts.map +1 -0
  54. package/dist/components/css/fieldset/fieldset.js +39 -0
  55. package/dist/components/css/fieldset/fieldset.js.map +1 -0
  56. package/dist/components/css/file-upload/file-upload.d.ts +41 -0
  57. package/dist/components/css/file-upload/file-upload.d.ts.map +1 -0
  58. package/dist/components/css/file-upload/file-upload.js +32 -0
  59. package/dist/components/css/file-upload/file-upload.js.map +1 -0
  60. package/dist/components/css/heading/heading.d.ts +29 -0
  61. package/dist/components/css/heading/heading.d.ts.map +1 -0
  62. package/dist/components/css/heading/heading.js +23 -0
  63. package/dist/components/css/heading/heading.js.map +1 -0
  64. package/dist/components/css/help-text/help-text.d.ts +24 -0
  65. package/dist/components/css/help-text/help-text.d.ts.map +1 -0
  66. package/dist/components/css/help-text/help-text.js +23 -0
  67. package/dist/components/css/help-text/help-text.js.map +1 -0
  68. package/dist/components/css/input/input.d.ts +39 -0
  69. package/dist/components/css/input/input.d.ts.map +1 -0
  70. package/dist/components/css/input/input.js +44 -0
  71. package/dist/components/css/input/input.js.map +1 -0
  72. package/dist/components/css/label/label.d.ts +33 -0
  73. package/dist/components/css/label/label.d.ts.map +1 -0
  74. package/dist/components/css/label/label.js +23 -0
  75. package/dist/components/css/label/label.js.map +1 -0
  76. package/dist/components/css/link/link.d.ts +21 -0
  77. package/dist/components/css/link/link.d.ts.map +1 -0
  78. package/dist/components/css/link/link.js +14 -0
  79. package/dist/components/css/link/link.js.map +1 -0
  80. package/dist/components/css/list/list.d.ts +29 -0
  81. package/dist/components/css/list/list.d.ts.map +1 -0
  82. package/dist/components/css/list/list.js +23 -0
  83. package/dist/components/css/list/list.js.map +1 -0
  84. package/dist/components/css/pagination/pagination.d.ts +27 -0
  85. package/dist/components/css/pagination/pagination.d.ts.map +1 -0
  86. package/dist/components/css/pagination/pagination.js +25 -0
  87. package/dist/components/css/pagination/pagination.js.map +1 -0
  88. package/dist/components/css/paragraph/paragraph.d.ts +36 -0
  89. package/dist/components/css/paragraph/paragraph.d.ts.map +1 -0
  90. package/dist/components/css/paragraph/paragraph.js +26 -0
  91. package/dist/components/css/paragraph/paragraph.js.map +1 -0
  92. package/dist/components/css/radio/radio.d.ts +32 -0
  93. package/dist/components/css/radio/radio.d.ts.map +1 -0
  94. package/dist/components/css/radio/radio.js +27 -0
  95. package/dist/components/css/radio/radio.js.map +1 -0
  96. package/dist/components/css/search/search.d.ts +33 -0
  97. package/dist/components/css/search/search.d.ts.map +1 -0
  98. package/dist/components/css/search/search.js +31 -0
  99. package/dist/components/css/search/search.js.map +1 -0
  100. package/dist/components/css/select/select.d.ts +23 -0
  101. package/dist/components/css/select/select.d.ts.map +1 -0
  102. package/dist/components/css/select/select.js +18 -0
  103. package/dist/components/css/select/select.js.map +1 -0
  104. package/dist/components/css/shared.d.ts +26 -0
  105. package/dist/components/css/shared.d.ts.map +1 -0
  106. package/dist/components/css/shared.js +34 -0
  107. package/dist/components/css/shared.js.map +1 -0
  108. package/dist/components/css/skeleton/skeleton.d.ts +29 -0
  109. package/dist/components/css/skeleton/skeleton.d.ts.map +1 -0
  110. package/dist/components/css/skeleton/skeleton.js +23 -0
  111. package/dist/components/css/skeleton/skeleton.js.map +1 -0
  112. package/dist/components/css/skip-link/skip-link.d.ts +18 -0
  113. package/dist/components/css/skip-link/skip-link.d.ts.map +1 -0
  114. package/dist/components/css/skip-link/skip-link.js +16 -0
  115. package/dist/components/css/skip-link/skip-link.js.map +1 -0
  116. package/dist/components/css/spinner/spinner.d.ts +33 -0
  117. package/dist/components/css/spinner/spinner.d.ts.map +1 -0
  118. package/dist/components/css/spinner/spinner.js +25 -0
  119. package/dist/components/css/spinner/spinner.js.map +1 -0
  120. package/dist/components/css/sr-only/sr-only.d.ts +17 -0
  121. package/dist/components/css/sr-only/sr-only.d.ts.map +1 -0
  122. package/dist/components/css/sr-only/sr-only.js +14 -0
  123. package/dist/components/css/sr-only/sr-only.js.map +1 -0
  124. package/dist/components/css/switch/switch.d.ts +33 -0
  125. package/dist/components/css/switch/switch.d.ts.map +1 -0
  126. package/dist/components/css/switch/switch.js +29 -0
  127. package/dist/components/css/switch/switch.js.map +1 -0
  128. package/dist/components/css/table/table.d.ts +36 -0
  129. package/dist/components/css/table/table.d.ts.map +1 -0
  130. package/dist/components/css/table/table.js +28 -0
  131. package/dist/components/css/table/table.js.map +1 -0
  132. package/dist/components/css/tag/tag.d.ts +35 -0
  133. package/dist/components/css/tag/tag.d.ts.map +1 -0
  134. package/dist/components/css/tag/tag.js +27 -0
  135. package/dist/components/css/tag/tag.js.map +1 -0
  136. package/dist/components/css/textarea/textarea.d.ts +23 -0
  137. package/dist/components/css/textarea/textarea.d.ts.map +1 -0
  138. package/dist/components/css/textarea/textarea.js +18 -0
  139. package/dist/components/css/textarea/textarea.js.map +1 -0
  140. package/dist/components/css/toggle-group/toggle-group.d.ts +31 -0
  141. package/dist/components/css/toggle-group/toggle-group.d.ts.map +1 -0
  142. package/dist/components/css/toggle-group/toggle-group.js +29 -0
  143. package/dist/components/css/toggle-group/toggle-group.js.map +1 -0
  144. package/dist/components/css/tooltip/tooltip.d.ts +30 -0
  145. package/dist/components/css/tooltip/tooltip.d.ts.map +1 -0
  146. package/dist/components/css/tooltip/tooltip.js +28 -0
  147. package/dist/components/css/tooltip/tooltip.js.map +1 -0
  148. package/dist/components/frittstaende/calendar/fs-calendar.d.ts +52 -0
  149. package/dist/components/frittstaende/calendar/fs-calendar.d.ts.map +1 -0
  150. package/dist/components/frittstaende/calendar/fs-calendar.js +462 -0
  151. package/dist/components/frittstaende/calendar/fs-calendar.js.map +1 -0
  152. package/dist/components/frittstaende/date-field/fs-date-field.d.ts +110 -0
  153. package/dist/components/frittstaende/date-field/fs-date-field.d.ts.map +1 -0
  154. package/dist/components/frittstaende/date-field/fs-date-field.js +264 -0
  155. package/dist/components/frittstaende/date-field/fs-date-field.js.map +1 -0
  156. package/dist/components/frittstaende/suggestion/fs-suggestion.d.ts +133 -0
  157. package/dist/components/frittstaende/suggestion/fs-suggestion.d.ts.map +1 -0
  158. package/dist/components/frittstaende/suggestion/fs-suggestion.js +280 -0
  159. package/dist/components/frittstaende/suggestion/fs-suggestion.js.map +1 -0
  160. package/dist/components/frittstaende/toast/fs-toast.d.ts +67 -0
  161. package/dist/components/frittstaende/toast/fs-toast.d.ts.map +1 -0
  162. package/dist/components/frittstaende/toast/fs-toast.js +108 -0
  163. package/dist/components/frittstaende/toast/fs-toast.js.map +1 -0
  164. package/dist/components/ramme/error-summary/fs-error-summary.d.ts +70 -0
  165. package/dist/components/ramme/error-summary/fs-error-summary.d.ts.map +1 -0
  166. package/dist/components/ramme/error-summary/fs-error-summary.js +155 -0
  167. package/dist/components/ramme/error-summary/fs-error-summary.js.map +1 -0
  168. package/dist/components/ramme/field/field-core.d.ts +70 -0
  169. package/dist/components/ramme/field/field-core.d.ts.map +1 -0
  170. package/dist/components/ramme/field/field-core.js +60 -0
  171. package/dist/components/ramme/field/field-core.js.map +1 -0
  172. package/dist/components/ramme/field/fs-field.d.ts +49 -0
  173. package/dist/components/ramme/field/fs-field.d.ts.map +1 -0
  174. package/dist/components/ramme/field/fs-field.js +118 -0
  175. package/dist/components/ramme/field/fs-field.js.map +1 -0
  176. package/dist/components/ramme/popover/fs-popover.d.ts +68 -0
  177. package/dist/components/ramme/popover/fs-popover.d.ts.map +1 -0
  178. package/dist/components/ramme/popover/fs-popover.js +167 -0
  179. package/dist/components/ramme/popover/fs-popover.js.map +1 -0
  180. package/dist/components/ramme/tabs/fs-tabs.d.ts +61 -0
  181. package/dist/components/ramme/tabs/fs-tabs.d.ts.map +1 -0
  182. package/dist/components/ramme/tabs/fs-tabs.js +156 -0
  183. package/dist/components/ramme/tabs/fs-tabs.js.map +1 -0
  184. package/dist/dom.d.ts +33 -0
  185. package/dist/dom.d.ts.map +1 -0
  186. package/dist/dom.js +77 -0
  187. package/dist/dom.js.map +1 -0
  188. package/dist/fs.d.ts +199 -0
  189. package/dist/fs.d.ts.map +1 -0
  190. package/dist/fs.js +128 -0
  191. package/dist/fs.js.map +1 -0
  192. package/dist/index.d.ts +84 -0
  193. package/dist/index.d.ts.map +1 -0
  194. package/dist/index.js +48 -0
  195. package/dist/index.js.map +1 -0
  196. package/dist/jsx/react.d.ts +127 -0
  197. package/dist/jsx/react.d.ts.map +1 -0
  198. package/dist/jsx/react.js +2 -0
  199. package/dist/jsx/react.js.map +1 -0
  200. package/dist/react.d.ts +207 -0
  201. package/dist/react.d.ts.map +1 -0
  202. package/dist/react.js +109 -0
  203. package/dist/react.js.map +1 -0
  204. package/dist/tailwind/preset.d.ts +120 -0
  205. package/dist/tailwind/preset.d.ts.map +1 -0
  206. package/dist/tailwind/preset.js +107 -0
  207. package/dist/tailwind/preset.js.map +1 -0
  208. package/dist/takeover.d.ts +79 -0
  209. package/dist/takeover.d.ts.map +1 -0
  210. package/dist/takeover.js +119 -0
  211. package/dist/takeover.js.map +1 -0
  212. package/dist/tokens/color.d.ts +85 -0
  213. package/dist/tokens/color.d.ts.map +1 -0
  214. package/dist/tokens/color.js +212 -0
  215. package/dist/tokens/color.js.map +1 -0
  216. package/dist/tokens/theme.d.ts +52 -0
  217. package/dist/tokens/theme.d.ts.map +1 -0
  218. package/dist/tokens/theme.js +197 -0
  219. package/dist/tokens/theme.js.map +1 -0
  220. package/dist/tokens/tokens.d.ts +210 -0
  221. package/dist/tokens/tokens.d.ts.map +1 -0
  222. package/dist/tokens/tokens.js +238 -0
  223. package/dist/tokens/tokens.js.map +1 -0
  224. package/package.json +334 -0
  225. package/src/components/css/accordion/accordion.css +74 -0
  226. package/src/components/css/accordion/accordion.ts +50 -0
  227. package/src/components/css/alert/alert.css +50 -0
  228. package/src/components/css/alert/alert.ts +48 -0
  229. package/src/components/css/avatar/avatar.css +64 -0
  230. package/src/components/css/avatar/avatar.ts +57 -0
  231. package/src/components/css/badge/badge.css +42 -0
  232. package/src/components/css/badge/badge.ts +43 -0
  233. package/src/components/css/breadcrumbs/breadcrumbs.css +50 -0
  234. package/src/components/css/breadcrumbs/breadcrumbs.ts +29 -0
  235. package/src/components/css/button/button.css +101 -0
  236. package/src/components/css/button/button.ts +44 -0
  237. package/src/components/css/card/card.css +48 -0
  238. package/src/components/css/card/card.ts +50 -0
  239. package/src/components/css/checkbox/checkbox.css +96 -0
  240. package/src/components/css/checkbox/checkbox.ts +50 -0
  241. package/src/components/css/dialog/dialog.css +50 -0
  242. package/src/components/css/dialog/dialog.ts +36 -0
  243. package/src/components/css/divider/divider.css +18 -0
  244. package/src/components/css/divider/divider.ts +41 -0
  245. package/src/components/css/error-text/error-text.css +21 -0
  246. package/src/components/css/error-text/error-text.ts +37 -0
  247. package/src/components/css/fieldset/fieldset.css +57 -0
  248. package/src/components/css/fieldset/fieldset.ts +87 -0
  249. package/src/components/css/file-upload/file-upload.css +92 -0
  250. package/src/components/css/file-upload/file-upload.ts +65 -0
  251. package/src/components/css/heading/heading.css +33 -0
  252. package/src/components/css/heading/heading.ts +42 -0
  253. package/src/components/css/help-text/help-text.css +24 -0
  254. package/src/components/css/help-text/help-text.ts +42 -0
  255. package/src/components/css/input/input.css +131 -0
  256. package/src/components/css/input/input.ts +76 -0
  257. package/src/components/css/label/label.css +34 -0
  258. package/src/components/css/label/label.ts +51 -0
  259. package/src/components/css/link/link.css +36 -0
  260. package/src/components/css/link/link.ts +29 -0
  261. package/src/components/css/list/list.css +40 -0
  262. package/src/components/css/list/list.ts +42 -0
  263. package/src/components/css/pagination/pagination.css +77 -0
  264. package/src/components/css/pagination/pagination.ts +33 -0
  265. package/src/components/css/paragraph/paragraph.css +31 -0
  266. package/src/components/css/paragraph/paragraph.ts +53 -0
  267. package/src/components/css/radio/radio.css +76 -0
  268. package/src/components/css/radio/radio.ts +50 -0
  269. package/src/components/css/search/search.css +49 -0
  270. package/src/components/css/search/search.ts +52 -0
  271. package/src/components/css/select/select.css +95 -0
  272. package/src/components/css/select/select.ts +40 -0
  273. package/src/components/css/shared.ts +40 -0
  274. package/src/components/css/skeleton/skeleton.css +49 -0
  275. package/src/components/css/skeleton/skeleton.ts +43 -0
  276. package/src/components/css/skip-link/skip-link.css +36 -0
  277. package/src/components/css/skip-link/skip-link.ts +22 -0
  278. package/src/components/css/spinner/spinner.css +48 -0
  279. package/src/components/css/spinner/spinner.ts +48 -0
  280. package/src/components/css/sr-only/sr-only.css +16 -0
  281. package/src/components/css/sr-only/sr-only.ts +18 -0
  282. package/src/components/css/switch/switch.css +101 -0
  283. package/src/components/css/switch/switch.ts +46 -0
  284. package/src/components/css/table/table.css +63 -0
  285. package/src/components/css/table/table.ts +50 -0
  286. package/src/components/css/tag/tag.css +58 -0
  287. package/src/components/css/tag/tag.ts +49 -0
  288. package/src/components/css/textarea/textarea.css +71 -0
  289. package/src/components/css/textarea/textarea.ts +40 -0
  290. package/src/components/css/toggle-group/toggle-group.css +82 -0
  291. package/src/components/css/toggle-group/toggle-group.ts +37 -0
  292. package/src/components/css/tooltip/tooltip.css +47 -0
  293. package/src/components/css/tooltip/tooltip.ts +36 -0
  294. package/src/components/frittstaende/calendar/fs-calendar.ts +525 -0
  295. package/src/components/frittstaende/date-field/date-field.css +54 -0
  296. package/src/components/frittstaende/date-field/fs-date-field.ts +309 -0
  297. package/src/components/frittstaende/suggestion/fs-suggestion.ts +333 -0
  298. package/src/components/frittstaende/suggestion/suggestion.css +63 -0
  299. package/src/components/frittstaende/toast/fs-toast.ts +146 -0
  300. package/src/components/frittstaende/toast/toast.css +71 -0
  301. package/src/components/ramme/error-summary/error-summary.css +45 -0
  302. package/src/components/ramme/error-summary/fs-error-summary.ts +197 -0
  303. package/src/components/ramme/field/field-core.ts +132 -0
  304. package/src/components/ramme/field/field.css +6 -0
  305. package/src/components/ramme/field/fs-field.ts +154 -0
  306. package/src/components/ramme/popover/fs-popover.ts +205 -0
  307. package/src/components/ramme/popover/popover.css +34 -0
  308. package/src/components/ramme/tabs/fs-tabs.ts +182 -0
  309. package/src/components/ramme/tabs/tabs.css +68 -0
  310. package/src/tailwind/tailwind.css +134 -0
  311. package/src/tokens/color.ts +267 -0
  312. package/src/tokens/theme.ts +350 -0
  313. package/src/tokens/tokens.css +214 -0
  314. package/src/tokens/tokens.ts +293 -0
@@ -0,0 +1,134 @@
1
+ /*
2
+ * Fristils verdier som Tailwind-tema.
3
+ *
4
+ * Fila er ren CSS, og pakken har ingen avhengighet til Tailwind. Det er
5
+ * Tailwind-versjonen i appen din som leser den, så to versjoner kan ikke
6
+ * komme i konflikt: her finnes det ingen andre.
7
+ *
8
+ * Krever Tailwind 4 og at `tokens.css` er lastet, siden verdiene peker dit.
9
+ *
10
+ * ```css
11
+ * @layer theme, base, fristil, components, utilities;
12
+ *
13
+ * @import "tailwindcss";
14
+ * @import "@fristil/designsystem/tokens.css";
15
+ * @import "@fristil/designsystem/tailwind.css";
16
+ * ```
17
+ *
18
+ * Rekkefølgen på den første linja er ikke pynt. Lagene teller i den
19
+ * rekkefølgen de først blir nevnt, og vinneren er det siste laget, uansett
20
+ * spesifisitet. Står `fristil` foran `base`, slår Tailwinds Preflight
21
+ * komponentene våre og nullstiller for eksempel bakgrunnen på en knapp. Står
22
+ * det etter `utilities`, slår komponentene våre `p-6` og resten av klassene
23
+ * dine. Mellom `base` og `components` er det eneste stedet begge deler virker.
24
+ *
25
+ * Alt vi legger til heter `fs-`, som klassene ellers i systemet. Da rører vi
26
+ * ikke Tailwinds egne verdier: `bg-neutral-100` betyr fortsatt det samme.
27
+ */
28
+
29
+ @theme inline {
30
+ /*
31
+ * Avstandsenheten. Tailwind regner `p-4` som `calc(var(--spacing) * 4)`,
32
+ * så med `--size-1` som enhet er `p-4` nøyaktig `--size-4`. Endrer du
33
+ * skalaen, følger Tailwind-klassene med.
34
+ */
35
+ --spacing: var(--size-1);
36
+
37
+ /* Side */
38
+ --color-fs-page: var(--semantic-page-background);
39
+ --color-fs-page-fg: var(--semantic-page-foreground);
40
+
41
+ /* Interaktiv */
42
+ --color-fs-interactive: var(--semantic-interactive-main);
43
+ --color-fs-interactive-bg: var(--semantic-interactive-background);
44
+ --color-fs-interactive-fg: var(--semantic-interactive-foreground);
45
+ --color-fs-interactive-contrast: var(--semantic-interactive-contrast);
46
+ --color-fs-visited: var(--semantic-interactive-visited);
47
+
48
+ /* Status */
49
+ --color-fs-success: var(--semantic-success-foreground);
50
+ --color-fs-success-bg: var(--semantic-success-background);
51
+ --color-fs-warning: var(--semantic-warning-foreground);
52
+ --color-fs-warning-bg: var(--semantic-warning-background);
53
+ --color-fs-danger: var(--semantic-danger-foreground);
54
+ --color-fs-danger-bg: var(--semantic-danger-background);
55
+ --color-fs-danger-main: var(--semantic-danger-main);
56
+ --color-fs-danger-contrast: var(--semantic-danger-contrast);
57
+ --color-fs-neutral: var(--semantic-neutral-foreground);
58
+ --color-fs-neutral-bg: var(--semantic-neutral-background);
59
+ --color-fs-disabled: var(--semantic-disabled-foreground);
60
+ --color-fs-disabled-bg: var(--semantic-disabled-background);
61
+
62
+ /* Tekst og kanter */
63
+ --color-fs-muted: var(--semantic-muted-foreground);
64
+ --color-fs-field-border: var(--semantic-field-border);
65
+ --color-fs-field-border-hover: var(--semantic-field-border-hover);
66
+ --color-fs-divider: var(--semantic-divider-30);
67
+ --color-fs-divider-strong: var(--semantic-divider-100);
68
+
69
+ /* Palett, for det som ikke har en semantisk betydning ennå */
70
+ --color-fs-burgundy-5: var(--palette-burgundy-5);
71
+ --color-fs-burgundy-10: var(--palette-burgundy-10);
72
+ --color-fs-burgundy-30: var(--palette-burgundy-30);
73
+ --color-fs-burgundy-50: var(--palette-burgundy-50);
74
+ --color-fs-burgundy-70: var(--palette-burgundy-70);
75
+ --color-fs-burgundy-100: var(--palette-burgundy-100);
76
+ --color-fs-forest-5: var(--palette-forest-5);
77
+ --color-fs-forest-10: var(--palette-forest-10);
78
+ --color-fs-forest-30: var(--palette-forest-30);
79
+ --color-fs-forest-50: var(--palette-forest-50);
80
+ --color-fs-forest-70: var(--palette-forest-70);
81
+ --color-fs-forest-100: var(--palette-forest-100);
82
+ --color-fs-ochre-5: var(--palette-ochre-5);
83
+ --color-fs-ochre-10: var(--palette-ochre-10);
84
+ --color-fs-ochre-30: var(--palette-ochre-30);
85
+ --color-fs-ochre-50: var(--palette-ochre-50);
86
+ --color-fs-ochre-70: var(--palette-ochre-70);
87
+ --color-fs-ochre-100: var(--palette-ochre-100);
88
+ --color-fs-denim-5: var(--palette-denim-5);
89
+ --color-fs-denim-10: var(--palette-denim-10);
90
+ --color-fs-denim-30: var(--palette-denim-30);
91
+ --color-fs-denim-50: var(--palette-denim-50);
92
+ --color-fs-denim-70: var(--palette-denim-70);
93
+ --color-fs-denim-100: var(--palette-denim-100);
94
+ --color-fs-azure-10: var(--palette-azure-10);
95
+ --color-fs-azure-30: var(--palette-azure-30);
96
+ --color-fs-azure-70: var(--palette-azure-70);
97
+ --color-fs-azure-100: var(--palette-azure-100);
98
+ --color-fs-graphite-0: var(--palette-graphite-0);
99
+ --color-fs-graphite-5: var(--palette-graphite-5);
100
+ --color-fs-graphite-10: var(--palette-graphite-10);
101
+ --color-fs-graphite-30: var(--palette-graphite-30);
102
+ --color-fs-graphite-50: var(--palette-graphite-50);
103
+ --color-fs-graphite-70: var(--palette-graphite-70);
104
+ --color-fs-graphite-100: var(--palette-graphite-100);
105
+
106
+ /* Tekststørrelser */
107
+ --text-fs-xxs: var(--font-size-xxs);
108
+ --text-fs-xs: var(--font-size-xs);
109
+ --text-fs-s: var(--font-size-s);
110
+ --text-fs-m: var(--font-size-m);
111
+ --text-fs-l: var(--font-size-l);
112
+ --text-fs-xl: var(--font-size-xl);
113
+ --text-fs-xxl: var(--font-size-xxl);
114
+ --text-fs-mega: var(--font-size-mega);
115
+
116
+ /* Bredder for sideoppsett */
117
+ --container-fs-xs: 100%;
118
+ --container-fs-sm: 576px;
119
+ --container-fs-md: 960px;
120
+ --container-fs-lg: 1152px;
121
+ --container-fs-xl: 1536px;
122
+ --container-fs-aside: 384px;
123
+ --container-fs-aside-narrow: 288px;
124
+ --container-fs-wide-content: 768px;
125
+
126
+ /* Skygge under flater som ligger over siden */
127
+ --shadow-fs-overlay: var(--semantic-shadow-overlay);
128
+ }
129
+
130
+ /*
131
+ * Brekkpunktene er med vilje utelatt. Fristils `sm`, `md`, `lg`, `xl` og
132
+ * `2xl` har nøyaktig de samme verdiene som Tailwind allerede bruker, så
133
+ * `md:` virker som før uten at vi overstyrer noe.
134
+ */
@@ -0,0 +1,267 @@
1
+ /**
2
+ * Fargeregning for temageneratoren.
3
+ *
4
+ * Skalaene lages i OKLCH og ikke i HSL. I HSL betyr lyshet noe annet for hver
5
+ * kulør: `hsl(60 100% 50%)` er knallgul og `hsl(240 100% 50%)` er nesten sort,
6
+ * med samme tall. En skala bygget på HSL blir derfor ujevn, og kontrasten
7
+ * varierer med kuløren brukeren valgte. I OKLCH er lysheten den samme
8
+ * opplevde lysheten uansett kulør, så trinnene kan settes én gang og gjelde
9
+ * for alle farger.
10
+ *
11
+ * Kontrasten regnes med WCAG 2.1 sin formel, altså den samme som testene
12
+ * bruker, slik at generatoren og kontrollen er enige.
13
+ */
14
+
15
+ export type Rgb = { r: number; g: number; b: number }
16
+ export type Oklch = { l: number; c: number; h: number }
17
+
18
+ /** Leser `#rrggbb` eller `#rgb`. */
19
+ export function parseHex(hex: string): Rgb {
20
+ const rent = hex.trim().replace(/^#/, "")
21
+ const full =
22
+ rent.length === 3
23
+ ? rent
24
+ .split("")
25
+ .map((tegn) => tegn + tegn)
26
+ .join("")
27
+ : rent
28
+
29
+ if (!/^[0-9a-fA-F]{6}$/.test(full)) {
30
+ throw new Error(`«${hex}» er ikke en gyldig heksadesimal farge`)
31
+ }
32
+
33
+ return {
34
+ r: Number.parseInt(full.slice(0, 2), 16),
35
+ g: Number.parseInt(full.slice(2, 4), 16),
36
+ b: Number.parseInt(full.slice(4, 6), 16),
37
+ }
38
+ }
39
+
40
+ export function toHex({ r, g, b }: Rgb): string {
41
+ const tall = (verdi: number) =>
42
+ Math.round(Math.min(255, Math.max(0, verdi)))
43
+ .toString(16)
44
+ .padStart(2, "0")
45
+
46
+ return `#${tall(r)}${tall(g)}${tall(b)}`
47
+ }
48
+
49
+ function toLinear(kanal: number): number {
50
+ const c = kanal / 255
51
+ return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4
52
+ }
53
+
54
+ function fromLinear(kanal: number): number {
55
+ const c =
56
+ kanal <= 0.0031308 ? kanal * 12.92 : 1.055 * kanal ** (1 / 2.4) - 0.055
57
+ return c * 255
58
+ }
59
+
60
+ export function rgbToOklch({ r, g, b }: Rgb): Oklch {
61
+ const lr = toLinear(r)
62
+ const lg = toLinear(g)
63
+ const lb = toLinear(b)
64
+
65
+ const l = 0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb
66
+ const m = 0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb
67
+ const s = 0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb
68
+
69
+ const l_ = Math.cbrt(l)
70
+ const m_ = Math.cbrt(m)
71
+ const s_ = Math.cbrt(s)
72
+
73
+ const lightness = 0.2104542553 * l_ + 0.793617785 * m_ - 0.0040720468 * s_
74
+ const a = 1.9779984951 * l_ - 2.428592205 * m_ + 0.4505937099 * s_
75
+ const bb = 0.0259040371 * l_ + 0.7827717662 * m_ - 0.808675766 * s_
76
+
77
+ return {
78
+ l: lightness,
79
+ c: Math.hypot(a, bb),
80
+ h: (Math.atan2(bb, a) * 180) / Math.PI,
81
+ }
82
+ }
83
+
84
+ function oklchToRgbRaw({ l, c, h }: Oklch): Rgb {
85
+ const rad = (h * Math.PI) / 180
86
+ const a = c * Math.cos(rad)
87
+ const b = c * Math.sin(rad)
88
+
89
+ const l_ = l + 0.3963377774 * a + 0.2158037573 * b
90
+ const m_ = l - 0.1055613458 * a - 0.0638541728 * b
91
+ const s_ = l - 0.0894841775 * a - 1.291485548 * b
92
+
93
+ const lr = l_ ** 3
94
+ const mr = m_ ** 3
95
+ const sr = s_ ** 3
96
+
97
+ return {
98
+ r: fromLinear(4.0767416621 * lr - 3.3077115913 * mr + 0.2309699292 * sr),
99
+ g: fromLinear(-1.2684380046 * lr + 2.6097574011 * mr - 0.3413193965 * sr),
100
+ b: fromLinear(-0.0041960863 * lr - 0.7034186147 * mr + 1.707614701 * sr),
101
+ }
102
+ }
103
+
104
+ function utenfor({ r, g, b }: Rgb): boolean {
105
+ const slingringsmonn = 0.5
106
+ return [r, g, b].some(
107
+ (kanal) => kanal < -slingringsmonn || kanal > 255 + slingringsmonn,
108
+ )
109
+ }
110
+
111
+ /**
112
+ * Gjør en OKLCH-farge om til rgb som finnes på en skjerm.
113
+ *
114
+ * Ikke alle kombinasjoner av lyshet og metning kan vises i sRGB. Havner
115
+ * fargen utenfor, dempes metningen til den er innenfor, framfor å klippe
116
+ * kanalene hver for seg. Det siste ville endret kuløren.
117
+ */
118
+ export function oklchToRgb(farge: Oklch): Rgb {
119
+ const forsok = oklchToRgbRaw(farge)
120
+ if (!utenfor(forsok)) return forsok
121
+
122
+ let lav = 0
123
+ let hoy = farge.c
124
+
125
+ for (let i = 0; i < 24; i += 1) {
126
+ const midt = (lav + hoy) / 2
127
+ if (utenfor(oklchToRgbRaw({ ...farge, c: midt }))) hoy = midt
128
+ else lav = midt
129
+ }
130
+
131
+ return oklchToRgbRaw({ ...farge, c: lav })
132
+ }
133
+
134
+ function luminans({ r, g, b }: Rgb): number {
135
+ return 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b)
136
+ }
137
+
138
+ /** Kontrastforholdet mellom to farger, slik WCAG 2.1 regner det. */
139
+ export function contrastRatio(a: Rgb, b: Rgb): number {
140
+ const la = luminans(a)
141
+ const lb = luminans(b)
142
+ return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05)
143
+ }
144
+
145
+ /** Trinnene i en Fristil-skala, og lysheten hvert av dem sikter mot. */
146
+ export const SCALE_STEPS = {
147
+ 5: 0.97,
148
+ 10: 0.93,
149
+ 30: 0.83,
150
+ 50: 0.72,
151
+ 70: 0.55,
152
+ 100: 0.38,
153
+ } as const
154
+
155
+ /**
156
+ * Hvor mye av kulørens metning hvert trinn beholder.
157
+ *
158
+ * Lyse trinn tåler lite metning før de ser skitne ut, og mørke trinn mister
159
+ * den likevel i sRGB. Forholdstallene er lest av Fristils egen palett, så en
160
+ * generert skala får samme rytme som den håndlagde.
161
+ */
162
+ const CHROMA_FACTOR: Record<keyof typeof SCALE_STEPS, number> = {
163
+ 5: 0.09,
164
+ 10: 0.24,
165
+ 30: 0.62,
166
+ 50: 1.06,
167
+ 70: 1,
168
+ 100: 0.79,
169
+ }
170
+
171
+ /** Lysheten i den nøytrale skalaen, som går lenger i begge ender. */
172
+ export const NEUTRAL_STEPS = {
173
+ 0: 1,
174
+ 5: 0.97,
175
+ 10: 0.92,
176
+ 30: 0.76,
177
+ 50: 0.56,
178
+ 70: 0.42,
179
+ 100: 0.22,
180
+ } as const
181
+
182
+ /**
183
+ * Bygger en skala fra én farge.
184
+ *
185
+ * Kuløren beholdes, mens lysheten settes av trinnet. Metningen tas fra fargen
186
+ * som ble oppgitt, og dempes i endene.
187
+ */
188
+ export function buildScale(hex: string): Record<number, string> {
189
+ const { c, h } = rgbToOklch(parseHex(hex))
190
+ const referanse = Math.min(c, 0.16)
191
+
192
+ const skala: Record<number, string> = {}
193
+ for (const [trinn, lyshet] of Object.entries(SCALE_STEPS)) {
194
+ const nummer = Number(trinn) as keyof typeof SCALE_STEPS
195
+ skala[nummer] = toHex(
196
+ oklchToRgb({ l: lyshet, c: referanse * CHROMA_FACTOR[nummer], h }),
197
+ )
198
+ }
199
+ return skala
200
+ }
201
+
202
+ /** Bygger den nøytrale skalaen, som også har et rent hvitt trinn. */
203
+ export function buildNeutralScale(hex: string): Record<number, string> {
204
+ const { c, h } = rgbToOklch(parseHex(hex))
205
+ // Nøytrale farger tåler bare en antydning til kulør før de ser malt ut.
206
+ const metning = Math.min(c, 0.02)
207
+
208
+ const skala: Record<number, string> = {}
209
+ for (const [trinn, lyshet] of Object.entries(NEUTRAL_STEPS)) {
210
+ skala[Number(trinn)] =
211
+ Number(trinn) === 0
212
+ ? "#ffffff"
213
+ : toHex(oklchToRgb({ l: lyshet, c: metning, h }))
214
+ }
215
+ return skala
216
+ }
217
+
218
+ export type AdjustResult = {
219
+ /** Fargen som holder kravet. */
220
+ hex: string
221
+ /** Hvor mye lysheten måtte flyttes, i OKLCH-enheter. */
222
+ moved: number
223
+ /** Kontrasten den endte på. */
224
+ ratio: number
225
+ }
226
+
227
+ /**
228
+ * Flytter lysheten til fargen holder kravet mot bakgrunnen.
229
+ *
230
+ * Kuløren og metningen står stille, så fargen er den samme fargen, bare lys
231
+ * nok eller mørk nok. Retningen velges etter bakgrunnen: mot sort på en lys
232
+ * flate, mot hvit på en mørk.
233
+ *
234
+ * Kravet kan være umulig, for eksempel 4,5:1 mot en flate midt på skalaen.
235
+ * Da returneres det beste forsøket, og kalleren sier fra.
236
+ */
237
+ export function adjustForContrast(
238
+ hex: string,
239
+ backgroundHex: string,
240
+ target: number,
241
+ ): AdjustResult {
242
+ const bakgrunn = parseHex(backgroundHex)
243
+ const start = rgbToOklch(parseHex(hex))
244
+ const mork = luminans(bakgrunn) > 0.18 ? -1 : 1
245
+
246
+ let beste = {
247
+ hex: toHex(oklchToRgb(start)),
248
+ moved: 0,
249
+ ratio: contrastRatio(oklchToRgb(start), bakgrunn),
250
+ }
251
+
252
+ for (let steg = 0; steg <= 100; steg += 1) {
253
+ const lyshet = Math.min(1, Math.max(0, start.l + mork * steg * 0.01))
254
+ const farge = oklchToRgb({ ...start, l: lyshet })
255
+ const forhold = contrastRatio(farge, bakgrunn)
256
+
257
+ if (forhold > beste.ratio) {
258
+ beste = { hex: toHex(farge), moved: steg * 0.01, ratio: forhold }
259
+ }
260
+
261
+ if (forhold >= target) {
262
+ return { hex: toHex(farge), moved: steg * 0.01, ratio: forhold }
263
+ }
264
+ }
265
+
266
+ return beste
267
+ }