@navikt/ds-react 8.4.0 → 8.5.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 (89) hide show
  1. package/cjs/accordion/Accordion.d.ts +10 -0
  2. package/cjs/accordion/Accordion.js +2 -2
  3. package/cjs/accordion/Accordion.js.map +1 -1
  4. package/cjs/data/table/helpers/table-cell.d.ts +2 -2
  5. package/cjs/data/table/helpers/table-cell.js +2 -5
  6. package/cjs/data/table/helpers/table-cell.js.map +1 -1
  7. package/cjs/data/table/helpers/table-focus.d.ts +26 -2
  8. package/cjs/data/table/helpers/table-focus.js +60 -9
  9. package/cjs/data/table/helpers/table-focus.js.map +1 -1
  10. package/cjs/data/table/helpers/table-grid-nav.d.ts +45 -9
  11. package/cjs/data/table/helpers/table-grid-nav.js +108 -24
  12. package/cjs/data/table/helpers/table-grid-nav.js.map +1 -1
  13. package/cjs/data/table/helpers/table-keyboard.d.ts +24 -3
  14. package/cjs/data/table/helpers/table-keyboard.js +30 -5
  15. package/cjs/data/table/helpers/table-keyboard.js.map +1 -1
  16. package/cjs/data/table/hooks/useGridCache.d.ts +17 -0
  17. package/cjs/data/table/hooks/useGridCache.js +65 -0
  18. package/cjs/data/table/hooks/useGridCache.js.map +1 -0
  19. package/cjs/data/table/root/DataTableRoot.d.ts +1 -1
  20. package/cjs/data/table/root/DataTableRoot.js +2 -2
  21. package/cjs/data/table/root/DataTableRoot.js.map +1 -1
  22. package/cjs/data/table/root/useTableKeyboardNav.d.ts +9 -3
  23. package/cjs/data/table/root/useTableKeyboardNav.js +53 -95
  24. package/cjs/data/table/root/useTableKeyboardNav.js.map +1 -1
  25. package/cjs/data/table/th/DataTableTh.d.ts +1 -1
  26. package/cjs/data/table/th/DataTableTh.js +3 -1
  27. package/cjs/data/table/th/DataTableTh.js.map +1 -1
  28. package/cjs/data/table/tr/DataTableTr.d.ts +6 -2
  29. package/cjs/data/table/tr/DataTableTr.js +4 -2
  30. package/cjs/data/table/tr/DataTableTr.js.map +1 -1
  31. package/cjs/link-card/LinkCard.d.ts +13 -0
  32. package/cjs/link-card/LinkCard.js +2 -2
  33. package/cjs/link-card/LinkCard.js.map +1 -1
  34. package/cjs/process/Process.d.ts +1 -1
  35. package/cjs/utils/i18n/locales/nb.d.ts +154 -75
  36. package/cjs/utils/i18n/locales/nb.js +154 -75
  37. package/cjs/utils/i18n/locales/nb.js.map +1 -1
  38. package/esm/accordion/Accordion.d.ts +10 -0
  39. package/esm/accordion/Accordion.js +2 -2
  40. package/esm/accordion/Accordion.js.map +1 -1
  41. package/esm/data/table/helpers/table-cell.d.ts +2 -2
  42. package/esm/data/table/helpers/table-cell.js +2 -5
  43. package/esm/data/table/helpers/table-cell.js.map +1 -1
  44. package/esm/data/table/helpers/table-focus.d.ts +26 -2
  45. package/esm/data/table/helpers/table-focus.js +55 -9
  46. package/esm/data/table/helpers/table-focus.js.map +1 -1
  47. package/esm/data/table/helpers/table-grid-nav.d.ts +45 -9
  48. package/esm/data/table/helpers/table-grid-nav.js +102 -23
  49. package/esm/data/table/helpers/table-grid-nav.js.map +1 -1
  50. package/esm/data/table/helpers/table-keyboard.d.ts +24 -3
  51. package/esm/data/table/helpers/table-keyboard.js +29 -4
  52. package/esm/data/table/helpers/table-keyboard.js.map +1 -1
  53. package/esm/data/table/hooks/useGridCache.d.ts +17 -0
  54. package/esm/data/table/hooks/useGridCache.js +63 -0
  55. package/esm/data/table/hooks/useGridCache.js.map +1 -0
  56. package/esm/data/table/root/DataTableRoot.d.ts +1 -1
  57. package/esm/data/table/root/DataTableRoot.js +2 -2
  58. package/esm/data/table/root/DataTableRoot.js.map +1 -1
  59. package/esm/data/table/root/useTableKeyboardNav.d.ts +9 -3
  60. package/esm/data/table/root/useTableKeyboardNav.js +58 -100
  61. package/esm/data/table/root/useTableKeyboardNav.js.map +1 -1
  62. package/esm/data/table/th/DataTableTh.d.ts +1 -1
  63. package/esm/data/table/th/DataTableTh.js +3 -1
  64. package/esm/data/table/th/DataTableTh.js.map +1 -1
  65. package/esm/data/table/tr/DataTableTr.d.ts +6 -2
  66. package/esm/data/table/tr/DataTableTr.js +4 -2
  67. package/esm/data/table/tr/DataTableTr.js.map +1 -1
  68. package/esm/link-card/LinkCard.d.ts +13 -0
  69. package/esm/link-card/LinkCard.js +2 -2
  70. package/esm/link-card/LinkCard.js.map +1 -1
  71. package/esm/process/Process.d.ts +1 -1
  72. package/esm/utils/i18n/locales/nb.d.ts +154 -75
  73. package/esm/utils/i18n/locales/nb.js +154 -75
  74. package/esm/utils/i18n/locales/nb.js.map +1 -1
  75. package/package.json +3 -3
  76. package/src/accordion/Accordion.tsx +19 -2
  77. package/src/data/table/helpers/table-cell.ts +2 -7
  78. package/src/data/table/helpers/table-focus.ts +70 -9
  79. package/src/data/table/helpers/table-grid-nav.ts +146 -31
  80. package/src/data/table/helpers/table-keyboard.test.ts +27 -27
  81. package/src/data/table/helpers/table-keyboard.ts +43 -4
  82. package/src/data/table/hooks/useGridCache.ts +73 -0
  83. package/src/data/table/root/DataTableRoot.tsx +2 -3
  84. package/src/data/table/root/useTableKeyboardNav.ts +95 -125
  85. package/src/data/table/th/DataTableTh.tsx +7 -3
  86. package/src/data/table/tr/DataTableTr.tsx +7 -3
  87. package/src/link-card/LinkCard.tsx +15 -1
  88. package/src/process/Process.tsx +1 -1
  89. package/src/utils/i18n/locales/nb.ts +83 -4
@@ -1,60 +1,95 @@
1
- import { useEffect, useRef, useState } from "react";
1
+ import { useEffect } from "react";
2
2
  import { useEventCallback } from "../../../utils/hooks";
3
- import { getActiveCell, getFirstCell } from "../helpers/table-cell";
4
- import { focusCell, focusCellAndUpdateTabIndex } from "../helpers/table-focus";
3
+ import { focusInitialTableTarget } from "../helpers/table-cell";
4
+ import { focusCellAndUpdateTabIndex } from "../helpers/table-focus";
5
5
  import {
6
- type GridCache,
7
- ensureTableGrid,
8
- findNextCell,
6
+ findFirstCell,
7
+ findFirstCellInRow,
8
+ findLastCell,
9
+ findLastCellInRow,
10
+ findNextFocusableCell,
9
11
  } from "../helpers/table-grid-nav";
10
12
  import {
11
- getDeltaFromKey,
12
- shouldBlockArrowKeyNavigation,
13
+ type NavigationAction,
14
+ getNavigationAction,
15
+ shouldBlockNavigation,
13
16
  } from "../helpers/table-keyboard";
17
+ import { useGridCache } from "../hooks/useGridCache";
18
+
19
+ type UseTableKeyboardNavOptions = {
20
+ enabled: boolean;
21
+ /**
22
+ * Custom callback to determine if navigation should be blocked.
23
+ * Called before default blocking logic.
24
+ */
25
+ shouldBlockNavigation?: (event: KeyboardEvent) => boolean;
26
+ };
14
27
 
15
28
  function useTableKeyboardNav(
16
29
  tableRef: HTMLTableElement | null,
17
- { enabled }: { enabled: boolean },
30
+ { enabled, shouldBlockNavigation: customBlockFn }: UseTableKeyboardNavOptions,
18
31
  ) {
19
- const [activeCell, setActiveCell] = useState<Element | null>(null);
20
- const activeCellRef = useRef<Element | null>(null);
21
- activeCellRef.current = activeCell;
22
-
23
- const observerRef = useRef<MutationObserver | null>(null);
24
-
25
- const gridCacheRef = useRef<GridCache>({
26
- grid: null,
27
- dirty: true,
28
- });
32
+ const { getTableGrid, activeCell, setActiveCell } = useGridCache(
33
+ tableRef,
34
+ enabled,
35
+ );
29
36
 
30
37
  /**
31
- * TODO:
32
- * - Save original tabIndex of cells and restore when navigating away?
38
+ * Executes a navigation action and returns the target cell.
33
39
  */
34
- const navigateByArrowKey = useEventCallback(
35
- (delta: { x: number; y: number }) => {
36
- const currentCell = getActiveCell(tableRef, activeCell);
37
- if (!currentCell || !tableRef) {
40
+ const executeNavigationAction = useEventCallback(
41
+ (action: NavigationAction) => {
42
+ if (!tableRef) {
43
+ return null;
44
+ }
45
+
46
+ let currentCell = activeCell;
47
+ currentCell ??= focusInitialTableTarget(tableRef);
48
+
49
+ if (!currentCell) {
38
50
  return null;
39
51
  }
40
52
 
41
- const { grid, positions, maxCols } = ensureTableGrid(
42
- tableRef,
43
- gridCacheRef.current,
44
- );
53
+ const { grid, positions } = getTableGrid(tableRef);
45
54
  const currentPos = positions.get(currentCell);
46
55
 
47
- if (!currentPos) {
56
+ if (
57
+ !currentPos &&
58
+ action.type !== "tableStart" &&
59
+ action.type !== "tableEnd"
60
+ ) {
48
61
  return null;
49
62
  }
50
63
 
51
- const nextCell = findNextCell(
52
- grid,
53
- currentPos,
54
- delta,
55
- currentCell,
56
- maxCols,
57
- );
64
+ let nextCell: Element | null = null;
65
+
66
+ switch (action.type) {
67
+ case "delta":
68
+ nextCell = findNextFocusableCell(
69
+ grid,
70
+ currentPos!,
71
+ action.delta,
72
+ currentCell,
73
+ );
74
+ break;
75
+
76
+ case "home":
77
+ nextCell = findFirstCellInRow(grid, positions, currentCell);
78
+ break;
79
+
80
+ case "end":
81
+ nextCell = findLastCellInRow(grid, positions, currentCell);
82
+ break;
83
+
84
+ case "tableStart":
85
+ nextCell = findFirstCell(grid, currentCell);
86
+ break;
87
+
88
+ case "tableEnd":
89
+ nextCell = findLastCell(grid, currentCell);
90
+ break;
91
+ }
92
+
58
93
  return nextCell
59
94
  ? focusCellAndUpdateTabIndex(nextCell, currentCell)
60
95
  : null;
@@ -62,29 +97,21 @@ function useTableKeyboardNav(
62
97
  );
63
98
 
64
99
  /**
65
- * Handles keyboard navigation with arrow keys.
66
- * We check if the key is an arrow key, and if so, we calculate the next cell to focus based on the current active cell and the grid structure.
67
- *
68
- * TODO:
69
- * - Check for other "blocking" scenarios, like actionmenus, dropdown etc
70
- * - Consider having acallback user can hook into to determine if navigation should be blocked
71
- * - Consider adding Home, End, PageUp, PageDown navigation
72
- *
100
+ * Handles keyboard navigation with arrow keys, Home/End, and PageUp/PageDown.
101
+ * Checks if navigation should be blocked based on current focus context.
73
102
  */
74
- const onKeyDown = useEventCallback((event: KeyboardEvent): void => {
75
- /* Stops keydown from moving if we can assume that you are currently editing input, select etc */
76
- if (shouldBlockArrowKeyNavigation(event)) {
103
+ const handleTableKeyDown = useEventCallback((event: KeyboardEvent): void => {
104
+ if (shouldBlockNavigation(event, customBlockFn)) {
77
105
  return;
78
106
  }
79
107
 
80
- let newCell: Element | null = null;
81
-
82
- const delta = getDeltaFromKey(event.key);
83
- if (delta) {
84
- event.preventDefault();
85
- newCell = navigateByArrowKey(delta);
108
+ const action = getNavigationAction(event);
109
+ if (!action) {
110
+ return;
86
111
  }
87
112
 
113
+ event.preventDefault();
114
+ const newCell = executeNavigationAction(action);
88
115
  newCell && setActiveCell(newCell);
89
116
  });
90
117
 
@@ -92,8 +119,14 @@ function useTableKeyboardNav(
92
119
  * When focus is moved to elements inside a cell like inputs, checkbox etc
93
120
  * we want to update the active cell to the parent td/th, so that keyboard navigation continues to work as expected from there.
94
121
  */
95
- const onFocusIn = useEventCallback((event: FocusEvent): void => {
122
+ const handleTableFocusIn = useEventCallback((event: FocusEvent): void => {
96
123
  const target = event.target as Element | null;
124
+
125
+ if (tableRef && target === tableRef) {
126
+ focusInitialTableTarget(tableRef);
127
+ return;
128
+ }
129
+
97
130
  const newCell = target?.closest("td, th") ?? null;
98
131
  if (!newCell || newCell === activeCell) {
99
132
  return;
@@ -108,90 +141,27 @@ function useTableKeyboardNav(
108
141
  });
109
142
 
110
143
  /**
111
- * Observes changes is table structure and updates the grid cache accordingly.
112
- * - We want to check if elements are removed/added, like when filtering table, pagination etc
113
- * - Changes in colspan/rowspan that can affect the grid structure
114
- * - Hidden attribute or styles that can affect focusability of cells
115
- *
116
- * We also check if the active cell is removed from the DOM, and clear it if so.
144
+ * Attach event listeners for keyboard navigation and focus management.
117
145
  */
118
146
  useEffect(() => {
119
147
  if (!tableRef || !enabled) {
120
148
  return;
121
149
  }
122
150
 
123
- observerRef.current = new MutationObserver(() => {
124
- gridCacheRef.current.dirty = true;
125
- if (activeCellRef.current && !activeCellRef.current.isConnected) {
126
- setActiveCell(null);
127
- }
128
- });
129
-
130
- observerRef.current.observe(tableRef, {
131
- subtree: true,
132
- childList: true,
133
- attributes: true,
134
- attributeFilter: ["colspan", "rowspan", "hidden", "style"],
135
- });
151
+ tableRef.addEventListener("keydown", handleTableKeyDown);
152
+ tableRef.addEventListener("focusin", handleTableFocusIn);
136
153
 
137
154
  return () => {
138
- if (observerRef.current) {
139
- observerRef.current.disconnect();
140
- observerRef.current = null;
141
- }
142
- };
143
- }, [tableRef, enabled]);
144
-
145
- useEffect(() => {
146
- if (!tableRef || !enabled) {
147
- return;
148
- }
149
-
150
- tableRef.addEventListener("keydown", onKeyDown);
151
- tableRef.addEventListener("focusin", onFocusIn);
152
-
153
- return () => {
154
- tableRef.removeEventListener("keydown", onKeyDown);
155
- tableRef.removeEventListener("focusin", onFocusIn);
155
+ tableRef.removeEventListener("keydown", handleTableKeyDown);
156
+ tableRef.removeEventListener("focusin", handleTableFocusIn);
156
157
  };
157
- }, [tableRef, onKeyDown, onFocusIn, enabled]);
158
-
159
- /*
160
- * If keyboard-nav is re-enabled, we need to make sure to update the grid cache,
161
- * since the table might have changed while it was disabled.
162
- */
163
- useEffect(() => {
164
- if (!enabled) {
165
- return;
166
- }
167
-
168
- gridCacheRef.current.dirty = true;
169
- }, [enabled]);
158
+ }, [tableRef, handleTableKeyDown, handleTableFocusIn, enabled]);
170
159
 
171
160
  return {
172
161
  /* Table should only have tabIndex until the focus is moved inside and is enabled */
173
162
  tableTabIndex: enabled ? (activeCell ? undefined : 0) : undefined,
174
- /*
175
- * Allows us to capture focus on the table when navigating with Tab from outside, and move it to the first cell.
176
- * We only want to do this if no cell is already focused.
177
- */
178
- onFocus: () => {
179
- if (!tableRef) {
180
- return;
181
- }
182
-
183
- const focusedElement = document.activeElement;
184
- const cellInTable = focusedElement?.closest("td, th");
185
-
186
- /* Assume onFocusIn handler has updates cell */
187
- if (cellInTable && tableRef.contains(cellInTable)) {
188
- return;
189
- }
190
-
191
- const firstCell = getFirstCell(tableRef);
192
- return firstCell ? focusCell(firstCell) : null;
193
- },
194
163
  };
195
164
  }
196
165
 
197
166
  export { useTableKeyboardNav };
167
+ export type { UseTableKeyboardNavOptions };
@@ -7,7 +7,11 @@ import { DataTableThActions } from "./DataTableThActions";
7
7
  import { DataTableThSortHandle } from "./DataTableThSortHandle";
8
8
 
9
9
  interface DataTableThProps extends React.HTMLAttributes<HTMLTableCellElement> {
10
- resizeHandler?: React.MouseEventHandler<HTMLButtonElement>;
10
+ resizeHandler?: (
11
+ event:
12
+ | React.MouseEvent<HTMLButtonElement>
13
+ | React.TouchEvent<HTMLButtonElement>,
14
+ ) => void;
11
15
  size?: number; // TODO: size should be required when resizeHandler is set
12
16
  sortDirection?: "asc" | "desc" | "none" | false;
13
17
  onSortChange?: (direction: "asc" | "desc" | "none", event: Event) => void;
@@ -98,10 +102,10 @@ const DataTableTh = forwardRef<HTMLTableCellElement, DataTableThProps>(
98
102
 
99
103
  {resizeHandler && (
100
104
  <button
105
+ // TODO: Should probably not be a button since it doesn't have onClick
101
106
  onMouseDown={resizeHandler}
102
- onMouseUp={resizeHandler}
107
+ onTouchStart={resizeHandler}
103
108
  className="aksel-data-table__th-resize-handle"
104
- data-color="neutral"
105
109
  />
106
110
  )}
107
111
  </th>
@@ -1,15 +1,19 @@
1
1
  import React, { forwardRef } from "react";
2
2
  import { cl } from "../../../utils/helpers";
3
3
 
4
- type DataTableTrProps = React.HTMLAttributes<HTMLTableRowElement>;
4
+ type DataTableTrProps = React.HTMLAttributes<HTMLTableRowElement> & {
5
+ selected?: boolean;
6
+ };
5
7
 
6
8
  const DataTableTr = forwardRef<HTMLTableRowElement, DataTableTrProps>(
7
- ({ className, ...rest }, forwardedRef) => {
9
+ ({ className, selected = false, ...rest }, forwardedRef) => {
8
10
  return (
9
11
  <tr
10
12
  {...rest}
11
13
  ref={forwardedRef}
12
- className={cl("aksel-data-table__tr", className)}
14
+ className={cl("aksel-data-table__tr", className, {
15
+ "aksel-data-table__tr--selected": selected,
16
+ })}
13
17
  />
14
18
  );
15
19
  },
@@ -33,6 +33,19 @@ interface LinkCardProps extends HTMLAttributes<HTMLDivElement> {
33
33
  * @see [📝 Documentation](https://aksel.nav.no/grunnleggende/styling/farger-tokens)
34
34
  */
35
35
  "data-color"?: AkselColor;
36
+ /**
37
+ * Changes the HTML element used for the root element.
38
+ *
39
+ * **When using `section`, provide either `aria-label` or `aria-labelledby` for better accessibility.**
40
+ * `axe-core` might warn about unique landmarks if you have multiple Accordions on page with the same label.
41
+ * In those cases consider updating to unique `aria-label` or `aria-labelledby` props.
42
+ * @see [📝 Landmarks unique](https://dequeuniversity.com/rules/axe/4.6/landmark-unique)
43
+ *
44
+ *
45
+ * **When using `article`, make sure `<LinkCard.Title />` is a heading and not a `span`.**
46
+ * @default "div"
47
+ */
48
+ as?: "div" | "section" | "article";
36
49
  }
37
50
 
38
51
  type LinkCardContextProps = {
@@ -106,6 +119,7 @@ export const LinkCard = forwardRef<HTMLDivElement, LinkCardProps>(
106
119
  arrow = true,
107
120
  arrowPosition = "baseline",
108
121
  size = "medium",
122
+ as: Component = "div",
109
123
  ...restProps
110
124
  }: LinkCardProps,
111
125
  forwardedRef,
@@ -114,7 +128,7 @@ export const LinkCard = forwardRef<HTMLDivElement, LinkCardProps>(
114
128
  <LinkCardContextProvider size={size}>
115
129
  <LinkAnchorOverlay asChild>
116
130
  <BodyLong
117
- as="div"
131
+ as={Component}
118
132
  size={size}
119
133
  ref={forwardedRef}
120
134
  data-color="neutral"
@@ -15,7 +15,7 @@ interface ProcessProps extends React.HTMLAttributes<HTMLOListElement> {
15
15
  /**
16
16
  * `<Process.Event />` elements.
17
17
  */
18
- children: React.ReactElement<typeof ProcessEvent>[];
18
+ children: React.ReactNode;
19
19
  /**
20
20
  * Hides the "aktiv"-text when the event is active.
21
21
  * @default false
@@ -7,139 +7,218 @@ interface TranslationMap {
7
7
  export default {
8
8
  global: {
9
9
  dateLocale: nb,
10
+ /** @default "Vis mer" */
10
11
  showMore: "Vis mer",
12
+ /** @default "Vis mindre" */
11
13
  showLess: "Vis mindre",
14
+ /** @default "Skrivebeskyttet" */
12
15
  readOnly: "Skrivebeskyttet",
16
+ /** @default "Lukk" */
13
17
  close: "Lukk",
18
+ /** @default "Feil" */
14
19
  error: "Feil",
20
+ /** @default "Informasjon" */
15
21
  info: "Informasjon",
22
+ /** @default "Suksess" */
16
23
  success: "Suksess",
24
+ /** @default "Advarsel" */
17
25
  warning: "Advarsel",
26
+ /** @default "Kunngjøring" */
18
27
  announcement: "Kunngjøring",
19
28
  },
20
29
  Chips: {
21
30
  Removable: {
22
- /** Will be appended to the accessible name for the button. */
31
+ /** Will be appended to the accessible name for the button.
32
+ * @default "slett" */
23
33
  labelSuffix: "slett",
24
34
  },
25
35
  },
26
36
  Combobox: {
27
- /** The input value will be appended to the end of this text, e.g. `Legg til "input value"`. */
37
+ /** The input value will be appended to the end of this text, e.g. `Legg til "input value"`.
38
+ * @default "Legg til" */
28
39
  addOption: "Legg til",
40
+ /** @default "Ingen søketreff" */
29
41
  noMatches: "Ingen søketreff",
30
- /** Loader title */
42
+ /** Loader title
43
+ * @default "Søker…" */
31
44
  loading: "Søker…",
45
+ /** @default "{selected} av maks {limit} er valgt." */
32
46
  maxSelected: "{selected} av maks {limit} er valgt.",
33
47
  },
34
48
  CopyButton: {
49
+ /** @default "Kopier" */
35
50
  title: "Kopier",
51
+ /** @default "Kopiert!" */
36
52
  activeText: "Kopiert!",
37
53
  },
38
54
  DatePicker: {
55
+ /** @default "Velg dato" */
39
56
  chooseDate: "Velg dato",
57
+ /** @default "Velg datoer" */
40
58
  chooseDates: "Velg datoer",
59
+ /** @default "Velg start- og sluttdato" */
41
60
  chooseDateRange: "Velg start- og sluttdato",
61
+ /** @default "Velg måned" */
42
62
  chooseMonth: "Velg måned",
63
+ /** @default "Uke" */
43
64
  week: "Uke",
65
+ /** @default "Uke {week}" */
44
66
  weekNumber: "Uke {week}",
67
+ /** @default "Velg uke {week}" */
45
68
  selectWeekNumber: "Velg uke {week}",
69
+ /** @default "Måned" */
46
70
  month: "Måned",
71
+ /** @default "Gå til neste måned" */
47
72
  goToNextMonth: "Gå til neste måned",
73
+ /** @default "Gå til forrige måned" */
48
74
  goToPreviousMonth: "Gå til forrige måned",
75
+ /** @default "År" */
49
76
  year: "År",
77
+ /** @default "Gå til neste år" */
50
78
  goToNextYear: "Gå til neste år",
79
+ /** @default "Gå til forrige år" */
51
80
  goToPreviousYear: "Gå til forrige år",
81
+ /** @default "Åpne datovelger" */
52
82
  openDatePicker: "Åpne datovelger",
83
+ /** @default "Åpne månedsvelger" */
53
84
  openMonthPicker: "Åpne månedsvelger",
85
+ /** @default "Lukk datovelger" */
54
86
  closeDatePicker: "Lukk datovelger",
87
+ /** @default "Lukk månedsvelger" */
55
88
  closeMonthPicker: "Lukk månedsvelger",
56
89
  },
57
90
  ErrorSummary: {
91
+ /** @default "Du må rette disse feilene før du kan fortsette:" */
58
92
  heading: "Du må rette disse feilene før du kan fortsette:",
59
93
  },
60
94
  FileUpload: {
61
95
  dropzone: {
96
+ /** @default "Velg fil" */
62
97
  button: "Velg fil",
98
+ /** @default "Velg filer" */
63
99
  buttonMultiple: "Velg filer",
100
+ /** @default "Dra og slipp filen her" */
64
101
  dragAndDrop: "Dra og slipp filen her",
102
+ /** @default "Dra og slipp filer her" */
65
103
  dragAndDropMultiple: "Dra og slipp filer her",
104
+ /** @default "Slipp" */
66
105
  drop: "Slipp",
106
+ /** @default "eller" */
67
107
  or: "eller",
108
+ /** @default "Filopplasting er deaktivert" */
68
109
  disabled: "Filopplasting er deaktivert",
110
+ /** @default "Du kan ikke laste opp flere filer" */
69
111
  disabledFilelimit: "Du kan ikke laste opp flere filer",
70
112
  },
71
113
  item: {
114
+ /** @default "Prøv å laste opp filen på nytt" */
72
115
  retryButtonTitle: "Prøv å laste opp filen på nytt",
116
+ /** @default "Slett filen" */
73
117
  deleteButtonTitle: "Slett filen",
118
+ /** @default "Laster opp…" */
74
119
  uploading: "Laster opp…",
120
+ /** @default "Laster ned…" */
75
121
  downloading: "Laster ned…",
76
122
  },
77
123
  },
78
124
  FormProgress: {
125
+ /** @default "Steg {activeStep} av {totalSteps}" */
79
126
  step: "Steg {activeStep} av {totalSteps}",
127
+ /** @default "Vis alle steg" */
80
128
  showAllSteps: "Vis alle steg",
129
+ /** @default "Skjul alle steg" */
81
130
  hideAllSteps: "Skjul alle steg",
82
131
  },
83
132
  FormSummary: {
133
+ /** @default "Endre svar" */
84
134
  editAnswer: "Endre svar",
85
135
  },
86
136
  GuidePanel: {
137
+ /** @default "Illustrasjon av veileder" */
87
138
  illustrationLabel: "Illustrasjon av veileder",
88
139
  },
89
140
  HelpText: {
141
+ /** @default "Mer informasjon" */
90
142
  title: "Mer informasjon",
91
143
  },
92
144
  Loader: {
145
+ /** @default "Venter…" */
93
146
  title: "Venter…",
94
147
  },
95
148
  Pagination: {
149
+ /** @default "Forrige" */
96
150
  previous: "Forrige",
151
+ /** @default "Neste" */
97
152
  next: "Neste",
98
153
  },
99
154
  Process: {
155
+ /** @default "Aktiv" */
100
156
  active: "Aktiv",
101
157
  },
102
158
  ProgressBar: {
159
+ /** @default "{current} av {max}" */
103
160
  progress: "{current} av {max}",
161
+ /** @default "Fremdrift kan ikke beregnes, antatt tid er {seconds} sekunder." */
104
162
  progressUnknown:
105
163
  "Fremdrift kan ikke beregnes, antatt tid er {seconds} sekunder.",
106
164
  },
107
165
  Search: {
166
+ /** @default "Tøm feltet" */
108
167
  clear: "Tøm feltet",
168
+ /** @default "Søk" */
109
169
  search: "Søk",
110
170
  },
111
171
  Textarea: {
112
- /** Screen readers only */
172
+ /** Screen readers only
173
+ * @default "Tekstområde med plass til {maxLength} tegn." */
113
174
  maxLength: "Tekstområde med plass til {maxLength} tegn.",
175
+ /** @default "{chars} tegn for mye" */
114
176
  charsTooMany: "{chars} tegn for mye",
177
+ /** @default "{chars} tegn igjen" */
115
178
  charsLeft: "{chars} tegn igjen",
116
179
  },
117
180
  Timeline: {
181
+ /** @default "dd.MM.yyyy" */
118
182
  dateFormat: "dd.MM.yyyy",
183
+ /** @default "dd.MM" */
119
184
  dayFormat: "dd.MM",
185
+ /** @default "MMM yy" */
120
186
  monthFormat: "MMM yy",
187
+ /** @default "yyyy" */
121
188
  yearFormat: "yyyy",
122
189
  Row: {
190
+ /** @default "Ingen perioder" */
123
191
  noPeriods: "Ingen perioder",
192
+ /** @default "{start} til {end}" */
124
193
  period: "{start} til {end}",
125
194
  },
126
195
  Period: {
196
+ /** @default "Suksess" */
127
197
  success: "Suksess",
198
+ /** @default "Advarsel" */
128
199
  warning: "Advarsel",
200
+ /** @default "Fare" */
129
201
  danger: "Fare",
202
+ /** @default "Info" */
130
203
  info: "Info",
204
+ /** @default "Nøytral" */
131
205
  neutral: "Nøytral",
206
+ /** @default "{status} fra {start} til {end}" */
132
207
  period: "{status} fra {start} til {end}",
133
208
  },
134
209
  Pin: {
210
+ /** @default "Pin: {date}" */
135
211
  pin: "Pin: {date}",
136
212
  },
137
213
  Zoom: {
214
+ /** @default "Zoom tidslinjen {start} til {end}" */
138
215
  zoom: "Zoom tidslinjen {start} til {end}",
216
+ /** @default "Tilbakestill tidsperspektiv" */
139
217
  reset: "Tilbakestill tidsperspektiv",
140
218
  },
141
219
  },
142
220
  Tooltip: {
221
+ /** @default "eller" */
143
222
  shortcutSeparator: "eller",
144
223
  },
145
224
  } satisfies TranslationMap;