@navikt/ds-react 8.4.1 → 8.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) 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 +40 -10
  11. package/cjs/data/table/helpers/table-grid-nav.js +102 -25
  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 +25 -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 +14 -4
  20. package/cjs/data/table/root/DataTableRoot.js +4 -6
  21. package/cjs/data/table/root/DataTableRoot.js.map +1 -1
  22. package/cjs/data/table/root/useTableKeyboardNav.d.ts +10 -4
  23. package/cjs/data/table/root/useTableKeyboardNav.js +70 -99
  24. package/cjs/data/table/root/useTableKeyboardNav.js.map +1 -1
  25. package/cjs/data/token-filter/AutoSuggest.d.ts +21 -0
  26. package/cjs/data/token-filter/AutoSuggest.js +129 -0
  27. package/cjs/data/token-filter/AutoSuggest.js.map +1 -0
  28. package/cjs/data/token-filter/TokenFilter.d.ts +11 -0
  29. package/cjs/data/token-filter/TokenFilter.js +91 -0
  30. package/cjs/data/token-filter/TokenFilter.js.map +1 -0
  31. package/cjs/data/token-filter/TokenFilter.types.d.ts +46 -0
  32. package/cjs/data/token-filter/TokenFilter.types.js +3 -0
  33. package/cjs/data/token-filter/TokenFilter.types.js.map +1 -0
  34. package/cjs/data/token-filter/helpers/generate-autocomplete-options.d.ts +70 -0
  35. package/cjs/data/token-filter/helpers/generate-autocomplete-options.js +171 -0
  36. package/cjs/data/token-filter/helpers/generate-autocomplete-options.js.map +1 -0
  37. package/cjs/data/token-filter/helpers/parse-query-text.d.ts +31 -0
  38. package/cjs/data/token-filter/helpers/parse-query-text.js +91 -0
  39. package/cjs/data/token-filter/helpers/parse-query-text.js.map +1 -0
  40. package/cjs/link-card/LinkCard.d.ts +13 -0
  41. package/cjs/link-card/LinkCard.js +2 -2
  42. package/cjs/link-card/LinkCard.js.map +1 -1
  43. package/cjs/process/Process.d.ts +1 -1
  44. package/cjs/tooltip/Tooltip.js +1 -1
  45. package/cjs/tooltip/Tooltip.js.map +1 -1
  46. package/esm/accordion/Accordion.d.ts +10 -0
  47. package/esm/accordion/Accordion.js +2 -2
  48. package/esm/accordion/Accordion.js.map +1 -1
  49. package/esm/data/table/helpers/table-cell.d.ts +2 -2
  50. package/esm/data/table/helpers/table-cell.js +2 -5
  51. package/esm/data/table/helpers/table-cell.js.map +1 -1
  52. package/esm/data/table/helpers/table-focus.d.ts +26 -2
  53. package/esm/data/table/helpers/table-focus.js +55 -9
  54. package/esm/data/table/helpers/table-focus.js.map +1 -1
  55. package/esm/data/table/helpers/table-grid-nav.d.ts +40 -10
  56. package/esm/data/table/helpers/table-grid-nav.js +96 -24
  57. package/esm/data/table/helpers/table-grid-nav.js.map +1 -1
  58. package/esm/data/table/helpers/table-keyboard.d.ts +24 -3
  59. package/esm/data/table/helpers/table-keyboard.js +24 -4
  60. package/esm/data/table/helpers/table-keyboard.js.map +1 -1
  61. package/esm/data/table/hooks/useGridCache.d.ts +17 -0
  62. package/esm/data/table/hooks/useGridCache.js +63 -0
  63. package/esm/data/table/hooks/useGridCache.js.map +1 -0
  64. package/esm/data/table/root/DataTableRoot.d.ts +14 -4
  65. package/esm/data/table/root/DataTableRoot.js +4 -6
  66. package/esm/data/table/root/DataTableRoot.js.map +1 -1
  67. package/esm/data/table/root/useTableKeyboardNav.d.ts +10 -4
  68. package/esm/data/table/root/useTableKeyboardNav.js +75 -104
  69. package/esm/data/table/root/useTableKeyboardNav.js.map +1 -1
  70. package/esm/data/token-filter/AutoSuggest.d.ts +21 -0
  71. package/esm/data/token-filter/AutoSuggest.js +93 -0
  72. package/esm/data/token-filter/AutoSuggest.js.map +1 -0
  73. package/esm/data/token-filter/TokenFilter.d.ts +11 -0
  74. package/esm/data/token-filter/TokenFilter.js +55 -0
  75. package/esm/data/token-filter/TokenFilter.js.map +1 -0
  76. package/esm/data/token-filter/TokenFilter.types.d.ts +46 -0
  77. package/esm/data/token-filter/TokenFilter.types.js +2 -0
  78. package/esm/data/token-filter/TokenFilter.types.js.map +1 -0
  79. package/esm/data/token-filter/helpers/generate-autocomplete-options.d.ts +70 -0
  80. package/esm/data/token-filter/helpers/generate-autocomplete-options.js +169 -0
  81. package/esm/data/token-filter/helpers/generate-autocomplete-options.js.map +1 -0
  82. package/esm/data/token-filter/helpers/parse-query-text.d.ts +31 -0
  83. package/esm/data/token-filter/helpers/parse-query-text.js +87 -0
  84. package/esm/data/token-filter/helpers/parse-query-text.js.map +1 -0
  85. package/esm/link-card/LinkCard.d.ts +13 -0
  86. package/esm/link-card/LinkCard.js +2 -2
  87. package/esm/link-card/LinkCard.js.map +1 -1
  88. package/esm/process/Process.d.ts +1 -1
  89. package/esm/tooltip/Tooltip.js +2 -2
  90. package/esm/tooltip/Tooltip.js.map +1 -1
  91. package/package.json +3 -3
  92. package/src/accordion/Accordion.tsx +19 -2
  93. package/src/data/table/helpers/table-cell.ts +2 -7
  94. package/src/data/table/helpers/table-focus.ts +70 -9
  95. package/src/data/table/helpers/table-grid-nav.test.ts +659 -0
  96. package/src/data/table/helpers/table-grid-nav.ts +128 -32
  97. package/src/data/table/helpers/table-keyboard.test.ts +27 -27
  98. package/src/data/table/helpers/table-keyboard.ts +34 -4
  99. package/src/data/table/hooks/useGridCache.ts +73 -0
  100. package/src/data/table/root/DataTableRoot.tsx +21 -11
  101. package/src/data/table/root/useTableKeyboardNav.ts +110 -128
  102. package/src/data/token-filter/AutoSuggest.tsx +179 -0
  103. package/src/data/token-filter/TokenFilter.tsx +124 -0
  104. package/src/data/token-filter/TokenFilter.types.ts +79 -0
  105. package/src/data/token-filter/helpers/generate-autocomplete-options.ts +244 -0
  106. package/src/data/token-filter/helpers/parse-query-text.test.ts +410 -0
  107. package/src/data/token-filter/helpers/parse-query-text.ts +148 -0
  108. package/src/link-card/LinkCard.tsx +15 -1
  109. package/src/process/Process.tsx +1 -1
  110. package/src/tooltip/Tooltip.tsx +3 -3
@@ -1,3 +1,29 @@
1
+ /**
2
+ * WeakMap to store original tabIndex values for cells.
3
+ * Used to restore tabIndex when navigation moves away from a cell.
4
+ */
5
+ const originalTabIndexMap = new WeakMap<Element, number>();
6
+
7
+ /**
8
+ * Stores the original tabIndex of a cell if not already stored, and returns it.
9
+ */
10
+ function syncOriginalTabIndex(cell: Element): void {
11
+ if (!originalTabIndexMap.has(cell)) {
12
+ const current = (cell as HTMLElement).tabIndex;
13
+ originalTabIndexMap.set(cell, current);
14
+ }
15
+ }
16
+
17
+ /**
18
+ * Restores the original tabIndex for a cell.
19
+ */
20
+ function restoreTabIndex(cell: Element): void {
21
+ const original = originalTabIndexMap.get(cell);
22
+ if (original !== undefined) {
23
+ (cell as HTMLElement).tabIndex = original;
24
+ }
25
+ }
26
+
1
27
  /**
2
28
  * Makes sure only focusable and non-disabled elements are targeted when navigating through the table using keyboard interactions.
3
29
  * Tries to find the most logical focus target inside a cell, by looking for commonly used interactive elements,
@@ -6,7 +32,7 @@
6
32
  * If the assumed focus target is not the cell itself, we check if that element is hidden or disabled, and fall back to the cell if so,
7
33
  * since we want to avoid/can't focus hidden/disabled elements.
8
34
  */
9
- function getFocusableTarget(cell: Element): HTMLElement | null {
35
+ function findFocusableElementInCell(cell: Element): HTMLElement | null {
10
36
  const el = cell as HTMLElement | null;
11
37
  if (!el || isHiddenElement(el)) {
12
38
  return null;
@@ -31,8 +57,7 @@ function getFocusableTarget(cell: Element): HTMLElement | null {
31
57
  }
32
58
 
33
59
  /**
34
- * TODO:
35
- * - validate this implementation against SR-only elements
60
+ * Checks if an element is visually hidden (but not SR-only).
36
61
  */
37
62
  function isHiddenElement(el: HTMLElement): boolean {
38
63
  if (el.hidden) {
@@ -43,6 +68,9 @@ function isHiddenElement(el: HTMLElement): boolean {
43
68
  return style.display === "none" || style.visibility === "hidden";
44
69
  }
45
70
 
71
+ /**
72
+ * Checks if an element is disabled (via aria-disabled, fieldset, or native disabled property).
73
+ */
46
74
  function isDisabledElement(el: HTMLElement): boolean {
47
75
  if (el.getAttribute("aria-disabled") === "true") {
48
76
  return true;
@@ -64,8 +92,12 @@ function isDisabledElement(el: HTMLElement): boolean {
64
92
  return false;
65
93
  }
66
94
 
67
- function focusCell(cell: Element): Element | null {
68
- const focusTarget = getFocusableTarget(cell);
95
+ /**
96
+ * Determines the focus target and updates tabIndex if the cell itself should be focused.
97
+ * Returns null if no focusable target found.
98
+ */
99
+ function prepareCellFocus(cell: Element): HTMLElement | null {
100
+ const focusTarget = findFocusableElementInCell(cell);
69
101
  if (!focusTarget) {
70
102
  return null;
71
103
  }
@@ -74,15 +106,34 @@ function focusCell(cell: Element): Element | null {
74
106
  (cell as HTMLElement).tabIndex = 0;
75
107
  }
76
108
 
77
- focusTarget.focus({
109
+ return focusTarget;
110
+ }
111
+
112
+ /**
113
+ * Applies focus and scroll to an element.
114
+ */
115
+ function applyFocusAndScroll(element: HTMLElement): void {
116
+ element.focus({
78
117
  preventScroll: true,
79
118
  });
80
119
 
81
- focusTarget.scrollIntoView({
120
+ element.scrollIntoView({
82
121
  behavior: "smooth",
83
122
  block: "nearest",
84
123
  inline: "nearest",
85
124
  });
125
+ }
126
+
127
+ /**
128
+ * Focuses a cell by finding its focusable target and applying focus with scroll.
129
+ */
130
+ function focusCell(cell: Element): Element | null {
131
+ const focusTarget = prepareCellFocus(cell);
132
+ if (!focusTarget) {
133
+ return null;
134
+ }
135
+
136
+ applyFocusAndScroll(focusTarget);
86
137
  return cell;
87
138
  }
88
139
 
@@ -92,7 +143,8 @@ function focusCellAndUpdateTabIndex(
92
143
  { shouldFocus = true }: { shouldFocus?: boolean } = {},
93
144
  ): Element | null {
94
145
  if (previousCell && previousCell !== nextCell) {
95
- (previousCell as HTMLElement).tabIndex = -1;
146
+ syncOriginalTabIndex(previousCell);
147
+ restoreTabIndex(previousCell);
96
148
  }
97
149
 
98
150
  if (!shouldFocus) {
@@ -102,4 +154,13 @@ function focusCellAndUpdateTabIndex(
102
154
  return focusCell(nextCell);
103
155
  }
104
156
 
105
- export { focusCell, focusCellAndUpdateTabIndex, getFocusableTarget };
157
+ export {
158
+ applyFocusAndScroll,
159
+ focusCell,
160
+ focusCellAndUpdateTabIndex,
161
+ findFocusableElementInCell,
162
+ isDisabledElement,
163
+ isHiddenElement,
164
+ prepareCellFocus,
165
+ restoreTabIndex,
166
+ };