@navikt/ds-react 7.32.2 → 7.32.4

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 (45) hide show
  1. package/cjs/accordion/AccordionHeader.js +1 -1
  2. package/cjs/accordion/AccordionHeader.js.map +1 -1
  3. package/cjs/form/combobox/FilteredOptions/FilteredOptionsItem.js +4 -0
  4. package/cjs/form/combobox/FilteredOptions/FilteredOptionsItem.js.map +1 -1
  5. package/cjs/form/combobox/Input/ToggleListButton.js +2 -1
  6. package/cjs/form/combobox/Input/ToggleListButton.js.map +1 -1
  7. package/cjs/form/switch/Switch.js +3 -3
  8. package/cjs/form/switch/Switch.js.map +1 -1
  9. package/cjs/popover/Popover.js +1 -1
  10. package/cjs/popover/Popover.js.map +1 -1
  11. package/cjs/util/hideNonTargetElements.d.ts +8 -0
  12. package/cjs/util/hideNonTargetElements.js +141 -0
  13. package/cjs/util/hideNonTargetElements.js.map +1 -0
  14. package/cjs/util/hooks/descendants/useDescendant.js +3 -0
  15. package/cjs/util/hooks/descendants/useDescendant.js.map +1 -1
  16. package/cjs/util/hooks/useLatestRef.js +1 -0
  17. package/cjs/util/hooks/useLatestRef.js.map +1 -1
  18. package/esm/accordion/AccordionHeader.js +1 -1
  19. package/esm/accordion/AccordionHeader.js.map +1 -1
  20. package/esm/form/combobox/FilteredOptions/FilteredOptionsItem.js +4 -0
  21. package/esm/form/combobox/FilteredOptions/FilteredOptionsItem.js.map +1 -1
  22. package/esm/form/combobox/Input/ToggleListButton.js +2 -1
  23. package/esm/form/combobox/Input/ToggleListButton.js.map +1 -1
  24. package/esm/form/switch/Switch.js +3 -3
  25. package/esm/form/switch/Switch.js.map +1 -1
  26. package/esm/popover/Popover.js +1 -1
  27. package/esm/popover/Popover.js.map +1 -1
  28. package/esm/util/hideNonTargetElements.d.ts +8 -0
  29. package/esm/util/hideNonTargetElements.js +139 -0
  30. package/esm/util/hideNonTargetElements.js.map +1 -0
  31. package/esm/util/hooks/descendants/useDescendant.js +3 -0
  32. package/esm/util/hooks/descendants/useDescendant.js.map +1 -1
  33. package/esm/util/hooks/useLatestRef.js +1 -0
  34. package/esm/util/hooks/useLatestRef.js.map +1 -1
  35. package/package.json +4 -4
  36. package/src/accordion/AccordionHeader.tsx +1 -1
  37. package/src/form/combobox/FilteredOptions/FilteredOptionsItem.tsx +4 -0
  38. package/src/form/combobox/Input/ToggleListButton.tsx +2 -1
  39. package/src/form/combobox/__tests__/combobox.test.tsx +45 -106
  40. package/src/form/switch/Switch.tsx +4 -4
  41. package/src/popover/Popover.tsx +1 -1
  42. package/src/util/__tests__/hideNonTargetElements.test.ts +147 -0
  43. package/src/util/hideNonTargetElements.ts +179 -0
  44. package/src/util/hooks/descendants/useDescendant.tsx +3 -0
  45. package/src/util/hooks/useLatestRef.ts +1 -0
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Modified version of `aria-hidden`-package.
3
+ * - Removed "inert"-functionality.
4
+ * - Removed flexibility for different data-attributes.
5
+ * https://github.com/theKashey/aria-hidden/blob/720e8a8e1cfa047bd299a929d95d47ac860a5c1a/src/index.ts
6
+ */
7
+ import { ownerDocument } from "./owner.js";
8
+ let ariaHiddenCounter = new WeakMap();
9
+ let markerCounter = new WeakMap();
10
+ let uncontrolledElementsSet = new WeakSet();
11
+ let lockCount = 0;
12
+ const controlAttribute = "aria-hidden";
13
+ const markerName = "data-aksel-hidden";
14
+ /**
15
+ * Unwraps a Shadow DOM host to find the actual Element in the light DOM.
16
+ */
17
+ function unwrapHost(node) {
18
+ return (node &&
19
+ (node.host || unwrapHost(node.parentNode)));
20
+ }
21
+ /**
22
+ * Corrects the target elements by unwrapping Shadow DOM hosts if necessary.
23
+ *
24
+ * @param parent - The parent HTMLElement to check containment against.
25
+ * @param targets - An array of target Elements to correct.
26
+ * @returns An array of corrected Elements that are contained within the parent.
27
+ */
28
+ function correctElements(parent, targets) {
29
+ return targets
30
+ .map((target) => {
31
+ if (parent.contains(target)) {
32
+ return target;
33
+ }
34
+ const correctedTarget = unwrapHost(target);
35
+ if (parent.contains(correctedTarget)) {
36
+ return correctedTarget;
37
+ }
38
+ return null;
39
+ })
40
+ .filter((x) => x !== null);
41
+ }
42
+ /**
43
+ * Applies the aria-hidden attribute to all elements in the body except the specified avoid elements.
44
+ */
45
+ function applyAttributeToOthers(uncorrectedAvoidElements, body) {
46
+ const avoidElements = correctElements(body, uncorrectedAvoidElements);
47
+ const elementsToAvoidWithParents = new Set();
48
+ const elementsToAvoidUpdating = new Set(avoidElements);
49
+ const hiddenElements = [];
50
+ avoidElements.forEach(addToAvoidList);
51
+ applyAttributes(body);
52
+ elementsToAvoidWithParents.clear();
53
+ function addToAvoidList(el) {
54
+ if (!el || elementsToAvoidWithParents.has(el)) {
55
+ return;
56
+ }
57
+ elementsToAvoidWithParents.add(el);
58
+ if (el.parentNode) {
59
+ addToAvoidList(el.parentNode);
60
+ }
61
+ }
62
+ function applyAttributes(parent) {
63
+ if (!parent || elementsToAvoidUpdating.has(parent)) {
64
+ return;
65
+ }
66
+ const parentChildren = parent.children;
67
+ for (let index = 0; index < parentChildren.length; index += 1) {
68
+ const node = parentChildren[index];
69
+ if (elementsToAvoidWithParents.has(node)) {
70
+ applyAttributes(node);
71
+ }
72
+ else {
73
+ const attr = node.getAttribute(controlAttribute);
74
+ /*
75
+ * We only check for falsy values here since since arbitrary values
76
+ * (e.g. "true", "foo", "") are all valid for indicating that the element is already hidden.
77
+ */
78
+ const alreadyHidden = attr !== null && attr !== "false";
79
+ const counterValue = (ariaHiddenCounter.get(node) || 0) + 1;
80
+ const markerValue = (markerCounter.get(node) || 0) + 1;
81
+ ariaHiddenCounter.set(node, counterValue);
82
+ markerCounter.set(node, markerValue);
83
+ hiddenElements.push(node);
84
+ if (counterValue === 1 && alreadyHidden) {
85
+ uncontrolledElementsSet.add(node);
86
+ }
87
+ if (markerValue === 1) {
88
+ node.setAttribute(markerName, "");
89
+ }
90
+ if (!alreadyHidden) {
91
+ node.setAttribute(controlAttribute, "true");
92
+ }
93
+ }
94
+ }
95
+ }
96
+ lockCount += 1;
97
+ /* Cleanup */
98
+ return () => {
99
+ for (const element of hiddenElements) {
100
+ const currentCounterValue = ariaHiddenCounter.get(element) || 0;
101
+ const counterValue = currentCounterValue - 1;
102
+ const markerValue = (markerCounter.get(element) || 0) - 1;
103
+ ariaHiddenCounter.set(element, counterValue);
104
+ markerCounter.set(element, markerValue);
105
+ if (!counterValue) {
106
+ if (!uncontrolledElementsSet.has(element)) {
107
+ element.removeAttribute(controlAttribute);
108
+ }
109
+ uncontrolledElementsSet.delete(element);
110
+ }
111
+ if (!markerValue) {
112
+ element.removeAttribute(markerName);
113
+ }
114
+ }
115
+ lockCount -= 1;
116
+ /* Reset */
117
+ if (!lockCount) {
118
+ ariaHiddenCounter = new WeakMap();
119
+ uncontrolledElementsSet = new WeakSet();
120
+ markerCounter = new WeakMap();
121
+ }
122
+ };
123
+ }
124
+ /**
125
+ * Hides all elements in the document body for assertive technologies except the specified elements with `aria-hidden`.
126
+ * @param avoidElements - An array of elements to avoid hiding.
127
+ * @returns A function that, when called, will undo the hiding of elements.
128
+ */
129
+ function hideNonTargetElements(avoidElements) {
130
+ const body = ownerDocument(avoidElements[0]).body;
131
+ /**
132
+ * Assume that elements with `aria-live` or `script` tags should not be hidden.
133
+ * This ensures that live regions and scripts continue to function properly.
134
+ */
135
+ const ingoredElements = Array.from(body.querySelectorAll("[aria-live], script"));
136
+ return applyAttributeToOthers(avoidElements.concat(ingoredElements), body);
137
+ }
138
+ export { hideNonTargetElements };
139
+ //# sourceMappingURL=hideNonTargetElements.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hideNonTargetElements.js","sourceRoot":"","sources":["../../src/util/hideNonTargetElements.ts"],"names":[],"mappings":"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"}
@@ -31,9 +31,12 @@ export function createDescendantContext() {
31
31
  return () => {
32
32
  if (!ref.current)
33
33
  return;
34
+ // eslint-disable-next-line react-hooks/exhaustive-deps
34
35
  descendants.unregister(ref.current);
35
36
  };
37
+ // eslint-disable-next-line react-hooks/exhaustive-deps
36
38
  }, []);
39
+ // eslint-disable-next-line react-hooks/exhaustive-deps
37
40
  useClientLayoutEffect(() => {
38
41
  if (!ref.current)
39
42
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"useDescendant.js","sourceRoot":"","sources":["../../../../src/util/hooks/descendants/useDescendant.tsx"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAqB,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B;;GAEG;AACH,MAAM,UAAU,uBAAuB;IAIrC,MAAM,CAAC,0BAA0B,EAAE,qBAAqB,CAAC,GAAG,aAAa,CAEvE;QACA,IAAI,EAAE,qBAAqB;QAC3B,YAAY,EACV,+DAA+D;KAClE,CAAC,CAAC;IAEH,MAAM,eAAe,GAAG,IAAI,CAC1B,CAAC,KAAK,EAAE,EAAE,CAAC,CACT,oBAAC,0BAA0B,oBAAK,KAAK,CAAC,KAAK,GACxC,KAAK,CAAC,QAAQ,CACY,CAC9B,CACF,CAAC;IAEF;;;;;;OAMG;IACH,SAAS,aAAa,CAAC,OAA8B;QACnD,MAAM,WAAW,GAAG,qBAAqB,EAAE,CAAC;QAC5C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,GAAG,GAAG,MAAM,CAAI,IAAI,CAAC,CAAC;QAE5B,qBAAqB,CAAC,GAAG,EAAE;YACzB,OAAO,GAAG,EAAE;gBACV,IAAI,CAAC,GAAG,CAAC,OAAO;oBAAE,OAAO;gBACzB,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACtC,CAAC,CAAC;QACJ,CAAC,EAAE,EAAE,CAAC,CAAC;QAEP,qBAAqB,CAAC,GAAG,EAAE;YACzB,IAAI,CAAC,GAAG,CAAC,OAAO;gBAAE,OAAO;YACzB,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACpD,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;gBACpD,QAAQ,CAAC,SAAS,CAAC,CAAC;YACtB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,WAAW,GAAG,OAAO;YACzB,CAAC,CAAC,IAAI,CAAuB,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC3D,CAAC,CAAC,IAAI,CAAuB,WAAW,CAAC,QAAQ,CAAC,CAAC;QAErD,OAAO;YACL,WAAW;YACX,KAAK;YACL,YAAY,EAAE,WAAW,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC;YACrD,QAAQ,EAAE,SAAS,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;SACxC,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,SAAS,cAAc;QACrB,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,kBAAkB,EAAQ,CAAC,CAAC,OAAO,CAAC;QAEnE,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,OAAO;QACL,mBAAmB;QACnB,eAAe;QACf,+CAA+C;QAC/C,qBAAqB;QACrB,8EAA8E;QAC9E,cAAc;QACd,+BAA+B;QAC/B,aAAa;KACL,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"useDescendant.js","sourceRoot":"","sources":["../../../../src/util/hooks/descendants/useDescendant.tsx"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAqB,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B;;GAEG;AACH,MAAM,UAAU,uBAAuB;IAIrC,MAAM,CAAC,0BAA0B,EAAE,qBAAqB,CAAC,GAAG,aAAa,CAEvE;QACA,IAAI,EAAE,qBAAqB;QAC3B,YAAY,EACV,+DAA+D;KAClE,CAAC,CAAC;IAEH,MAAM,eAAe,GAAG,IAAI,CAC1B,CAAC,KAAK,EAAE,EAAE,CAAC,CACT,oBAAC,0BAA0B,oBAAK,KAAK,CAAC,KAAK,GACxC,KAAK,CAAC,QAAQ,CACY,CAC9B,CACF,CAAC;IAEF;;;;;;OAMG;IACH,SAAS,aAAa,CAAC,OAA8B;QACnD,MAAM,WAAW,GAAG,qBAAqB,EAAE,CAAC;QAC5C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,GAAG,GAAG,MAAM,CAAI,IAAI,CAAC,CAAC;QAE5B,qBAAqB,CAAC,GAAG,EAAE;YACzB,OAAO,GAAG,EAAE;gBACV,IAAI,CAAC,GAAG,CAAC,OAAO;oBAAE,OAAO;gBACzB,uDAAuD;gBACvD,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACtC,CAAC,CAAC;YACF,uDAAuD;QACzD,CAAC,EAAE,EAAE,CAAC,CAAC;QAEP,uDAAuD;QACvD,qBAAqB,CAAC,GAAG,EAAE;YACzB,IAAI,CAAC,GAAG,CAAC,OAAO;gBAAE,OAAO;YACzB,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACpD,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;gBACpD,QAAQ,CAAC,SAAS,CAAC,CAAC;YACtB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,WAAW,GAAG,OAAO;YACzB,CAAC,CAAC,IAAI,CAAuB,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC3D,CAAC,CAAC,IAAI,CAAuB,WAAW,CAAC,QAAQ,CAAC,CAAC;QAErD,OAAO;YACL,WAAW;YACX,KAAK;YACL,YAAY,EAAE,WAAW,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC;YACrD,QAAQ,EAAE,SAAS,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;SACxC,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,SAAS,cAAc;QACrB,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,kBAAkB,EAAQ,CAAC,CAAC,OAAO,CAAC;QAEnE,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,OAAO;QACL,mBAAmB;QACnB,eAAe;QACf,+CAA+C;QAC/C,qBAAqB;QACrB,8EAA8E;QAC9E,cAAc;QACd,+BAA+B;QAC/B,aAAa;KACL,CAAC;AACb,CAAC"}
@@ -4,6 +4,7 @@ import { useRefWithInit } from "./useRefWithInit.js";
4
4
  export function useLatestRef(value) {
5
5
  const latest = useRefWithInit(createLatestRef, value).current;
6
6
  latest.next = value;
7
+ // eslint-disable-next-line react-hooks/exhaustive-deps
7
8
  useClientLayoutEffect(latest.effect);
8
9
  return latest;
9
10
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useLatestRef.js","sourceRoot":"","sources":["../../../src/util/hooks/useLatestRef.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,MAAM,UAAU,YAAY,CAAI,KAAQ;IACtC,MAAM,MAAM,GAAG,cAAc,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC,OAAQ,CAAC;IAE/D,MAAM,CAAC,IAAI,GAAG,KAAK,CAAC;IAEpB,qBAAqB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAErC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,eAAe,CAAI,KAAQ;IAClC,MAAM,MAAM,GAAG;QACb,OAAO,EAAE,KAAK;QACd,IAAI,EAAE,KAAK;QACX,MAAM,EAAE,GAAG,EAAE;YACX,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC;QAC/B,CAAC;KACF,CAAC;IACF,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"useLatestRef.js","sourceRoot":"","sources":["../../../src/util/hooks/useLatestRef.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,MAAM,UAAU,YAAY,CAAI,KAAQ;IACtC,MAAM,MAAM,GAAG,cAAc,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC,OAAQ,CAAC;IAE/D,MAAM,CAAC,IAAI,GAAG,KAAK,CAAC;IAEpB,uDAAuD;IACvD,qBAAqB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAErC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,eAAe,CAAI,KAAQ;IAClC,MAAM,MAAM,GAAG;QACb,OAAO,EAAE,KAAK;QACd,IAAI,EAAE,KAAK;QACX,MAAM,EAAE,GAAG,EAAE;YACX,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC;QAC/B,CAAC;KACF,CAAC;IACF,OAAO,MAAM,CAAC;AAChB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@navikt/ds-react",
3
- "version": "7.32.2",
3
+ "version": "7.32.4",
4
4
  "description": "React components from the Norwegian Labour and Welfare Administration.",
5
5
  "author": "Aksel, a team part of the Norwegian Labour and Welfare Administration.",
6
6
  "license": "MIT",
@@ -643,15 +643,15 @@
643
643
  "clean": "rimraf cjs esm",
644
644
  "build": "yarn i18n-jsdoc && concurrently \"tsc -p tsconfig.build.json\" \"tsc -p tsconfig.esm.json && tsc-alias -p tsconfig.esm.json && yarn write-packagejson\" && yarn i18n-jsdoc --cleanup && yarn copy-types",
645
645
  "watch": "tsc --watch -p tsconfig.esm.json",
646
- "test": "TZ=UTC vitest run -c tests/vitest.config.ts --silent",
646
+ "test": "TZ=UTC vitest run -c tests/vitest.config.ts",
647
647
  "test:watch": "TZ=UTC vitest watch -c tests/vitest.config.ts",
648
648
  "copy-types": "copyfiles -f ./src/types/theme.d.ts ./esm/types"
649
649
  },
650
650
  "dependencies": {
651
651
  "@floating-ui/react": "0.27.8",
652
652
  "@floating-ui/react-dom": "^2.1.6",
653
- "@navikt/aksel-icons": "^7.32.2",
654
- "@navikt/ds-tokens": "^7.32.2",
653
+ "@navikt/aksel-icons": "^7.32.4",
654
+ "@navikt/ds-tokens": "^7.32.4",
655
655
  "clsx": "^2.1.0",
656
656
  "date-fns": "^4.0.0",
657
657
  "react-day-picker": "9.7.0"
@@ -33,7 +33,7 @@ const AccordionHeader = forwardRef<HTMLButtonElement, AccordionHeaderProps>(
33
33
 
34
34
  if (themeContext?.isDarkside) {
35
35
  /* Fallback to "medium" Accordion-size if any other sizes are used */
36
- headingSize = accordionContext?.size === "small" ? "xsmall" : "small";
36
+ headingSize = accordionContext?.size === "large" ? "small" : "xsmall";
37
37
  }
38
38
 
39
39
  return (
@@ -13,6 +13,10 @@ const useTextHighlight = (text: string, searchTerm: string) => {
13
13
  const indexOfHighlightedText = text
14
14
  .toLowerCase()
15
15
  .indexOf(searchTerm.toLowerCase());
16
+ if (indexOfHighlightedText === -1) {
17
+ // This can happen if the consumer has implemented their own filtering logic
18
+ return [text, "", ""];
19
+ }
16
20
  const start = text.substring(0, indexOfHighlightedText);
17
21
  const highlight = text.substring(
18
22
  indexOfHighlightedText,
@@ -12,7 +12,8 @@ export const ToggleListButton = forwardRef<HTMLDivElement>((_, ref) => {
12
12
  return (
13
13
  <div
14
14
  ref={ref}
15
- onClick={() => {
15
+ onClick={(event) => {
16
+ event.stopPropagation();
16
17
  toggleIsListOpen();
17
18
  focusInput();
18
19
  }}
@@ -1,5 +1,4 @@
1
- /* eslint-disable testing-library/no-unnecessary-act -- https://kentcdodds.com/blog/fix-the-not-wrapped-in-act-warning */
2
- import { act, render, screen } from "@testing-library/react";
1
+ import { render, screen } from "@testing-library/react";
3
2
  import userEvent from "@testing-library/user-event";
4
3
  import React from "react";
5
4
  import { describe, expect, test, vi } from "vitest";
@@ -40,34 +39,20 @@ describe("Render combobox", () => {
40
39
  test("Should be able to search, select and remove selections", async () => {
41
40
  render(<App isMultiSelect options={options} />);
42
41
 
43
- await act(async () => {
44
- await userEvent.click(
45
- screen.getByRole("combobox", {
46
- name: "Hva er dine favorittfrukter?",
47
- }),
48
- );
49
- });
50
- await act(async () => {
51
- await userEvent.type(
52
- screen.getByRole("combobox", {
53
- name: "Hva er dine favorittfrukter?",
54
- }),
55
- "apple",
56
- );
57
- });
58
- await act(async () => {
59
- await userEvent.click(
60
- await screen.findByRole("option", { name: "apple" }),
61
- );
42
+ const input = screen.getByRole("combobox", {
43
+ name: "Hva er dine favorittfrukter?",
62
44
  });
45
+ await userEvent.click(input);
46
+ await userEvent.type(input, "apple");
47
+ await userEvent.click(
48
+ await screen.findByRole("option", { name: "apple" }),
49
+ );
63
50
  expect(
64
51
  await screen.findByRole("option", { name: "apple", selected: true }),
65
52
  ).toBeInTheDocument();
66
- await act(async () => {
67
- await userEvent.click(
68
- await screen.findByRole("button", { name: "apple slett" }),
69
- );
70
- });
53
+ await userEvent.click(
54
+ await screen.findByRole("button", { name: "apple slett" }),
55
+ );
71
56
  });
72
57
  });
73
58
 
@@ -81,24 +66,14 @@ describe("Render combobox", () => {
81
66
  test("Should not select previous focused element when closes", async () => {
82
67
  render(<App options={options} />);
83
68
 
84
- await act(async () => {
85
- await userEvent.click(
86
- screen.getByRole("combobox", {
87
- name: "Hva er dine favorittfrukter?",
88
- }),
89
- );
90
- });
91
- await act(async () => {
92
- await userEvent.type(
93
- screen.getByRole("combobox", {
94
- name: "Hva er dine favorittfrukter?",
95
- }),
96
- "ban",
97
- );
98
- await userEvent.keyboard("{ArrowDown}");
99
- await userEvent.keyboard("{ArrowUp}");
100
- await userEvent.keyboard("{Enter}");
69
+ const input = screen.getByRole("combobox", {
70
+ name: "Hva er dine favorittfrukter?",
101
71
  });
72
+ await userEvent.click(input);
73
+ await userEvent.type(input, "ban");
74
+ await userEvent.keyboard("{ArrowDown}");
75
+ await userEvent.keyboard("{ArrowUp}");
76
+ await userEvent.keyboard("{Enter}");
102
77
 
103
78
  expect(screen.queryByRole("button", { name: "banana slett" })).toBeNull();
104
79
  });
@@ -106,24 +81,14 @@ describe("Render combobox", () => {
106
81
  test("Should reset list when resetting input (ESC)", async () => {
107
82
  render(<App options={options} />);
108
83
 
109
- await act(async () => {
110
- await userEvent.click(
111
- screen.getByRole("combobox", {
112
- name: "Hva er dine favorittfrukter?",
113
- }),
114
- );
115
- });
116
- await act(async () => {
117
- await userEvent.type(
118
- screen.getByRole("combobox", {
119
- name: "Hva er dine favorittfrukter?",
120
- }),
121
- "apple",
122
- );
123
- await userEvent.keyboard("{ArrowDown}");
124
- await userEvent.keyboard("{Escape}");
125
- await userEvent.keyboard("{ArrowDown}");
84
+ const input = screen.getByRole("combobox", {
85
+ name: "Hva er dine favorittfrukter?",
126
86
  });
87
+ await userEvent.click(input);
88
+ await userEvent.type(input, "apple");
89
+ await userEvent.keyboard("{ArrowDown}");
90
+ await userEvent.keyboard("{Escape}");
91
+ await userEvent.keyboard("{ArrowDown}");
127
92
 
128
93
  expect(
129
94
  await screen.findByRole("option", { name: "banana" }),
@@ -145,13 +110,11 @@ describe("Render combobox", () => {
145
110
  );
146
111
 
147
112
  expect(screen.getByRole("combobox")).toBeInTheDocument();
148
- const bananaOption = screen.getByRole("option", {
113
+ const option = screen.getByRole("option", {
149
114
  name: "Hjelpemidler [HJE]",
150
115
  selected: false,
151
116
  });
152
- await act(async () => {
153
- await userEvent.click(bananaOption);
154
- });
117
+ await userEvent.click(option);
155
118
  expect(onToggleSelected).toHaveBeenCalledWith("HJE", true, false);
156
119
  expect(
157
120
  screen.getByRole("option", {
@@ -175,10 +138,8 @@ describe("Render combobox", () => {
175
138
  const combobox = screen.getByRole("combobox");
176
139
  expect(combobox).toBeInTheDocument();
177
140
 
178
- await act(async () => {
179
- await userEvent.click(combobox);
180
- await userEvent.type(combobox, "Lemon");
181
- });
141
+ await userEvent.click(combobox);
142
+ await userEvent.type(combobox, "Lemon");
182
143
  expect(onChange).toHaveBeenNthCalledWith(1, "L");
183
144
  expect(onChange).toHaveBeenNthCalledWith(2, "Le");
184
145
  expect(onChange).toHaveBeenNthCalledWith(3, "Lem");
@@ -205,13 +166,11 @@ describe("Render combobox", () => {
205
166
  const combobox = screen.getByRole("combobox");
206
167
  expect(combobox).toBeInTheDocument();
207
168
 
208
- await act(async () => {
209
- await userEvent.click(combobox);
210
- await userEvent.type(combobox, "Syke");
211
- await userEvent.keyboard("{ArrowRight}");
212
- await userEvent.keyboard("{ArrowDown}");
213
- await userEvent.keyboard("{Enter}");
214
- });
169
+ await userEvent.click(combobox);
170
+ await userEvent.type(combobox, "Syke");
171
+ await userEvent.keyboard("{ArrowRight}");
172
+ await userEvent.keyboard("{ArrowDown}");
173
+ await userEvent.keyboard("{Enter}");
215
174
  expect(onChange).toHaveBeenNthCalledWith(1, "S");
216
175
  expect(onChange).toHaveBeenNthCalledWith(2, "Sy");
217
176
  expect(onChange).toHaveBeenNthCalledWith(3, "Syk");
@@ -228,18 +187,14 @@ describe("Render combobox", () => {
228
187
  });
229
188
 
230
189
  describe("search", () => {
231
- test("should find matched anywhere in the label", async () => {
190
+ test("should find matches anywhere in the label", async () => {
232
191
  render(<App options={options} />);
233
192
 
234
193
  const combobox = screen.getByRole("combobox", {
235
194
  name: "Hva er dine favorittfrukter?",
236
195
  });
237
-
238
- await act(async () => {
239
- await userEvent.click(combobox);
240
-
241
- await userEvent.type(combobox, "p");
242
- });
196
+ await userEvent.click(combobox);
197
+ await userEvent.type(combobox, "p");
243
198
 
244
199
  const searchHits = [
245
200
  "apple",
@@ -273,18 +228,12 @@ describe("Render combobox", () => {
273
228
  const combobox = screen.getByRole("combobox", {
274
229
  name: "Hva er dine favorittfrukter?",
275
230
  });
276
-
277
- await act(async () => {
278
- await userEvent.click(combobox);
279
-
280
- await userEvent.type(combobox, "p");
281
- });
231
+ await userEvent.click(combobox);
232
+ await userEvent.type(combobox, "p");
282
233
 
283
234
  expect(combobox.getAttribute("value")).toBe("passion fruit");
284
235
 
285
- await act(async () => {
286
- await userEvent.keyboard("{Enter}");
287
- });
236
+ await userEvent.keyboard("{Enter}");
288
237
 
289
238
  expect(onToggleSelected).toHaveBeenCalledWith(
290
239
  "passion fruit",
@@ -310,20 +259,14 @@ describe("Render combobox", () => {
310
259
  const combobox = screen.getByRole("combobox", {
311
260
  name: "Hva er dine favorittfrukter?",
312
261
  });
313
-
314
- await act(async () => {
315
- await userEvent.click(combobox);
316
-
317
- await userEvent.type(combobox, "p");
318
- });
262
+ await userEvent.click(combobox);
263
+ await userEvent.type(combobox, "p");
319
264
 
320
265
  expect(combobox.getAttribute("value")).toBe(
321
266
  "passion fruit (passion fruit)",
322
267
  );
323
268
 
324
- await act(async () => {
325
- await userEvent.keyboard("{Enter}");
326
- });
269
+ await userEvent.keyboard("{Enter}");
327
270
 
328
271
  expect(onToggleSelected).toHaveBeenCalledWith(
329
272
  "passion fruit",
@@ -342,9 +285,7 @@ describe("Render combobox", () => {
342
285
  });
343
286
 
344
287
  const pressKey = async (key: string) => {
345
- await act(async () => {
346
- await userEvent.keyboard(`{${key}}`);
347
- });
288
+ await userEvent.keyboard(`{${key}}`);
348
289
  };
349
290
 
350
291
  const hasVirtualFocus = (option: string) =>
@@ -352,9 +293,7 @@ describe("Render combobox", () => {
352
293
  screen.getByRole("option", { name: option }).id,
353
294
  );
354
295
 
355
- await act(async () => {
356
- await userEvent.click(combobox);
357
- });
296
+ await userEvent.click(combobox);
358
297
 
359
298
  await pressKey("ArrowDown");
360
299
  hasVirtualFocus("apple");
@@ -124,14 +124,14 @@ export const Switch = forwardRef<HTMLInputElement, SwitchProps>(
124
124
  htmlFor={inputProps.id}
125
125
  className={cn("navds-switch__label-wrapper")}
126
126
  >
127
- <div
127
+ <span
128
128
  className={cn("navds-switch__content", {
129
129
  "navds-sr-only": hideLabel,
130
130
  "navds-switch--with-description": description && !hideLabel,
131
131
  })}
132
132
  >
133
133
  <BodyShort
134
- as="div"
134
+ as="span"
135
135
  size={size}
136
136
  className={cn("navds-switch__label")}
137
137
  >
@@ -141,7 +141,7 @@ export const Switch = forwardRef<HTMLInputElement, SwitchProps>(
141
141
  {description && (
142
142
  <BodyShort
143
143
  size={size}
144
- as="div"
144
+ as="span"
145
145
  className={cn(
146
146
  "navds-form-field__subdescription navds-switch__description",
147
147
  )}
@@ -149,7 +149,7 @@ export const Switch = forwardRef<HTMLInputElement, SwitchProps>(
149
149
  {description}
150
150
  </BodyShort>
151
151
  )}
152
- </div>
152
+ </span>
153
153
  </label>
154
154
  </div>
155
155
  );
@@ -148,7 +148,7 @@ export const Popover = forwardRef<HTMLDivElement, PopoverProps>(
148
148
 
149
149
  useClientLayoutEffect(() => {
150
150
  refs.setReference(anchorEl);
151
- }, [anchorEl]);
151
+ }, [anchorEl, refs]);
152
152
 
153
153
  const floatingRef = useMergeRefs(refs.setFloating, ref);
154
154