@fremtind/jokul 5.0.0-next.1 → 5.0.0-next.11

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 (350) hide show
  1. package/README.md +41 -22
  2. package/bin/jokul.mjs +10 -0
  3. package/bin/run-jokul-cli.mjs +63 -0
  4. package/build/build-stats.html +1 -1
  5. package/build/cjs/components/card/Card.cjs +1 -1
  6. package/build/cjs/components/card/Card.cjs.map +1 -1
  7. package/build/cjs/components/card/index.d.cts +1 -1
  8. package/build/cjs/components/card/types.cjs +1 -1
  9. package/build/cjs/components/card/types.cjs.map +1 -1
  10. package/build/cjs/components/card/types.d.cts +3 -6
  11. package/build/cjs/components/checkbox/Checkbox.cjs +1 -1
  12. package/build/cjs/components/checkbox/Checkbox.cjs.map +1 -1
  13. package/build/cjs/components/cookie-consent/CookieConsent.cjs +1 -1
  14. package/build/cjs/components/cookie-consent/CookieConsent.cjs.map +1 -1
  15. package/build/cjs/components/cookie-consent/CookieConsent.d.cts +1 -1
  16. package/build/cjs/components/cookie-consent/types.d.cts +4 -0
  17. package/build/cjs/components/datepicker/DatePicker.cjs +1 -1
  18. package/build/cjs/components/datepicker/DatePicker.cjs.map +1 -1
  19. package/build/cjs/components/expander/ExpandablePanel.cjs +1 -1
  20. package/build/cjs/components/expander/ExpandablePanel.cjs.map +1 -1
  21. package/build/cjs/components/link/Link.cjs +1 -1
  22. package/build/cjs/components/link/Link.cjs.map +1 -1
  23. package/build/cjs/components/link/Link.d.cts +2 -2
  24. package/build/cjs/components/link/types.d.cts +1 -4
  25. package/build/cjs/components/modal/Modal.cjs +1 -1
  26. package/build/cjs/components/modal/Modal.cjs.map +1 -1
  27. package/build/cjs/components/modal/Modal.d.cts +2 -9
  28. package/build/cjs/components/modal/index.d.cts +1 -1
  29. package/build/cjs/components/modal/types.d.cts +18 -0
  30. package/build/cjs/components/popover/Popover.cjs +1 -1
  31. package/build/cjs/components/popover/Popover.cjs.map +1 -1
  32. package/build/cjs/components/radio-button/BaseRadioButton.cjs +1 -1
  33. package/build/cjs/components/radio-button/BaseRadioButton.cjs.map +1 -1
  34. package/build/cjs/components/text-area/BaseTextArea.cjs +1 -1
  35. package/build/cjs/components/text-area/BaseTextArea.cjs.map +1 -1
  36. package/build/cjs/components/text-area/counter.cjs +2 -0
  37. package/build/cjs/components/text-area/counter.cjs.map +1 -0
  38. package/build/cjs/components/text-area/counter.d.cts +2 -0
  39. package/build/cjs/components/text-area/types.d.cts +21 -1
  40. package/build/cjs/components/typography/Text.cjs +2 -0
  41. package/build/cjs/components/typography/Text.cjs.map +1 -0
  42. package/build/cjs/components/typography/Text.d.cts +5 -0
  43. package/build/cjs/components/typography/Title.cjs +2 -0
  44. package/build/cjs/components/typography/Title.cjs.map +1 -0
  45. package/build/cjs/components/typography/Title.d.cts +5 -0
  46. package/build/cjs/components/typography/index.cjs +2 -0
  47. package/build/cjs/components/typography/index.cjs.map +1 -0
  48. package/build/cjs/components/typography/index.d.cts +3 -0
  49. package/build/cjs/components/typography/types.cjs +2 -0
  50. package/build/cjs/components/typography/types.cjs.map +1 -0
  51. package/build/cjs/components/typography/types.d.cts +48 -0
  52. package/build/cjs/tokens.cjs +1 -1
  53. package/build/cjs/tokens.cjs.map +1 -1
  54. package/build/cjs/tokens.d.cts +90 -38
  55. package/build/es/components/card/Card.js +1 -1
  56. package/build/es/components/card/Card.js.map +1 -1
  57. package/build/es/components/card/index.d.ts +1 -1
  58. package/build/es/components/card/types.d.ts +3 -6
  59. package/build/es/components/card/types.js +1 -1
  60. package/build/es/components/card/types.js.map +1 -1
  61. package/build/es/components/checkbox/Checkbox.js +1 -1
  62. package/build/es/components/checkbox/Checkbox.js.map +1 -1
  63. package/build/es/components/cookie-consent/CookieConsent.d.ts +1 -1
  64. package/build/es/components/cookie-consent/CookieConsent.js +1 -1
  65. package/build/es/components/cookie-consent/CookieConsent.js.map +1 -1
  66. package/build/es/components/cookie-consent/types.d.ts +4 -0
  67. package/build/es/components/datepicker/DatePicker.js +1 -1
  68. package/build/es/components/datepicker/DatePicker.js.map +1 -1
  69. package/build/es/components/expander/ExpandablePanel.js +1 -1
  70. package/build/es/components/expander/ExpandablePanel.js.map +1 -1
  71. package/build/es/components/link/Link.d.ts +2 -2
  72. package/build/es/components/link/Link.js +1 -1
  73. package/build/es/components/link/Link.js.map +1 -1
  74. package/build/es/components/link/types.d.ts +1 -4
  75. package/build/es/components/modal/Modal.d.ts +2 -9
  76. package/build/es/components/modal/Modal.js +1 -1
  77. package/build/es/components/modal/Modal.js.map +1 -1
  78. package/build/es/components/modal/index.d.ts +1 -1
  79. package/build/es/components/modal/types.d.ts +18 -0
  80. package/build/es/components/popover/Popover.js +1 -1
  81. package/build/es/components/popover/Popover.js.map +1 -1
  82. package/build/es/components/radio-button/BaseRadioButton.js +1 -1
  83. package/build/es/components/radio-button/BaseRadioButton.js.map +1 -1
  84. package/build/es/components/text-area/BaseTextArea.js +1 -1
  85. package/build/es/components/text-area/BaseTextArea.js.map +1 -1
  86. package/build/es/components/text-area/counter.d.ts +2 -0
  87. package/build/es/components/text-area/counter.js +2 -0
  88. package/build/es/components/text-area/counter.js.map +1 -0
  89. package/build/es/components/text-area/types.d.ts +21 -1
  90. package/build/es/components/typography/Text.d.ts +5 -0
  91. package/build/es/components/typography/Text.js +2 -0
  92. package/build/es/components/typography/Text.js.map +1 -0
  93. package/build/es/components/typography/Title.d.ts +5 -0
  94. package/build/es/components/typography/Title.js +2 -0
  95. package/build/es/components/typography/Title.js.map +1 -0
  96. package/build/es/components/typography/index.d.ts +3 -0
  97. package/build/es/components/typography/index.js +2 -0
  98. package/build/es/components/typography/index.js.map +1 -0
  99. package/build/es/components/typography/types.d.ts +48 -0
  100. package/build/es/components/typography/types.js +2 -0
  101. package/build/es/components/typography/types.js.map +1 -0
  102. package/build/es/tokens.d.ts +90 -38
  103. package/build/es/tokens.js +1 -1
  104. package/build/es/tokens.js.map +1 -1
  105. package/codemods/CODEMODS.md +133 -0
  106. package/codemods/__tests__/import-paths.test.mjs +648 -0
  107. package/codemods/import-paths.mjs +198 -0
  108. package/codemods/transforms/color-tokens.mjs +77 -0
  109. package/codemods/transforms/font-family.mjs +23 -0
  110. package/codemods/transforms/import-specifiers.mjs +230 -0
  111. package/codemods/transforms/warnings.mjs +41 -0
  112. package/codemods/utils.mjs +35 -0
  113. package/package.json +7 -1
  114. package/src/fonts/InterVariable-Italic.woff2 +0 -0
  115. package/src/fonts/InterVariable.woff2 +0 -0
  116. package/src/fonts/brands/dnb/DNB-Bold.woff2 +0 -0
  117. package/src/fonts/brands/dnb/DNB-Medium.woff2 +0 -0
  118. package/src/fonts/brands/dnb/DNB-Regular.woff2 +0 -0
  119. package/src/fonts/brands/dnb/DNBMono-Regular.woff2 +0 -0
  120. package/src/fonts/brands/eika/OpenSans-Bold.woff2 +0 -0
  121. package/src/fonts/brands/eika/OpenSans-Light.woff2 +0 -0
  122. package/src/fonts/brands/eika/OpenSans-Regular.woff2 +0 -0
  123. package/src/fonts/brands/eika/OpenSans-SemiBold.woff2 +0 -0
  124. package/src/fonts/brands/fremtind/Fremtind-Material-Symbols.woff2 +0 -0
  125. package/src/fonts/brands/fremtind/InterVariable-Italic.woff2 +0 -0
  126. package/src/fonts/brands/fremtind/InterVariable.woff2 +0 -0
  127. package/src/fonts/brands/sparebank1/SpareBank1-Medium-Web.woff2 +0 -0
  128. package/src/fonts/brands/sparebank1/SpareBank1-Regular-Web.woff2 +0 -0
  129. package/src/fonts/brands/sparebank1/SpareBank1-Title-Medium-Web.woff2 +0 -0
  130. package/styles/base.css +819 -218
  131. package/styles/base.min.css +1 -1
  132. package/styles/components/autosuggest/autosuggest.css +4 -4
  133. package/styles/components/autosuggest/autosuggest.min.css +1 -1
  134. package/styles/components/autosuggest/autosuggest.scss +4 -4
  135. package/styles/components/beta/description-list/description-list.css +1 -1
  136. package/styles/components/beta/description-list/description-list.min.css +1 -1
  137. package/styles/components/beta/description-list/description-list.scss +1 -1
  138. package/styles/components/beta/nav-link/navlink.css +4 -4
  139. package/styles/components/beta/nav-link/navlink.min.css +1 -1
  140. package/styles/components/beta/nav-link/navlink.scss +6 -4
  141. package/styles/components/beta/select/select.css +9 -9
  142. package/styles/components/beta/select/select.min.css +1 -1
  143. package/styles/components/beta/select/select.scss +8 -7
  144. package/styles/components/breadcrumb/breadcrumb.css +1 -1
  145. package/styles/components/breadcrumb/breadcrumb.min.css +1 -1
  146. package/styles/components/button/button.css +8 -4
  147. package/styles/components/button/button.min.css +1 -1
  148. package/styles/components/button/button.scss +14 -14
  149. package/styles/components/card/card.css +6 -11
  150. package/styles/components/card/card.min.css +1 -1
  151. package/styles/components/card/card.scss +5 -12
  152. package/styles/components/checkbox/checkbox.css +43 -15
  153. package/styles/components/checkbox/checkbox.min.css +1 -1
  154. package/styles/components/checkbox/checkbox.scss +35 -24
  155. package/styles/components/checkbox-panel/checkbox-panel.css +65 -32
  156. package/styles/components/checkbox-panel/checkbox-panel.min.css +1 -1
  157. package/styles/components/checkbox-panel/checkbox-panel.scss +4 -0
  158. package/styles/components/checkbox-panel/development/styles.scss +1 -1
  159. package/styles/components/chip/chip.css +6 -6
  160. package/styles/components/chip/chip.min.css +1 -1
  161. package/styles/components/chip/chip.scss +6 -6
  162. package/styles/components/combobox/combobox.css +25 -23
  163. package/styles/components/combobox/combobox.min.css +1 -1
  164. package/styles/components/combobox/combobox.scss +15 -18
  165. package/styles/components/countdown/countdown.css +4 -4
  166. package/styles/components/countdown/countdown.min.css +1 -1
  167. package/styles/components/datepicker/_calendar-date-button.scss +11 -9
  168. package/styles/components/datepicker/_calendar-navigation-dropdown.scss +1 -1
  169. package/styles/components/datepicker/_calendar.scss +6 -7
  170. package/styles/components/datepicker/datepicker.css +20 -12
  171. package/styles/components/datepicker/datepicker.min.css +1 -1
  172. package/styles/components/description-list/description-list.css +1 -1
  173. package/styles/components/description-list/description-list.min.css +1 -1
  174. package/styles/components/description-list/description-list.scss +1 -1
  175. package/styles/components/expander/expandable.css +29 -27
  176. package/styles/components/expander/expandable.min.css +1 -1
  177. package/styles/components/expander/expandable.scss +29 -30
  178. package/styles/components/feedback/_index.scss +1 -1
  179. package/styles/components/feedback/feedback.css +6 -8
  180. package/styles/components/feedback/feedback.min.css +1 -1
  181. package/styles/components/feedback/feedback.scss +4 -9
  182. package/styles/components/file/file.css +5 -5
  183. package/styles/components/file/file.min.css +1 -1
  184. package/styles/components/file/file.scss +5 -5
  185. package/styles/components/file-input/file-input.css +29 -25
  186. package/styles/components/file-input/file-input.min.css +1 -1
  187. package/styles/components/file-input/file-input.scss +3 -3
  188. package/styles/components/help/help.css +2 -2
  189. package/styles/components/help/help.min.css +1 -1
  190. package/styles/components/help/help.scss +4 -4
  191. package/styles/components/icon/_base-styles.scss +12 -14
  192. package/styles/components/icon/icon.css +5 -5
  193. package/styles/components/icon/icon.min.css +1 -1
  194. package/styles/components/icon/icon.scss +73 -73
  195. package/styles/components/icon-button/icon-button.css +2 -2
  196. package/styles/components/icon-button/icon-button.min.css +1 -1
  197. package/styles/components/icon-button/icon-button.scss +1 -1
  198. package/styles/components/input-group/input-group.css +2 -2
  199. package/styles/components/input-group/input-group.min.css +1 -1
  200. package/styles/components/input-panel/input-panel.css +19 -17
  201. package/styles/components/input-panel/input-panel.min.css +1 -1
  202. package/styles/components/input-panel/input-panel.scss +21 -20
  203. package/styles/components/link/link.css +2 -2
  204. package/styles/components/link/link.min.css +1 -1
  205. package/styles/components/link-list/link-list.css +8 -4
  206. package/styles/components/link-list/link-list.min.css +1 -1
  207. package/styles/components/link-list/link-list.scss +7 -3
  208. package/styles/components/list/list.css +37 -21
  209. package/styles/components/list/list.min.css +1 -1
  210. package/styles/components/list/list.scss +27 -23
  211. package/styles/components/loader/loader.css +6 -6
  212. package/styles/components/loader/loader.min.css +1 -1
  213. package/styles/components/loader/skeleton-loader.css +4 -4
  214. package/styles/components/loader/skeleton-loader.min.css +1 -1
  215. package/styles/components/loader/skeleton-loader.scss +1 -1
  216. package/styles/components/menu/_menu-divider.scss +1 -1
  217. package/styles/components/menu/_menu-item.scss +2 -2
  218. package/styles/components/menu/menu.css +5 -5
  219. package/styles/components/menu/menu.min.css +1 -1
  220. package/styles/components/menu/menu.scss +2 -2
  221. package/styles/components/message/message.css +20 -10
  222. package/styles/components/message/message.min.css +1 -1
  223. package/styles/components/message/message.scss +19 -12
  224. package/styles/components/modal/_layout.scss +22 -0
  225. package/styles/components/modal/_modal-base.scss +32 -0
  226. package/styles/components/modal/_motion.scss +45 -0
  227. package/styles/components/modal/_overlay.scss +20 -0
  228. package/styles/components/modal/_parts.scss +33 -0
  229. package/styles/components/modal/_placement.scss +59 -0
  230. package/styles/components/modal/modal.css +118 -34
  231. package/styles/components/modal/modal.min.css +1 -1
  232. package/styles/components/modal/modal.scss +6 -95
  233. package/styles/components/nav-link/nav-link.css +1 -1
  234. package/styles/components/nav-link/nav-link.min.css +1 -1
  235. package/styles/components/pagination/development/styles.scss +1 -1
  236. package/styles/components/pagination/pagination.css +3 -3
  237. package/styles/components/pagination/pagination.min.css +1 -1
  238. package/styles/components/pagination/pagination.scss +2 -2
  239. package/styles/components/popover/popover.css +12 -1
  240. package/styles/components/popover/popover.min.css +1 -1
  241. package/styles/components/popover/popover.scss +15 -1
  242. package/styles/components/progress-bar/progress-bar.css +27 -3
  243. package/styles/components/progress-bar/progress-bar.min.css +1 -1
  244. package/styles/components/progress-bar/progress-bar.scss +5 -0
  245. package/styles/components/radio-button/radio-button.css +43 -8
  246. package/styles/components/radio-button/radio-button.min.css +1 -1
  247. package/styles/components/radio-button/radio-button.scss +35 -16
  248. package/styles/components/radio-panel/development/styles.scss +1 -1
  249. package/styles/components/radio-panel/radio-panel.css +22 -17
  250. package/styles/components/radio-panel/radio-panel.min.css +1 -1
  251. package/styles/components/radio-panel/radio-panel.scss +4 -0
  252. package/styles/components/search/search-with-submit-button.css +1 -1
  253. package/styles/components/search/search-with-submit-button.min.css +1 -1
  254. package/styles/components/search/search-with-submit-button.scss +1 -1
  255. package/styles/components/search/search.css +4 -4
  256. package/styles/components/search/search.min.css +1 -1
  257. package/styles/components/search/search.scss +3 -3
  258. package/styles/components/segmented-control/segmented-control.css +61 -26
  259. package/styles/components/segmented-control/segmented-control.min.css +1 -1
  260. package/styles/components/segmented-control/segmented-control.scss +7 -7
  261. package/styles/components/select/select.css +17 -18
  262. package/styles/components/select/select.min.css +1 -1
  263. package/styles/components/select/select.scss +24 -29
  264. package/styles/components/summary-table/development/summary-table-example.scss +1 -1
  265. package/styles/components/summary-table/summary-table.css +2 -2
  266. package/styles/components/summary-table/summary-table.min.css +1 -1
  267. package/styles/components/summary-table/summary-table.scss +2 -2
  268. package/styles/components/system-message/system-message.css +23 -13
  269. package/styles/components/system-message/system-message.min.css +1 -1
  270. package/styles/components/system-message/system-message.scss +119 -108
  271. package/styles/components/table/_table-head.scss +1 -1
  272. package/styles/components/table/_table-row.scss +5 -3
  273. package/styles/components/table/table.css +6 -4
  274. package/styles/components/table/table.min.css +1 -1
  275. package/styles/components/table-of-contents/table-of-contents.css +2 -2
  276. package/styles/components/table-of-contents/table-of-contents.min.css +1 -1
  277. package/styles/components/table-of-contents/table-of-contents.scss +3 -3
  278. package/styles/components/tabs/tabs.css +5 -5
  279. package/styles/components/tabs/tabs.min.css +1 -1
  280. package/styles/components/tabs/tabs.scss +5 -6
  281. package/styles/components/tag/tag.css +16 -6
  282. package/styles/components/tag/tag.min.css +1 -1
  283. package/styles/components/tag/tag.scss +18 -7
  284. package/styles/components/text-area/text-area.css +12 -12
  285. package/styles/components/text-area/text-area.min.css +1 -1
  286. package/styles/components/text-input/text-input.css +12 -12
  287. package/styles/components/text-input/text-input.min.css +1 -1
  288. package/styles/components/toast/toast.css +20 -13
  289. package/styles/components/toast/toast.min.css +1 -1
  290. package/styles/components/toast/toast.scss +19 -18
  291. package/styles/components/toggle-switch/_toggle-slider.scss +4 -4
  292. package/styles/components/toggle-switch/toggle-switch.css +15 -25
  293. package/styles/components/toggle-switch/toggle-switch.min.css +1 -3
  294. package/styles/components/toggle-switch/toggle-switch.scss +10 -22
  295. package/styles/components/tooltip/tooltip.css +5 -5
  296. package/styles/components/tooltip/tooltip.min.css +1 -1
  297. package/styles/components/tooltip/tooltip.scss +5 -5
  298. package/styles/components/typography/_index.scss +2 -0
  299. package/styles/components/typography/text.css +38 -0
  300. package/styles/components/typography/text.min.css +1 -0
  301. package/styles/components/typography/text.scss +54 -0
  302. package/styles/components/typography/title.css +55 -0
  303. package/styles/components/typography/title.min.css +1 -0
  304. package/styles/components/typography/title.scss +59 -0
  305. package/styles/components.css +729 -395
  306. package/styles/components.min.css +1 -3
  307. package/styles/components.scss +53 -52
  308. package/styles/global/_base-class.scss +2 -2
  309. package/styles/global/_top-layer.scss +1 -1
  310. package/styles/hooks/stories/styles.scss +3 -3
  311. package/styles/jkl/_ornaments.scss +1 -1
  312. package/styles/jkl/_tokens.scss +140 -66
  313. package/styles/jkl/_typography.scss +13 -21
  314. package/styles/shared/input/shared-input-styles.scss +11 -15
  315. package/styles/shared/track/track.scss +2 -2
  316. package/styles/tailwind.css +106 -62
  317. package/styles/theme/_color-scheme.scss +107 -60
  318. package/styles/theme/_dynamic-spacing.scss +24 -18
  319. package/styles/theme/_fonts.scss +19 -78
  320. package/styles/theme/_index.scss +4 -0
  321. package/styles/theme/_size.scss +20 -20
  322. package/styles/theme/_tokens.scss +14 -14
  323. package/styles/theme/brands/dnb/_color-scheme.scss +121 -0
  324. package/styles/theme/brands/dnb/_fonts.scss +46 -0
  325. package/styles/theme/brands/dnb/_index.scss +2 -0
  326. package/styles/theme/brands/eika/_color-scheme.scss +121 -0
  327. package/styles/theme/brands/eika/_fonts.scss +46 -0
  328. package/styles/theme/brands/eika/_index.scss +2 -0
  329. package/styles/theme/brands/fremtind/_color-scheme.scss +121 -0
  330. package/styles/theme/brands/fremtind/_fonts.scss +30 -0
  331. package/styles/theme/brands/fremtind/_index.scss +2 -0
  332. package/styles/theme/brands/sparebank1/_color-scheme.scss +121 -0
  333. package/styles/theme/brands/sparebank1/_fonts.scss +38 -0
  334. package/styles/theme/brands/sparebank1/_index.scss +2 -0
  335. package/styles/utility/_headings.scss +1 -1
  336. package/styles/utility/_paragraphs.scss +2 -2
  337. package/styles/utility/_screen-reader.scss +1 -1
  338. package/styles/utility/_spacing.scss +2 -2
  339. package/src/fonts/FremtindGrotesk-Bold-Web.woff +0 -0
  340. package/src/fonts/FremtindGrotesk-Bold-Web.woff2 +0 -0
  341. package/src/fonts/FremtindGrotesk-BoldItalic-Web.woff +0 -0
  342. package/src/fonts/FremtindGrotesk-BoldItalic-Web.woff2 +0 -0
  343. package/src/fonts/FremtindGrotesk-Display-Web.woff +0 -0
  344. package/src/fonts/FremtindGrotesk-Display-Web.woff2 +0 -0
  345. package/src/fonts/FremtindGrotesk-Italic-Web.woff +0 -0
  346. package/src/fonts/FremtindGrotesk-Italic-Web.woff2 +0 -0
  347. package/src/fonts/FremtindGrotesk-Regular-Web.woff +0 -0
  348. package/src/fonts/FremtindGrotesk-Regular-Web.woff2 +0 -0
  349. package/src/fonts/FremtindGroteskMono-Regular-Web.woff +0 -0
  350. package/src/fonts/FremtindGroteskMono-Regular-Web.woff2 +0 -0
@@ -0,0 +1,648 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { transformImportPaths } from "../import-paths.mjs";
4
+
5
+ test("migrates core, styles and utilities imports", () => {
6
+ const source = `
7
+ import "@fremtind/jokul/styles/core/core.scss";
8
+ import "@fremtind/jokul/styles/styles.scss";
9
+ import type { WithChildren } from "@fremtind/jokul/core";
10
+ `;
11
+
12
+ const result = transformImportPaths(source, "/tmp/example.ts");
13
+
14
+ assert.equal(
15
+ result.text.includes('import "@fremtind/jokul/styles/base.scss";'),
16
+ true,
17
+ );
18
+ assert.equal(
19
+ result.text.includes('import "@fremtind/jokul/styles/components.scss";'),
20
+ true,
21
+ );
22
+ assert.equal(
23
+ result.text.includes(
24
+ 'import type { WithChildren } from "@fremtind/jokul/utilities";',
25
+ ),
26
+ true,
27
+ );
28
+ });
29
+
30
+ test("moves configured font imports ahead of base styles", () => {
31
+ const source = `@use "@fremtind/jokul/styles/core";
32
+ @use "@fremtind/jokul/styles/fonts" with (
33
+ $webfonts-dir: "../../src/fonts"
34
+ );
35
+ `;
36
+
37
+ const result = transformImportPaths(source, "/tmp/global.scss");
38
+
39
+ assert.match(
40
+ result.text,
41
+ /^@use "@fremtind\/jokul\/styles\/theme\/fonts" with \([\s\S]*?\);\n@use "@fremtind\/jokul\/styles\/base\.scss";/m,
42
+ );
43
+ assert.equal(result.reordered, true);
44
+ });
45
+
46
+ test("migrates internal relative core jkl imports", () => {
47
+ const source = `@use "../../../core/jkl";
48
+ `;
49
+
50
+ const result = transformImportPaths(
51
+ source,
52
+ "/tmp/components/modal/styles/_layout.scss",
53
+ );
54
+
55
+ assert.equal(result.text, '@use "../../../styles/jkl";\n');
56
+ });
57
+
58
+ test("rewrites beta style imports when the beta component is used in the same file", () => {
59
+ const source = `
60
+ import { BETA_Select } from "@fremtind/jokul/select";
61
+ import "@fremtind/jokul/styles/components/select";
62
+ `;
63
+
64
+ const result = transformImportPaths(source, "/tmp/MyForm.tsx");
65
+
66
+ assert.equal(
67
+ result.text.includes(
68
+ '@fremtind/jokul/styles/components/beta/select',
69
+ ),
70
+ true,
71
+ );
72
+ assert.deepEqual(result.warnings, []);
73
+ });
74
+
75
+ test("warns when beta style import is ambiguous (no beta identifier in file)", () => {
76
+ const source = `
77
+ import "@fremtind/jokul/styles/components/select";
78
+ `;
79
+
80
+ const result = transformImportPaths(source, "/tmp/global.scss");
81
+
82
+ assert.equal(result.warnings.length, 1);
83
+ assert.match(result.warnings[0], /Select/);
84
+ });
85
+
86
+ test("removes esm webfonts.css import when base or components css is present", () => {
87
+ const source = `import "@fremtind/jokul/styles/base.css";
88
+ import "@fremtind/jokul/styles/fonts/webfonts.css";
89
+ `;
90
+
91
+ const result = transformImportPaths(source, "/tmp/main.tsx");
92
+
93
+ assert.equal(result.text.includes("webfonts"), false);
94
+ assert.deepEqual(result.warnings, []);
95
+ });
96
+
97
+ test("warns when webfonts.css is removed without a base or components import", () => {
98
+ const source = `import "@fremtind/jokul/styles/fonts/webfonts.css";
99
+ `;
100
+
101
+ const result = transformImportPaths(source, "/tmp/main.tsx");
102
+
103
+ assert.equal(result.text.includes("webfonts"), false);
104
+ assert.equal(result.warnings.length, 1);
105
+ assert.match(result.warnings[0], /styles\/base\.css/);
106
+ });
107
+
108
+ test("removes css @import of webfonts.css", () => {
109
+ const source = `@import "@fremtind/jokul/styles/components.css";
110
+ @import "@fremtind/jokul/styles/fonts/webfonts.css";
111
+ `;
112
+
113
+ const result = transformImportPaths(source, "/tmp/global.css");
114
+
115
+ assert.equal(result.text.includes("webfonts"), false);
116
+ assert.equal(
117
+ result.text.includes('@import "@fremtind/jokul/styles/components.css";'),
118
+ true,
119
+ );
120
+ assert.deepEqual(result.warnings, []);
121
+ });
122
+
123
+
124
+ test("renames Fremtind Material Symbols font-family", () => {
125
+ const source = `.icon {
126
+ font-family: "Fremtind Material Symbols", "Fremtind Material Symbols Fallback", sans-serif;
127
+ }
128
+ `;
129
+
130
+ const result = transformImportPaths(source, "/tmp/icons.scss");
131
+
132
+ assert.equal(
133
+ result.text.includes("Fremtind Material Symbols"),
134
+ false,
135
+ );
136
+ assert.equal(
137
+ result.text.includes(
138
+ '"Jokul Icons", "Jokul Icons Fallback", sans-serif',
139
+ ),
140
+ true,
141
+ );
142
+ assert.equal(result.replacements, 2);
143
+ });
144
+
145
+ test("renames Fremtind Material Symbols inside CSS files too", () => {
146
+ const source = `.icon {
147
+ font-family: 'Fremtind Material Symbols';
148
+ }
149
+ `;
150
+
151
+ const result = transformImportPaths(source, "/tmp/icons.css");
152
+
153
+ assert.equal(
154
+ result.text.includes("Fremtind Material Symbols"),
155
+ false,
156
+ );
157
+ assert.equal(result.text.includes("'Jokul Icons'"), true);
158
+ });
159
+
160
+ test("renames CSS background-action token", () => {
161
+ const source = `.btn {
162
+ background: var(--jkl-color-background-action);
163
+ color: var(--jkl-color-text-on-action);
164
+ }
165
+ `;
166
+
167
+ const result = transformImportPaths(source, "/tmp/button.css");
168
+
169
+ assert.equal(result.text.includes("--jkl-color-background-action"), false);
170
+ assert.equal(result.text.includes("--jkl-color-text-on-action"), false);
171
+ assert.equal(result.text.includes("--jkl-color-background-contrast"), true);
172
+ assert.equal(result.text.includes("--jkl-color-text-on-contrast"), true);
173
+ assert.equal(result.changed, true);
174
+ });
175
+
176
+ test("renames CSS text-inverted token to text-on-contrast", () => {
177
+ const source = `.inverted {
178
+ color: var(--jkl-color-text-inverted);
179
+ }
180
+ `;
181
+
182
+ const result = transformImportPaths(source, "/tmp/theme.css");
183
+
184
+ assert.equal(result.text.includes("--jkl-color-text-inverted"), false);
185
+ assert.equal(result.text.includes("--jkl-color-text-on-contrast"), true);
186
+ });
187
+
188
+ test("renames CSS container-high and container-low tokens", () => {
189
+ const source = `.card-high {
190
+ background: var(--jkl-color-background-container-high);
191
+ }
192
+ .card-low {
193
+ background: var(--jkl-color-background-container-low);
194
+ }
195
+ `;
196
+
197
+ const result = transformImportPaths(source, "/tmp/card.css");
198
+
199
+ assert.equal(result.text.includes("--jkl-color-background-container-high"), false);
200
+ assert.equal(result.text.includes("--jkl-color-background-container-low"), false);
201
+ assert.equal(
202
+ result.text.split("--jkl-color-background-container").length - 1,
203
+ 2,
204
+ "should have two occurrences of the new token",
205
+ );
206
+ });
207
+
208
+ test("renames CSS alert tokens to feedback tokens", () => {
209
+ const source = `.info { background: var(--jkl-color-background-alert-info); }
210
+ .warning { background: var(--jkl-color-background-alert-warning); }
211
+ .error { background: var(--jkl-color-background-alert-error); }
212
+ .success { background: var(--jkl-color-background-alert-success); }
213
+ `;
214
+
215
+ const result = transformImportPaths(source, "/tmp/alerts.css");
216
+
217
+ assert.equal(result.text.includes("--jkl-color-background-alert-"), false);
218
+ assert.equal(result.text.includes("--jkl-color-info-background-container"), true);
219
+ assert.equal(result.text.includes("--jkl-color-warning-background-container"), true);
220
+ assert.equal(result.text.includes("--jkl-color-error-background-container"), true);
221
+ assert.equal(result.text.includes("--jkl-color-success-background-container"), true);
222
+ });
223
+
224
+ test("warns about removed interactive tokens", () => {
225
+ const source = `.item {
226
+ background: var(--jkl-color-background-interactive);
227
+ color: var(--jkl-color-text-interactive);
228
+ }
229
+ `;
230
+
231
+ const result = transformImportPaths(source, "/tmp/interactive.css");
232
+
233
+ assert.equal(
234
+ result.warnings.some((w) => /interactive/.test(w)),
235
+ true,
236
+ );
237
+ assert.equal(
238
+ result.warnings.filter((w) => /interactive/.test(w)).length,
239
+ 1,
240
+ "should produce one warning for both interactive tokens",
241
+ );
242
+ });
243
+
244
+ test("warns about removed text-on-alert tokens", () => {
245
+ const source = `.info { color: var(--jkl-color-text-on-alert-info); }
246
+ `;
247
+
248
+ const result = transformImportPaths(source, "/tmp/alerts.css");
249
+
250
+ assert.equal(
251
+ result.warnings.some((w) => /text-on-alert/.test(w)),
252
+ true,
253
+ );
254
+ });
255
+
256
+ test("warns about Card variant prop", () => {
257
+ const source = `<Card variant="outlined">
258
+ <p>Innhold</p>
259
+ </Card>
260
+ `;
261
+
262
+ const result = transformImportPaths(source, "/tmp/MyCard.tsx");
263
+
264
+ assert.equal(
265
+ result.warnings.some((w) => /variant/.test(w) && /Card/.test(w)),
266
+ true,
267
+ );
268
+ });
269
+
270
+ test("warns about Card variant high and low", () => {
271
+ const source = `function Page() {
272
+ return (
273
+ <>
274
+ <Card variant="high">Høy</Card>
275
+ <Card variant="low">Lav</Card>
276
+ </>
277
+ );
278
+ }
279
+ `;
280
+
281
+ const result = transformImportPaths(source, "/tmp/Page.tsx");
282
+
283
+ assert.equal(
284
+ result.warnings.some((w) => /variant/.test(w)),
285
+ true,
286
+ );
287
+ assert.equal(
288
+ result.warnings.filter((w) => /variant/.test(w)).length,
289
+ 1,
290
+ "should produce one warning even with multiple variant usages",
291
+ );
292
+ });
293
+
294
+ test("renames container-inverted to background-contrast", () => {
295
+ const source = `.inverted { background: var(--jkl-color-background-container-inverted); }
296
+ `;
297
+
298
+ const result = transformImportPaths(source, "/tmp/inverted.css");
299
+
300
+ assert.equal(result.text.includes("--jkl-color-background-container-inverted"), false);
301
+ assert.equal(result.text.includes("--jkl-color-background-contrast"), true);
302
+ assert.deepEqual(result.warnings, []);
303
+ });
304
+
305
+ // --- idempotency ---
306
+
307
+ test("is idempotent — running twice gives same result", () => {
308
+ const source = `import "@fremtind/jokul/styles/core/core.scss";
309
+
310
+ .btn { background: var(--jkl-color-background-action); }
311
+ `;
312
+
313
+ const first = transformImportPaths(source, "/tmp/page.scss");
314
+ const second = transformImportPaths(first.text, "/tmp/page.scss");
315
+
316
+ assert.equal(second.changed, false);
317
+ assert.equal(second.replacements, 0);
318
+ assert.equal(second.text, first.text);
319
+ });
320
+
321
+ // --- no-op ---
322
+
323
+ test("returns changed: false for an already-migrated file", () => {
324
+ const source = `import "@fremtind/jokul/styles/base.scss";
325
+
326
+ .btn { background: var(--jkl-color-background-contrast); }
327
+ `;
328
+
329
+ const result = transformImportPaths(source, "/tmp/page.ts");
330
+
331
+ assert.equal(result.changed, false);
332
+ assert.equal(result.replacements, 0);
333
+ assert.deepEqual(result.warnings, []);
334
+ });
335
+
336
+ // --- token boundary safety ---
337
+
338
+ test("does not rename token that is a prefix of a longer token", () => {
339
+ // --jkl-color-text-inverted should not match inside --jkl-color-text-inverted-extra
340
+ const source = `.x { color: var(--jkl-color-text-inverted-extra); }`;
341
+
342
+ const result = transformImportPaths(source, "/tmp/x.css");
343
+
344
+ assert.equal(result.text.includes("--jkl-color-text-inverted-extra"), true);
345
+ assert.equal(result.changed, false);
346
+ });
347
+
348
+ test("does not rename --jkl-color-background-container (base token, not a v4 token)", () => {
349
+ const source = `.x { background: var(--jkl-color-background-container); }`;
350
+
351
+ const result = transformImportPaths(source, "/tmp/x.css");
352
+
353
+ assert.equal(result.text, source);
354
+ assert.equal(result.changed, false);
355
+ });
356
+
357
+ test("renames container-high but leaves sibling container-low and base container intact in same rule", () => {
358
+ const source = `.x {
359
+ --high: var(--jkl-color-background-container-high);
360
+ --low: var(--jkl-color-background-container-low);
361
+ --base: var(--jkl-color-background-container);
362
+ }
363
+ `;
364
+
365
+ const result = transformImportPaths(source, "/tmp/x.css");
366
+
367
+ assert.equal(result.text.includes("--jkl-color-background-container-high"), false);
368
+ assert.equal(result.text.includes("--jkl-color-background-container-low"), false);
369
+ assert.equal(result.text.includes("var(--jkl-color-background-container)"), true,
370
+ "base container token must survive unchanged");
371
+ assert.equal(result.replacements, 2);
372
+ });
373
+
374
+ test("does not rename alert-info token that has a longer suffix", () => {
375
+ const source = `.x { background: var(--jkl-color-background-alert-info-extra); }`;
376
+
377
+ const result = transformImportPaths(source, "/tmp/x.css");
378
+
379
+ assert.equal(result.changed, false);
380
+ });
381
+
382
+ // --- CSS token as custom property definition ---
383
+
384
+ test("renames token used as a custom property definition, not just inside var()", () => {
385
+ const source = `:root {
386
+ --jkl-color-background-action: #005aa4;
387
+ --jkl-color-text-inverted: #fff;
388
+ }
389
+ `;
390
+
391
+ const result = transformImportPaths(source, "/tmp/overrides.css");
392
+
393
+ assert.equal(result.text.includes("--jkl-color-background-action:"), false);
394
+ assert.equal(result.text.includes("--jkl-color-text-inverted:"), false);
395
+ assert.equal(result.text.includes("--jkl-color-background-contrast:"), true);
396
+ assert.equal(result.text.includes("--jkl-color-text-on-contrast:"), true);
397
+ });
398
+
399
+ // --- webfonts edge cases ---
400
+
401
+ test("removes webfonts.min.css import", () => {
402
+ const source = `import "@fremtind/jokul/styles/base.css";
403
+ import "@fremtind/jokul/styles/fonts/webfonts.min.css";
404
+ `;
405
+
406
+ const result = transformImportPaths(source, "/tmp/main.tsx");
407
+
408
+ assert.equal(result.text.includes("webfonts"), false);
409
+ assert.deepEqual(result.warnings, []);
410
+ });
411
+
412
+ test("removes webfonts.css when imported with require()", () => {
413
+ const source = `require("@fremtind/jokul/styles/base.css");
414
+ require("@fremtind/jokul/styles/fonts/webfonts.css");
415
+ `;
416
+
417
+ const result = transformImportPaths(source, "/tmp/main.cjs");
418
+
419
+ assert.equal(result.text.includes("webfonts"), false);
420
+ assert.deepEqual(result.warnings, []);
421
+ });
422
+
423
+ // --- font family edge cases ---
424
+
425
+ test("renames only the fallback font-family if primary is absent", () => {
426
+ const source = `.icon {
427
+ font-family: "Fremtind Material Symbols Fallback";
428
+ }
429
+ `;
430
+
431
+ const result = transformImportPaths(source, "/tmp/icons.css");
432
+
433
+ assert.equal(result.text.includes("Fremtind Material Symbols Fallback"), false);
434
+ assert.equal(result.text.includes("Jokul Icons Fallback"), true);
435
+ assert.equal(result.replacements, 1);
436
+ });
437
+
438
+ // --- combined transforms ---
439
+
440
+ test("applies import path and token rename in one pass", () => {
441
+ const source = `import "@fremtind/jokul/styles/core/core.scss";
442
+
443
+ .inverted {
444
+ background: var(--jkl-color-background-action);
445
+ }
446
+
447
+ export default function Page() {
448
+ return <section />;
449
+ }
450
+ `;
451
+
452
+ const result = transformImportPaths(source, "/tmp/page.tsx");
453
+
454
+ assert.equal(result.text.includes("styles/core/core"), false);
455
+ assert.equal(result.text.includes("--jkl-color-background-action"), false);
456
+ assert.equal(result.text.includes("styles/base.scss"), true);
457
+ assert.equal(result.text.includes("--jkl-color-background-contrast"), true);
458
+ assert.equal(result.replacements, 2);
459
+ });
460
+
461
+ // --- SCSS-only transforms ---
462
+
463
+ test("does not reorder font import in a .css file", () => {
464
+ const source = `@import "@fremtind/jokul/styles/base.css";
465
+ @import "@fremtind/jokul/styles/theme/fonts";
466
+ `;
467
+
468
+ const result = transformImportPaths(source, "/tmp/global.css");
469
+
470
+ assert.equal(result.reordered, false);
471
+ });
472
+
473
+ // --- Tailwind color class renames ---
474
+
475
+ test("renames bg-background-action to bg-background-contrast", () => {
476
+ const source = `<div className="bg-background-action text-white">Innhold</div>`;
477
+
478
+ const result = transformImportPaths(source, "/tmp/component.tsx");
479
+
480
+ assert.equal(result.text.includes("bg-background-action"), false);
481
+ assert.equal(result.text.includes("bg-background-contrast"), true);
482
+ assert.equal(result.replacements, 1);
483
+ });
484
+
485
+ test("renames text-text-inverted to text-text-on-contrast", () => {
486
+ const source = `<p className="text-text-inverted">Tekst</p>`;
487
+
488
+ const result = transformImportPaths(source, "/tmp/page.tsx");
489
+
490
+ assert.equal(result.text.includes("text-text-inverted"), false);
491
+ assert.equal(result.text.includes("text-text-on-contrast"), true);
492
+ });
493
+
494
+ test("renames text-text-on-action to text-text-on-contrast", () => {
495
+ const source = `<button className="bg-background-contrast text-text-on-action">Knapp</button>`;
496
+
497
+ const result = transformImportPaths(source, "/tmp/button.tsx");
498
+
499
+ assert.equal(result.text.includes("text-text-on-action"), false);
500
+ assert.equal(result.text.includes("text-text-on-contrast"), true);
501
+ });
502
+
503
+ test("renames bg-background-container-high and -low", () => {
504
+ const source = `<div className="bg-background-container-high md:bg-background-container-low">
505
+ Innhold
506
+ </div>`;
507
+
508
+ const result = transformImportPaths(source, "/tmp/card.tsx");
509
+
510
+ assert.equal(result.text.includes("bg-background-container-high"), false);
511
+ assert.equal(result.text.includes("bg-background-container-low"), false);
512
+ assert.equal(result.text.includes("bg-background-container"), true);
513
+ assert.equal(result.replacements, 2);
514
+ });
515
+
516
+ test("does not rename bg-background-container (base Tailwind class)", () => {
517
+ const source = `<div className="bg-background-container">Innhold</div>`;
518
+
519
+ const result = transformImportPaths(source, "/tmp/card.tsx");
520
+
521
+ assert.equal(result.text, source);
522
+ assert.equal(result.changed, false);
523
+ });
524
+
525
+ test("renames bg-background-alert-info to bg-info-background-container", () => {
526
+ const source = `<div className="bg-background-alert-info border-border-subdued">
527
+ Info
528
+ </div>`;
529
+
530
+ const result = transformImportPaths(source, "/tmp/alert.tsx");
531
+
532
+ assert.equal(result.text.includes("bg-background-alert-info"), false);
533
+ assert.equal(result.text.includes("bg-info-background-container"), true);
534
+ assert.equal(result.replacements, 1);
535
+ });
536
+
537
+ test("renames all four alert color classes", () => {
538
+ const source = `className="bg-background-alert-info bg-background-alert-warning bg-background-alert-error bg-background-alert-success"`;
539
+
540
+ const result = transformImportPaths(source, "/tmp/alerts.tsx");
541
+
542
+ assert.equal(result.text.includes("bg-background-alert-"), false);
543
+ assert.equal(result.text.includes("bg-info-background-container"), true);
544
+ assert.equal(result.text.includes("bg-warning-background-container"), true);
545
+ assert.equal(result.text.includes("bg-error-background-container"), true);
546
+ assert.equal(result.text.includes("bg-success-background-container"), true);
547
+ assert.equal(result.replacements, 4);
548
+ });
549
+
550
+ test("renames Tailwind class with hover: modifier", () => {
551
+ const source = `<div className="hover:bg-background-action focus:bg-background-action">X</div>`;
552
+
553
+ const result = transformImportPaths(source, "/tmp/cmp.tsx");
554
+
555
+ assert.equal(result.text.includes("bg-background-action"), false);
556
+ assert.equal(result.text.includes("hover:bg-background-contrast"), true);
557
+ assert.equal(result.text.includes("focus:bg-background-contrast"), true);
558
+ assert.equal(result.replacements, 2);
559
+ });
560
+
561
+ test("renames Tailwind class with opacity modifier (/50)", () => {
562
+ const source = `<div className="bg-background-action/50">X</div>`;
563
+
564
+ const result = transformImportPaths(source, "/tmp/cmp.tsx");
565
+
566
+ assert.equal(result.text.includes("bg-background-action/50"), false);
567
+ assert.equal(result.text.includes("bg-background-contrast/50"), true);
568
+ assert.equal(result.replacements, 1);
569
+ });
570
+
571
+ test("renames Tailwind class in @apply rule", () => {
572
+ const source = `.btn {
573
+ @apply bg-background-action text-text-inverted;
574
+ }
575
+ `;
576
+
577
+ const result = transformImportPaths(source, "/tmp/styles.css");
578
+
579
+ assert.equal(result.text.includes("bg-background-action"), false);
580
+ assert.equal(result.text.includes("text-text-inverted"), false);
581
+ assert.equal(result.text.includes("bg-background-contrast"), true);
582
+ assert.equal(result.text.includes("text-text-on-contrast"), true);
583
+ assert.equal(result.replacements, 2);
584
+ });
585
+
586
+ test("renames non-bg prefix: border-background-action", () => {
587
+ const source = `<div className="border-background-action">X</div>`;
588
+
589
+ const result = transformImportPaths(source, "/tmp/cmp.tsx");
590
+
591
+ assert.equal(result.text.includes("border-background-action"), false);
592
+ assert.equal(result.text.includes("border-background-contrast"), true);
593
+ });
594
+
595
+ test("does not rename longer Tailwind class that shares a prefix", () => {
596
+ // bg-background-container-inverted-extra must not match bg-background-container-inverted
597
+ const source = `<div className="bg-background-container-inverted-extra">X</div>`;
598
+
599
+ const result = transformImportPaths(source, "/tmp/cmp.tsx");
600
+
601
+ assert.equal(result.text, source);
602
+ assert.equal(result.changed, false);
603
+ });
604
+
605
+ test("Tailwind renames are idempotent", () => {
606
+ const source = `<div className="bg-background-contrast text-text-on-contrast">X</div>`;
607
+
608
+ const result = transformImportPaths(source, "/tmp/cmp.tsx");
609
+
610
+ assert.equal(result.changed, false);
611
+ assert.equal(result.replacements, 0);
612
+ });
613
+
614
+ // --- Tailwind warnings ---
615
+
616
+ test("warns about bg-background-interactive Tailwind class", () => {
617
+ const source = `<div className="bg-background-interactive hover:bg-background-interactive-hover">X</div>`;
618
+
619
+ const result = transformImportPaths(source, "/tmp/cmp.tsx");
620
+
621
+ assert.equal(result.warnings.some((w) => /background-interactive/.test(w)), true);
622
+ assert.equal(result.warnings.filter((w) => /background-interactive/.test(w)).length, 1);
623
+ });
624
+
625
+ test("warns about border-border-separator Tailwind class", () => {
626
+ const source = `<div className="border border-border-separator">X</div>`;
627
+
628
+ const result = transformImportPaths(source, "/tmp/cmp.tsx");
629
+
630
+ assert.equal(result.warnings.some((w) => /border-border-separator/.test(w) || /kantklasser/.test(w)), true);
631
+ });
632
+
633
+ // --- does not warn about valid 5.0 patterns ---
634
+
635
+ test("does not warn about valid 5.0 patterns", () => {
636
+ const source = `@use "@fremtind/jokul/styles/jkl";
637
+
638
+ .title {
639
+ @include jkl.text-style("heading-1");
640
+ color: var(--jkl-color-text-default);
641
+ background: var(--jkl-color-background-contrast);
642
+ }
643
+ `;
644
+
645
+ const result = transformImportPaths(source, "/tmp/title.scss");
646
+
647
+ assert.deepEqual(result.warnings, []);
648
+ });