@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,155 @@
1
+ import { html, LitElement } from "lit";
2
+ export const FS_ERROR_SUMMARY_TAG = "fs-error-summary";
3
+ export const ERROR_SUMMARY_CLASS = "fs-error-summary";
4
+ export const ERROR_SUMMARY_TITLE_CLASS = "fs-error-summary__title";
5
+ /**
6
+ * Samler feilene i et skjema og sender brukeren til feltet som feilet.
7
+ *
8
+ * Du skriver lista med feil selv, som lenker til id-en på hvert felt.
9
+ * Komponenten gjør tre ting som er lette å glemme, og som avgjør om
10
+ * oppsummeringen er til nytte:
11
+ *
12
+ * 1. Flytter fokus til boksen når den kommer til syne, så den som hører siden
13
+ * får vite at innsendingen stoppet.
14
+ * 2. Gir fokus til selve kontrollen når en lenke følges. En vanlig ankerlenke
15
+ * ruller bare dit, og neste tastetrykk fortsetter der fokus sto før.
16
+ * 3. Holder boksen skjult mens lista er tom, så en tom overskrift ikke blir
17
+ * stående i skjemaet.
18
+ *
19
+ * ```html
20
+ * <fs-error-summary heading="Skjemaet har to feil">
21
+ * <ul class="fs-list">
22
+ * <li><a href="#epost">Skriv en gyldig e-postadresse</a></li>
23
+ * </ul>
24
+ * </fs-error-summary>
25
+ * ```
26
+ */
27
+ export class FsErrorSummary extends LitElement {
28
+ constructor() {
29
+ super(...arguments);
30
+ /** Overskriften over lista. */
31
+ this.heading = "Skjemaet har feil";
32
+ /** Flytt fokus hit når boksen kommer til syne. Standard: på. */
33
+ this.autofocus = true;
34
+ this.hasFocused = false;
35
+ this.syncing = false;
36
+ this.handleSlotChange = () => {
37
+ this.sync();
38
+ };
39
+ this.handleLinkClick = (event) => {
40
+ const link = event.currentTarget;
41
+ const id = link.getAttribute("href")?.slice(1);
42
+ if (!id)
43
+ return;
44
+ const target = document.getElementById(id);
45
+ if (!target)
46
+ return;
47
+ event.preventDefault();
48
+ // Er lenken til en ledetekst, skal fokus til kontrollen den peker på.
49
+ const control = target instanceof HTMLLabelElement && target.htmlFor
50
+ ? document.getElementById(target.htmlFor)
51
+ : target;
52
+ const focusable = control ?? target;
53
+ if (!focusable.hasAttribute("tabindex") && !isFocusable(focusable)) {
54
+ focusable.setAttribute("tabindex", "-1");
55
+ }
56
+ focusable.focus();
57
+ focusable.scrollIntoView({ block: "center", behavior: "smooth" });
58
+ };
59
+ }
60
+ createRenderRoot() {
61
+ return this;
62
+ }
63
+ render() {
64
+ return html `<slot @slotchange=${this.handleSlotChange}></slot>`;
65
+ }
66
+ connectedCallback() {
67
+ super.connectedCallback();
68
+ this.observer = new MutationObserver(() => {
69
+ if (!this.syncing)
70
+ this.sync();
71
+ });
72
+ this.observer.observe(this, { childList: true, subtree: true });
73
+ }
74
+ disconnectedCallback() {
75
+ this.observer?.disconnect();
76
+ this.observer = undefined;
77
+ super.disconnectedCallback();
78
+ }
79
+ firstUpdated() {
80
+ this.sync();
81
+ }
82
+ updated() {
83
+ this.sync();
84
+ }
85
+ get items() {
86
+ return [...this.querySelectorAll("li a[href^='#']")];
87
+ }
88
+ sync() {
89
+ if (this.syncing)
90
+ return;
91
+ this.syncing = true;
92
+ try {
93
+ const links = this.items;
94
+ const empty = links.length === 0;
95
+ this.hidden = empty;
96
+ if (empty) {
97
+ this.hasFocused = false;
98
+ return;
99
+ }
100
+ // Boksen er selve elementet. Vi flytter ikke konsumentens markup inn i
101
+ // et omslag: da ville Lit-delen vår og innholdet byttet plass i DOM-en.
102
+ this.classList.add(ERROR_SUMMARY_CLASS);
103
+ this.setAttribute("role", "alert");
104
+ this.tabIndex = -1;
105
+ let title = this.querySelector(`.${ERROR_SUMMARY_TITLE_CLASS}`);
106
+ if (!title) {
107
+ title = document.createElement("h2");
108
+ title.className = ERROR_SUMMARY_TITLE_CLASS;
109
+ this.prepend(title);
110
+ this.ownTitle = title;
111
+ }
112
+ // Overskriften følger `heading` så lenge det er vi som har laget den.
113
+ // Antallet feil endrer seg mens brukeren retter, og en overskrift som
114
+ // ble stående på det første tallet er verre enn ingen: den som hører
115
+ // siden får vite at det er to feil igjen når det er én.
116
+ // Har konsumenten skrevet tittelen selv, er den deres.
117
+ //
118
+ // Sammenligningen er ikke pynt: å skrive den samme teksten på nytt
119
+ // teller som en endring for MutationObserver, og da kaller den sync()
120
+ // igjen i det uendelige.
121
+ const skalSkrive = title === this.ownTitle || !title.textContent?.trim();
122
+ if (skalSkrive && title.textContent !== this.heading) {
123
+ title.textContent = this.heading;
124
+ }
125
+ for (const link of links) {
126
+ link.removeEventListener("click", this.handleLinkClick);
127
+ link.addEventListener("click", this.handleLinkClick);
128
+ }
129
+ if (this.autofocus && !this.hasFocused) {
130
+ this.hasFocused = true;
131
+ this.focus();
132
+ }
133
+ }
134
+ finally {
135
+ this.syncing = false;
136
+ }
137
+ }
138
+ }
139
+ FsErrorSummary.properties = {
140
+ heading: { type: String },
141
+ autofocus: { type: Boolean, reflect: true },
142
+ };
143
+ function isFocusable(element) {
144
+ return (element instanceof HTMLInputElement ||
145
+ element instanceof HTMLSelectElement ||
146
+ element instanceof HTMLTextAreaElement ||
147
+ element instanceof HTMLButtonElement ||
148
+ element instanceof HTMLAnchorElement);
149
+ }
150
+ export function defineFsErrorSummary(tagName = FS_ERROR_SUMMARY_TAG) {
151
+ if (!customElements.get(tagName)) {
152
+ customElements.define(tagName, FsErrorSummary);
153
+ }
154
+ }
155
+ //# sourceMappingURL=fs-error-summary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-error-summary.js","sourceRoot":"","sources":["../../../../src/components/ramme/error-summary/fs-error-summary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ import type { FieldState, RequiredMarker } from "../../css/shared.js";
2
+ /**
3
+ * Regner ut koblingen mellom ledetekst, felt, hjelpetekst og feilmelding.
4
+ *
5
+ * Dette er den ene implementasjonen av tilgjengelighetskontrakten i systemet.
6
+ * `<fs-field>` bruker den på elementer som allerede står i DOM-en, og
7
+ * `fs.field()` gir den samme utregningen som data til den som vil eie
8
+ * markupen selv. Uten delingen ville kontrakten finnes to steder og kunne gå
9
+ * fra hverandre.
10
+ */
11
+ export type FieldOptions = {
12
+ /** Id på kontrollen. Lages automatisk hvis den utelates. */
13
+ id?: string;
14
+ /** Feltet har en hjelpetekst som skal kobles med `aria-describedby`. */
15
+ help?: boolean;
16
+ /** Feltet har en feilmelding. Den skjules til feltet er ugyldig. */
17
+ error?: boolean;
18
+ /** Egen id på hjelpeteksten. Utledes fra `id` hvis den utelates. */
19
+ helpId?: string;
20
+ /** Egen id på feilmeldingen. Utledes fra `id` hvis den utelates. */
21
+ errorId?: string;
22
+ /** Marker ledeteksten som påkrevd. */
23
+ required?: RequiredMarker;
24
+ /** Marker ledeteksten som valgfri. */
25
+ optional?: boolean;
26
+ /** Feltet er ugyldig: viser feilmeldingen og setter `aria-invalid`. */
27
+ invalid?: boolean;
28
+ /** Kontrollen er slått av. */
29
+ disabled?: boolean;
30
+ /** Ekstra id-er som skal med i `aria-describedby`. */
31
+ describedBy?: string[];
32
+ };
33
+ export type FieldAttributes = {
34
+ label: {
35
+ class: "fs-label";
36
+ for: string;
37
+ "data-required"?: RequiredMarker;
38
+ "data-optional"?: "";
39
+ "aria-disabled"?: "true";
40
+ };
41
+ control: {
42
+ id: string;
43
+ "aria-describedby"?: string;
44
+ "aria-invalid"?: "true";
45
+ "data-state"?: "invalid";
46
+ disabled?: true;
47
+ };
48
+ help: {
49
+ id: string;
50
+ };
51
+ error: {
52
+ id: string;
53
+ hidden?: true;
54
+ };
55
+ /** Tilstanden kontrollen skal ha, til `input()`, `textarea()` og `select()`. */
56
+ state: FieldState;
57
+ };
58
+ /** Lager en id som er unik innenfor dokumentet. */
59
+ export declare function createFieldId(): string;
60
+ /**
61
+ * Setter sammen `aria-describedby` av hjelpetekst, feilmelding og det
62
+ * kalleren har lagt til selv.
63
+ *
64
+ * Feilmeldingen tas bare med når feltet faktisk er ugyldig. Ellers ville
65
+ * `aria-describedby` pekt på et skjult element, og skjermlesere melder da
66
+ * enten ingenting eller noe som ikke står på skjermen.
67
+ */
68
+ export declare function joinDescribedBy(ids: Array<string | undefined | false>): string | undefined;
69
+ export declare function computeFieldAttributes(options?: FieldOptions): FieldAttributes;
70
+ //# sourceMappingURL=field-core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-core.d.ts","sourceRoot":"","sources":["../../../../src/components/ramme/field/field-core.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAGrE;;;;;;;;GAQG;AAEH,MAAM,MAAM,YAAY,GAAG;IACzB,4DAA4D;IAC5D,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,oEAAoE;IACpE,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,uEAAuE;IACvE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE;QACL,KAAK,EAAE,UAAU,CAAA;QACjB,GAAG,EAAE,MAAM,CAAA;QACX,eAAe,CAAC,EAAE,cAAc,CAAA;QAChC,eAAe,CAAC,EAAE,EAAE,CAAA;QACpB,eAAe,CAAC,EAAE,MAAM,CAAA;KACzB,CAAA;IACD,OAAO,EAAE;QACP,EAAE,EAAE,MAAM,CAAA;QACV,kBAAkB,CAAC,EAAE,MAAM,CAAA;QAC3B,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,YAAY,CAAC,EAAE,SAAS,CAAA;QACxB,QAAQ,CAAC,EAAE,IAAI,CAAA;KAChB,CAAA;IACD,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;IACpB,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,IAAI,CAAA;KAAE,CAAA;IACpC,gFAAgF;IAChF,KAAK,EAAE,UAAU,CAAA;CAClB,CAAA;AAID,mDAAmD;AACnD,wBAAgB,aAAa,IAAI,MAAM,CAGtC;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,KAAK,CAAC,MAAM,GAAG,SAAS,GAAG,KAAK,CAAC,GACrC,MAAM,GAAG,SAAS,CASpB;AAED,wBAAgB,sBAAsB,CACpC,OAAO,GAAE,YAAiB,GACzB,eAAe,CA2CjB"}
@@ -0,0 +1,60 @@
1
+ import { attributes } from "../../css/shared.js";
2
+ let counter = 0;
3
+ /** Lager en id som er unik innenfor dokumentet. */
4
+ export function createFieldId() {
5
+ counter += 1;
6
+ return `fs-field-${counter}-${Math.random().toString(36).slice(2, 8)}`;
7
+ }
8
+ /**
9
+ * Setter sammen `aria-describedby` av hjelpetekst, feilmelding og det
10
+ * kalleren har lagt til selv.
11
+ *
12
+ * Feilmeldingen tas bare med når feltet faktisk er ugyldig. Ellers ville
13
+ * `aria-describedby` pekt på et skjult element, og skjermlesere melder da
14
+ * enten ingenting eller noe som ikke står på skjermen.
15
+ */
16
+ export function joinDescribedBy(ids) {
17
+ const unique = new Set();
18
+ for (const id of ids) {
19
+ if (!id)
20
+ continue;
21
+ for (const part of id.split(/\s+/)) {
22
+ if (part)
23
+ unique.add(part);
24
+ }
25
+ }
26
+ return unique.size > 0 ? [...unique].join(" ") : undefined;
27
+ }
28
+ export function computeFieldAttributes(options = {}) {
29
+ const { id = createFieldId(), help = false, error = false, required, optional, invalid = false, disabled = false, describedBy = [], helpId = `${id}-help`, errorId = `${id}-error`, } = options;
30
+ return {
31
+ label: attributes({
32
+ class: "fs-label",
33
+ for: id,
34
+ "data-required": required,
35
+ "data-optional": optional && !required ? "" : undefined,
36
+ "aria-disabled": disabled ? "true" : undefined,
37
+ }),
38
+ control: attributes({
39
+ id,
40
+ "aria-describedby": joinDescribedBy([
41
+ help && helpId,
42
+ invalid && error && errorId,
43
+ ...describedBy,
44
+ ]),
45
+ "aria-invalid": invalid ? "true" : undefined,
46
+ // Fargen følger med her, ikke fra input()/textarea()/select(). Ellers
47
+ // ville begge satt aria-invalid, og i maler som skriver ut attributtene
48
+ // bokstavelig, som Astro og ren HTML, ble de stående dobbelt.
49
+ "data-state": invalid ? "invalid" : undefined,
50
+ disabled: disabled ? true : undefined,
51
+ }),
52
+ help: { id: helpId },
53
+ error: attributes({
54
+ id: errorId,
55
+ hidden: invalid ? undefined : true,
56
+ }),
57
+ state: invalid ? "invalid" : "default",
58
+ };
59
+ }
60
+ //# sourceMappingURL=field-core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-core.js","sourceRoot":"","sources":["../../../../src/components/ramme/field/field-core.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAwDhD,IAAI,OAAO,GAAG,CAAC,CAAA;AAEf,mDAAmD;AACnD,MAAM,UAAU,aAAa;IAC3B,OAAO,IAAI,CAAC,CAAA;IACZ,OAAO,YAAY,OAAO,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAA;AACxE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAC7B,GAAsC;IAEtC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAA;IAChC,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC,EAAE;YAAE,SAAQ;QACjB,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YACnC,IAAI,IAAI;gBAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAC5B,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AAC5D,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,UAAwB,EAAE;IAE1B,MAAM,EACJ,EAAE,GAAG,aAAa,EAAE,EACpB,IAAI,GAAG,KAAK,EACZ,KAAK,GAAG,KAAK,EACb,QAAQ,EACR,QAAQ,EACR,OAAO,GAAG,KAAK,EACf,QAAQ,GAAG,KAAK,EAChB,WAAW,GAAG,EAAE,EAChB,MAAM,GAAG,GAAG,EAAE,OAAO,EACrB,OAAO,GAAG,GAAG,EAAE,QAAQ,GACxB,GAAG,OAAO,CAAA;IAEX,OAAO;QACL,KAAK,EAAE,UAAU,CAAC;YAChB,KAAK,EAAE,UAAmB;YAC1B,GAAG,EAAE,EAAE;YACP,eAAe,EAAE,QAAQ;YACzB,eAAe,EAAE,QAAQ,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAE,EAAY,CAAC,CAAC,CAAC,SAAS;YAClE,eAAe,EAAE,QAAQ,CAAC,CAAC,CAAE,MAAgB,CAAC,CAAC,CAAC,SAAS;SAC1D,CAAC;QACF,OAAO,EAAE,UAAU,CAAC;YAClB,EAAE;YACF,kBAAkB,EAAE,eAAe,CAAC;gBAClC,IAAI,IAAI,MAAM;gBACd,OAAO,IAAI,KAAK,IAAI,OAAO;gBAC3B,GAAG,WAAW;aACf,CAAC;YACF,cAAc,EAAE,OAAO,CAAC,CAAC,CAAE,MAAgB,CAAC,CAAC,CAAC,SAAS;YACvD,sEAAsE;YACtE,wEAAwE;YACxE,8DAA8D;YAC9D,YAAY,EAAE,OAAO,CAAC,CAAC,CAAE,SAAmB,CAAC,CAAC,CAAC,SAAS;YACxD,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAE,IAAc,CAAC,CAAC,CAAC,SAAS;SACjD,CAAC;QACF,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE;QACpB,KAAK,EAAE,UAAU,CAAC;YAChB,EAAE,EAAE,OAAO;YACX,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAE,IAAc;SAC9C,CAAC;QACF,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;KACvC,CAAA;AACH,CAAC"}
@@ -0,0 +1,49 @@
1
+ import { LitElement } from "lit";
2
+ export declare const FS_FIELD_TAG: "fs-field";
3
+ export declare class FsField extends LitElement {
4
+ static properties: {
5
+ invalid: {
6
+ type: BooleanConstructor;
7
+ reflect: boolean;
8
+ };
9
+ disabled: {
10
+ type: BooleanConstructor;
11
+ reflect: boolean;
12
+ };
13
+ optional: {
14
+ type: BooleanConstructor;
15
+ reflect: boolean;
16
+ };
17
+ requiredMarker: {
18
+ type: StringConstructor;
19
+ attribute: string;
20
+ };
21
+ controlId: {
22
+ type: StringConstructor;
23
+ attribute: string;
24
+ };
25
+ describedBy: {
26
+ type: StringConstructor;
27
+ attribute: string;
28
+ };
29
+ };
30
+ invalid: boolean;
31
+ disabled: boolean;
32
+ optional: boolean;
33
+ requiredMarker: "none" | "symbol" | "text";
34
+ controlId?: string;
35
+ describedBy?: string;
36
+ createRenderRoot(): this;
37
+ render(): import("lit").TemplateResult<1>;
38
+ firstUpdated(): void;
39
+ updated(): void;
40
+ private handleSlotChange;
41
+ private syncA11y;
42
+ }
43
+ declare global {
44
+ interface HTMLElementTagNameMap {
45
+ "fs-field": FsField;
46
+ }
47
+ }
48
+ export declare function defineFsField(tagName?: "fs-field"): void;
49
+ //# sourceMappingURL=fs-field.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-field.d.ts","sourceRoot":"","sources":["../../../../src/components/ramme/field/fs-field.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,UAAU,EAAE,MAAM,KAAK,CAAA;AAItC,eAAO,MAAM,YAAY,EAAG,UAAmB,CAAA;AAM/C,qBAAa,OAAQ,SAAQ,UAAU;IACrC,MAAM,CAAC,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;MAOhB;IAED,OAAO,UAAQ;IACf,QAAQ,UAAQ;IAChB,QAAQ,UAAQ;IAChB,cAAc,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAS;IACnD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB,gBAAgB;IAIhB,MAAM;IAIN,YAAY;IAIZ,OAAO;IAIP,OAAO,CAAC,gBAAgB,CAEvB;IAED,OAAO,CAAC,QAAQ;CAkFjB;AAcD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,UAAU,EAAE,OAAO,CAAA;KACpB;CACF;AAED,wBAAgB,aAAa,CAAC,OAAO,aAAe,GAAG,IAAI,CAI1D"}
@@ -0,0 +1,118 @@
1
+ import { html, LitElement } from "lit";
2
+ import { computeFieldAttributes } from "./field-core.js";
3
+ export const FS_FIELD_TAG = "fs-field";
4
+ function uniqueId(prefix) {
5
+ return `${prefix}-${Math.random().toString(36).slice(2, 9)}`;
6
+ }
7
+ export class FsField extends LitElement {
8
+ constructor() {
9
+ super(...arguments);
10
+ this.invalid = false;
11
+ this.disabled = false;
12
+ this.optional = false;
13
+ this.requiredMarker = "none";
14
+ this.handleSlotChange = () => {
15
+ this.syncA11y();
16
+ };
17
+ }
18
+ createRenderRoot() {
19
+ return this;
20
+ }
21
+ render() {
22
+ return html `<slot @slotchange=${this.handleSlotChange}></slot>`;
23
+ }
24
+ firstUpdated() {
25
+ this.syncA11y();
26
+ }
27
+ updated() {
28
+ this.syncA11y();
29
+ }
30
+ syncA11y() {
31
+ const label = this.querySelector("label");
32
+ const control = this.querySelector("input:not([type='hidden']), textarea, select");
33
+ const help = this.querySelector(".fs-help-text, [data-role='help']");
34
+ const error = this.querySelector(".fs-error-text, [data-role='error']");
35
+ if (!control)
36
+ return;
37
+ if (help && !help.id)
38
+ help.id = uniqueId("fs-field-help");
39
+ if (error && !error.id)
40
+ error.id = uniqueId("fs-field-error");
41
+ // Selve kontrakten regnes ut av den delte kjernen, som fs.field() også
42
+ // bruker. Denne komponenten gjør bare én ting utover det: å sette
43
+ // resultatet på elementer som allerede står i DOM-en.
44
+ const computed = computeFieldAttributes({
45
+ id: this.controlId || control.id || uniqueId("fs-field-control"),
46
+ help: Boolean(help),
47
+ error: Boolean(error),
48
+ helpId: help?.id,
49
+ errorId: error?.id,
50
+ required: this.requiredMarker === "symbol" || this.requiredMarker === "text"
51
+ ? this.requiredMarker
52
+ : undefined,
53
+ optional: this.optional,
54
+ invalid: this.invalid,
55
+ disabled: this.disabled,
56
+ describedBy: [
57
+ control.getAttribute("aria-describedby") ?? "",
58
+ this.describedBy ?? "",
59
+ ].filter(Boolean),
60
+ });
61
+ control.id = computed.control.id;
62
+ if (label) {
63
+ label.classList.add(computed.label.class);
64
+ if (!label.htmlFor)
65
+ label.htmlFor = computed.label.for;
66
+ setOrRemove(label, "data-required", computed.label["data-required"]);
67
+ setOrRemove(label, "data-optional", computed.label["data-optional"]);
68
+ setOrRemove(label, "aria-disabled", computed.label["aria-disabled"]);
69
+ }
70
+ if (error) {
71
+ error.hidden = Boolean(computed.error.hidden);
72
+ error.setAttribute("aria-hidden", String(Boolean(computed.error.hidden)));
73
+ }
74
+ setOrRemove(control, "aria-describedby", computed.control["aria-describedby"]);
75
+ setOrRemove(control, "aria-invalid", computed.control["aria-invalid"]);
76
+ if (this.disabled) {
77
+ control.setAttribute("disabled", "");
78
+ control.setAttribute("aria-disabled", "true");
79
+ }
80
+ else {
81
+ control.removeAttribute("disabled");
82
+ control.removeAttribute("aria-disabled");
83
+ }
84
+ // data-state settes bare når konsumenten ikke har satt den selv.
85
+ const isSystemField = control.classList.contains("fs-input") ||
86
+ control.classList.contains("fs-textarea") ||
87
+ control.classList.contains("fs-select");
88
+ const state = computed.control["data-state"];
89
+ if (state && isSystemField && !control.hasAttribute("data-state")) {
90
+ control.setAttribute("data-state", state);
91
+ }
92
+ else if (!state && control.getAttribute("data-state") === "invalid") {
93
+ control.removeAttribute("data-state");
94
+ }
95
+ }
96
+ }
97
+ FsField.properties = {
98
+ invalid: { type: Boolean, reflect: true },
99
+ disabled: { type: Boolean, reflect: true },
100
+ optional: { type: Boolean, reflect: true },
101
+ requiredMarker: { type: String, attribute: "required-marker" },
102
+ controlId: { type: String, attribute: "control-id" },
103
+ describedBy: { type: String, attribute: "described-by" },
104
+ };
105
+ function setOrRemove(element, name, value) {
106
+ if (value === undefined) {
107
+ element.removeAttribute(name);
108
+ }
109
+ else {
110
+ element.setAttribute(name, value);
111
+ }
112
+ }
113
+ export function defineFsField(tagName = FS_FIELD_TAG) {
114
+ if (!customElements.get(tagName)) {
115
+ customElements.define(tagName, FsField);
116
+ }
117
+ }
118
+ //# sourceMappingURL=fs-field.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-field.js","sourceRoot":"","sources":["../../../../src/components/ramme/field/fs-field.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ import { LitElement } from "lit";
2
+ export declare const FS_POPOVER_TAG: "fs-popover";
3
+ export declare const POPOVER_CLASS: "fs-popover";
4
+ type Placement = "bottom-start" | "bottom-end" | "top-start" | "top-end";
5
+ /**
6
+ * Et panel som henger under en knapp, og som lukker seg selv.
7
+ *
8
+ * Panelet bruker nettleserens egen `popover`, så det havner i topplaget. Det
9
+ * løser tre ting som ellers krever kode: panelet legger seg over alt annet
10
+ * uten `z-index`, Escape lukker det, og et klikk utenfor lukker det.
11
+ *
12
+ * Det topplaget gjør ikke er å plassere panelet. `position-anchor` finnes
13
+ * ennå ikke i alle nettlesere, så posisjonen regnes ut her, mot knappens
14
+ * plass på skjermen.
15
+ *
16
+ * Du skriver knappen og innholdet selv, og komponenten kobler dem sammen:
17
+ *
18
+ * ```html
19
+ * <fs-popover placement="bottom-end">
20
+ * <button slot="trigger" class="fs-button">Handlinger</button>
21
+ * <ul class="fs-list" data-variant="plain">…</ul>
22
+ * </fs-popover>
23
+ * ```
24
+ */
25
+ export declare class FsPopover extends LitElement {
26
+ static properties: {
27
+ open: {
28
+ type: BooleanConstructor;
29
+ reflect: boolean;
30
+ };
31
+ placement: {
32
+ type: StringConstructor;
33
+ };
34
+ };
35
+ /** Om panelet er åpent. Speiles, så CSS kan treffe tilstanden. */
36
+ open: boolean;
37
+ /** Hvilken kant panelet henger fra. Standard: `bottom-start`. */
38
+ placement: Placement;
39
+ private panel?;
40
+ private triggerElement?;
41
+ createRenderRoot(): this;
42
+ render(): import("lit").TemplateResult<1>;
43
+ connectedCallback(): void;
44
+ disconnectedCallback(): void;
45
+ firstUpdated(): void;
46
+ updated(): void;
47
+ private handleSlotChange;
48
+ private sync;
49
+ private handleTriggerClick;
50
+ private handleOutsideClick;
51
+ private handleKeydown;
52
+ /** Regner ut hvor panelet skal stå, mot knappens plass på skjermen. */
53
+ private reposition;
54
+ /** Åpner panelet. */
55
+ show(): void;
56
+ /** Lukker panelet. */
57
+ hide(): void;
58
+ /** Åpner eller lukker. */
59
+ toggle(): void;
60
+ }
61
+ declare global {
62
+ interface HTMLElementTagNameMap {
63
+ "fs-popover": FsPopover;
64
+ }
65
+ }
66
+ export declare function defineFsPopover(tagName?: "fs-popover"): void;
67
+ export {};
68
+ //# sourceMappingURL=fs-popover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-popover.d.ts","sourceRoot":"","sources":["../../../../src/components/ramme/popover/fs-popover.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,UAAU,EAAE,MAAM,KAAK,CAAA;AAEtC,eAAO,MAAM,cAAc,EAAG,YAAqB,CAAA;AAEnD,eAAO,MAAM,aAAa,EAAG,YAAqB,CAAA;AAElD,KAAK,SAAS,GAAG,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,SAAS,CAAA;AAExE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,SAAU,SAAQ,UAAU;IACvC,MAAM,CAAC,UAAU;;;;;;;;MAGhB;IAED,kEAAkE;IAClE,IAAI,UAAQ;IACZ,iEAAiE;IACjE,SAAS,EAAE,SAAS,CAAiB;IAErC,OAAO,CAAC,KAAK,CAAC,CAAa;IAC3B,OAAO,CAAC,cAAc,CAAC,CAAa;IAEpC,gBAAgB;IAIhB,MAAM;IAIN,iBAAiB;IAMjB,oBAAoB;IAMpB,YAAY;IAIZ,OAAO;IAIP,OAAO,CAAC,gBAAgB,CAEvB;IAED,OAAO,CAAC,IAAI;IAyCZ,OAAO,CAAC,kBAAkB,CAEzB;IAED,OAAO,CAAC,kBAAkB,CAIzB;IAED,OAAO,CAAC,aAAa,CAMpB;IAED,uEAAuE;IACvE,OAAO,CAAC,UAAU,CAyBjB;IAED,qBAAqB;IACrB,IAAI;IAYJ,sBAAsB;IACtB,IAAI;IAYJ,0BAA0B;IAC1B,MAAM;CAIP;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,YAAY,EAAE,SAAS,CAAA;KACxB;CACF;AAED,wBAAgB,eAAe,CAAC,OAAO,eAAiB,GAAG,IAAI,CAI9D"}