@navikt/ds-react 6.6.1 → 6.7.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 (258) hide show
  1. package/cjs/chat/Chat.d.ts +2 -1
  2. package/cjs/chat/Chat.js +2 -1
  3. package/cjs/chat/Chat.js.map +1 -1
  4. package/cjs/date/datepicker/parts/DropdownCaption.js +1 -1
  5. package/cjs/date/datepicker/parts/DropdownCaption.js.map +1 -1
  6. package/cjs/date/monthpicker/MonthCaption.js +1 -1
  7. package/cjs/date/utils/labels.d.ts +2 -2
  8. package/cjs/form/ReadOnlyIcon.d.ts +2 -2
  9. package/cjs/form/combobox/Combobox.js +7 -22
  10. package/cjs/form/combobox/Combobox.js.map +1 -1
  11. package/cjs/form/combobox/ComboboxProvider.js +2 -2
  12. package/cjs/form/combobox/ComboboxProvider.js.map +1 -1
  13. package/cjs/form/combobox/ComboboxWrapper.d.ts +1 -2
  14. package/cjs/form/combobox/ComboboxWrapper.js +4 -2
  15. package/cjs/form/combobox/ComboboxWrapper.js.map +1 -1
  16. package/cjs/form/combobox/FilteredOptions/FilteredOptions.js +4 -4
  17. package/cjs/form/combobox/FilteredOptions/FilteredOptions.js.map +1 -1
  18. package/cjs/form/combobox/FilteredOptions/filteredOptionsContext.d.ts +4 -4
  19. package/cjs/form/combobox/FilteredOptions/filteredOptionsContext.js +13 -15
  20. package/cjs/form/combobox/FilteredOptions/filteredOptionsContext.js.map +1 -1
  21. package/cjs/form/combobox/Input/{inputContext.d.ts → Input.context.d.ts} +7 -5
  22. package/cjs/form/combobox/Input/{inputContext.js → Input.context.js} +22 -22
  23. package/cjs/form/combobox/Input/Input.context.js.map +1 -0
  24. package/cjs/form/combobox/Input/Input.js +2 -2
  25. package/cjs/form/combobox/Input/Input.js.map +1 -1
  26. package/cjs/form/combobox/Input/InputController.d.ts +3 -0
  27. package/cjs/form/combobox/Input/InputController.js +70 -0
  28. package/cjs/form/combobox/Input/InputController.js.map +1 -0
  29. package/cjs/form/combobox/{ToggleListButton.js → Input/ToggleListButton.js} +1 -1
  30. package/cjs/form/combobox/Input/ToggleListButton.js.map +1 -0
  31. package/cjs/form/combobox/SelectedOptions/SelectedOptions.js +2 -2
  32. package/cjs/form/combobox/SelectedOptions/SelectedOptions.js.map +1 -1
  33. package/cjs/form/combobox/SelectedOptions/selectedOptionsContext.d.ts +4 -4
  34. package/cjs/form/combobox/SelectedOptions/selectedOptionsContext.js +7 -13
  35. package/cjs/form/combobox/SelectedOptions/selectedOptionsContext.js.map +1 -1
  36. package/cjs/form/combobox/customOptionsContext.d.ts +4 -4
  37. package/cjs/form/combobox/customOptionsContext.js +10 -13
  38. package/cjs/form/combobox/customOptionsContext.js.map +1 -1
  39. package/cjs/form/combobox/types.d.ts +1 -1
  40. package/cjs/help-text/HelpTextIcon.d.ts +1 -1
  41. package/cjs/index.d.ts +1 -0
  42. package/cjs/index.js +4 -2
  43. package/cjs/index.js.map +1 -1
  44. package/cjs/overlay/dismiss/DismissableLayer.d.ts +70 -0
  45. package/cjs/overlay/dismiss/DismissableLayer.js +253 -0
  46. package/cjs/overlay/dismiss/DismissableLayer.js.map +1 -0
  47. package/cjs/overlay/dismiss/util/dispatchCustomEvent.d.ts +50 -0
  48. package/cjs/overlay/dismiss/util/dispatchCustomEvent.js +65 -0
  49. package/cjs/overlay/dismiss/util/dispatchCustomEvent.js.map +1 -0
  50. package/cjs/overlay/dismiss/util/useEscapeKeydown.d.ts +1 -0
  51. package/cjs/overlay/dismiss/util/useEscapeKeydown.js +19 -0
  52. package/cjs/overlay/dismiss/util/useEscapeKeydown.js.map +1 -0
  53. package/cjs/overlay/dismiss/util/useFocusOutside.d.ts +8 -0
  54. package/cjs/overlay/dismiss/util/useFocusOutside.js +42 -0
  55. package/cjs/overlay/dismiss/util/useFocusOutside.js.map +1 -0
  56. package/cjs/overlay/dismiss/util/usePointerDownOutside.d.ts +10 -0
  57. package/cjs/overlay/dismiss/util/usePointerDownOutside.js +84 -0
  58. package/cjs/overlay/dismiss/util/usePointerDownOutside.js.map +1 -0
  59. package/cjs/overlays/floating/Floating.d.ts +53 -0
  60. package/cjs/overlays/floating/Floating.js +215 -0
  61. package/cjs/overlays/floating/Floating.js.map +1 -0
  62. package/cjs/overlays/floating/Floating.utils.d.ts +18 -0
  63. package/cjs/overlays/floating/Floating.utils.js +52 -0
  64. package/cjs/overlays/floating/Floating.utils.js.map +1 -0
  65. package/cjs/popover/Popover.js +13 -28
  66. package/cjs/popover/Popover.js.map +1 -1
  67. package/cjs/progress-bar/ProgressBar.d.ts +72 -0
  68. package/cjs/progress-bar/ProgressBar.js +86 -0
  69. package/cjs/progress-bar/ProgressBar.js.map +1 -0
  70. package/cjs/progress-bar/index.d.ts +1 -0
  71. package/cjs/progress-bar/index.js +10 -0
  72. package/cjs/progress-bar/index.js.map +1 -0
  73. package/cjs/tabs/Tabs.context.d.ts +7 -3
  74. package/cjs/tabs/Tabs.context.js +1 -0
  75. package/cjs/tabs/Tabs.context.js.map +1 -1
  76. package/cjs/timeline/AxisLabels.d.ts +1 -1
  77. package/cjs/toggle-group/ToggleGroup.context.d.ts +7 -3
  78. package/cjs/toggle-group/ToggleGroup.context.js +1 -0
  79. package/cjs/toggle-group/ToggleGroup.context.js.map +1 -1
  80. package/cjs/typography/BodyLong.d.ts +7 -7
  81. package/cjs/typography/BodyLong.js +5 -5
  82. package/cjs/typography/BodyShort.d.ts +5 -5
  83. package/cjs/typography/BodyShort.js +3 -3
  84. package/cjs/typography/Detail.d.ts +5 -5
  85. package/cjs/typography/Detail.js +3 -3
  86. package/cjs/typography/ErrorMessage.d.ts +5 -5
  87. package/cjs/typography/ErrorMessage.js +3 -3
  88. package/cjs/typography/Heading.d.ts +6 -6
  89. package/cjs/typography/Heading.js +3 -3
  90. package/cjs/typography/Label.d.ts +5 -5
  91. package/cjs/typography/Label.js +3 -3
  92. package/cjs/typography/types.d.ts +3 -3
  93. package/cjs/util/hooks/descendants/useDescendant.d.ts +2 -2
  94. package/cjs/util/hooks/descendants/useDescendant.js +49 -52
  95. package/cjs/util/hooks/descendants/useDescendant.js.map +1 -1
  96. package/cjs/util/types/AsChild.d.ts +14 -0
  97. package/cjs/util/types/AsChild.js +3 -0
  98. package/cjs/util/types/AsChild.js.map +1 -0
  99. package/esm/chat/Chat.d.ts +2 -1
  100. package/esm/chat/Chat.js +1 -0
  101. package/esm/chat/Chat.js.map +1 -1
  102. package/esm/date/datepicker/parts/DropdownCaption.js +1 -1
  103. package/esm/date/datepicker/parts/DropdownCaption.js.map +1 -1
  104. package/esm/date/monthpicker/MonthCaption.js +1 -1
  105. package/esm/date/utils/labels.d.ts +2 -2
  106. package/esm/form/ReadOnlyIcon.d.ts +2 -2
  107. package/esm/form/combobox/Combobox.js +8 -23
  108. package/esm/form/combobox/Combobox.js.map +1 -1
  109. package/esm/form/combobox/ComboboxProvider.js +1 -1
  110. package/esm/form/combobox/ComboboxProvider.js.map +1 -1
  111. package/esm/form/combobox/ComboboxWrapper.d.ts +1 -2
  112. package/esm/form/combobox/ComboboxWrapper.js +4 -2
  113. package/esm/form/combobox/ComboboxWrapper.js.map +1 -1
  114. package/esm/form/combobox/FilteredOptions/FilteredOptions.js +3 -3
  115. package/esm/form/combobox/FilteredOptions/FilteredOptions.js.map +1 -1
  116. package/esm/form/combobox/FilteredOptions/filteredOptionsContext.d.ts +4 -4
  117. package/esm/form/combobox/FilteredOptions/filteredOptionsContext.js +15 -16
  118. package/esm/form/combobox/FilteredOptions/filteredOptionsContext.js.map +1 -1
  119. package/esm/form/combobox/Input/{inputContext.d.ts → Input.context.d.ts} +7 -5
  120. package/esm/form/combobox/Input/{inputContext.js → Input.context.js} +22 -21
  121. package/esm/form/combobox/Input/Input.context.js.map +1 -0
  122. package/esm/form/combobox/Input/Input.js +1 -1
  123. package/esm/form/combobox/Input/Input.js.map +1 -1
  124. package/esm/form/combobox/Input/InputController.d.ts +3 -0
  125. package/esm/form/combobox/Input/InputController.js +41 -0
  126. package/esm/form/combobox/Input/InputController.js.map +1 -0
  127. package/esm/form/combobox/{ToggleListButton.js → Input/ToggleListButton.js} +1 -1
  128. package/esm/form/combobox/Input/ToggleListButton.js.map +1 -0
  129. package/esm/form/combobox/SelectedOptions/SelectedOptions.js +1 -1
  130. package/esm/form/combobox/SelectedOptions/SelectedOptions.js.map +1 -1
  131. package/esm/form/combobox/SelectedOptions/selectedOptionsContext.d.ts +4 -4
  132. package/esm/form/combobox/SelectedOptions/selectedOptionsContext.js +9 -14
  133. package/esm/form/combobox/SelectedOptions/selectedOptionsContext.js.map +1 -1
  134. package/esm/form/combobox/customOptionsContext.d.ts +4 -4
  135. package/esm/form/combobox/customOptionsContext.js +10 -12
  136. package/esm/form/combobox/customOptionsContext.js.map +1 -1
  137. package/esm/form/combobox/types.d.ts +1 -1
  138. package/esm/help-text/HelpTextIcon.d.ts +1 -1
  139. package/esm/index.d.ts +1 -0
  140. package/esm/index.js +1 -0
  141. package/esm/index.js.map +1 -1
  142. package/esm/overlay/dismiss/DismissableLayer.d.ts +70 -0
  143. package/esm/overlay/dismiss/DismissableLayer.js +226 -0
  144. package/esm/overlay/dismiss/DismissableLayer.js.map +1 -0
  145. package/esm/overlay/dismiss/util/dispatchCustomEvent.d.ts +50 -0
  146. package/esm/overlay/dismiss/util/dispatchCustomEvent.js +58 -0
  147. package/esm/overlay/dismiss/util/dispatchCustomEvent.js.map +1 -0
  148. package/esm/overlay/dismiss/util/useEscapeKeydown.d.ts +1 -0
  149. package/esm/overlay/dismiss/util/useEscapeKeydown.js +15 -0
  150. package/esm/overlay/dismiss/util/useEscapeKeydown.js.map +1 -0
  151. package/esm/overlay/dismiss/util/useFocusOutside.d.ts +8 -0
  152. package/esm/overlay/dismiss/util/useFocusOutside.js +38 -0
  153. package/esm/overlay/dismiss/util/useFocusOutside.js.map +1 -0
  154. package/esm/overlay/dismiss/util/usePointerDownOutside.d.ts +10 -0
  155. package/esm/overlay/dismiss/util/usePointerDownOutside.js +80 -0
  156. package/esm/overlay/dismiss/util/usePointerDownOutside.js.map +1 -0
  157. package/esm/overlays/floating/Floating.d.ts +53 -0
  158. package/esm/overlays/floating/Floating.js +188 -0
  159. package/esm/overlays/floating/Floating.js.map +1 -0
  160. package/esm/overlays/floating/Floating.utils.d.ts +18 -0
  161. package/esm/overlays/floating/Floating.utils.js +48 -0
  162. package/esm/overlays/floating/Floating.utils.js.map +1 -0
  163. package/esm/popover/Popover.js +16 -31
  164. package/esm/popover/Popover.js.map +1 -1
  165. package/esm/progress-bar/ProgressBar.d.ts +72 -0
  166. package/esm/progress-bar/ProgressBar.js +57 -0
  167. package/esm/progress-bar/ProgressBar.js.map +1 -0
  168. package/esm/progress-bar/index.d.ts +1 -0
  169. package/esm/progress-bar/index.js +3 -0
  170. package/esm/progress-bar/index.js.map +1 -0
  171. package/esm/tabs/Tabs.context.d.ts +7 -3
  172. package/esm/tabs/Tabs.context.js +1 -0
  173. package/esm/tabs/Tabs.context.js.map +1 -1
  174. package/esm/timeline/AxisLabels.d.ts +1 -1
  175. package/esm/toggle-group/ToggleGroup.context.d.ts +7 -3
  176. package/esm/toggle-group/ToggleGroup.context.js +1 -0
  177. package/esm/toggle-group/ToggleGroup.context.js.map +1 -1
  178. package/esm/typography/BodyLong.d.ts +7 -7
  179. package/esm/typography/BodyLong.js +5 -5
  180. package/esm/typography/BodyShort.d.ts +5 -5
  181. package/esm/typography/BodyShort.js +3 -3
  182. package/esm/typography/Detail.d.ts +5 -5
  183. package/esm/typography/Detail.js +3 -3
  184. package/esm/typography/ErrorMessage.d.ts +5 -5
  185. package/esm/typography/ErrorMessage.js +3 -3
  186. package/esm/typography/Heading.d.ts +6 -6
  187. package/esm/typography/Heading.js +3 -3
  188. package/esm/typography/Label.d.ts +5 -5
  189. package/esm/typography/Label.js +3 -3
  190. package/esm/typography/types.d.ts +3 -3
  191. package/esm/util/hooks/descendants/useDescendant.d.ts +2 -2
  192. package/esm/util/hooks/descendants/useDescendant.js +49 -52
  193. package/esm/util/hooks/descendants/useDescendant.js.map +1 -1
  194. package/esm/util/types/AsChild.d.ts +14 -0
  195. package/esm/util/types/AsChild.js +2 -0
  196. package/esm/util/types/AsChild.js.map +1 -0
  197. package/package.json +16 -5
  198. package/src/chat/Chat.tsx +2 -1
  199. package/src/date/datepicker/parts/DropdownCaption.tsx +5 -1
  200. package/src/date/monthpicker/MonthCaption.tsx +1 -1
  201. package/src/form/combobox/Combobox.tsx +6 -76
  202. package/src/form/combobox/ComboboxProvider.tsx +1 -1
  203. package/src/form/combobox/ComboboxWrapper.tsx +4 -3
  204. package/src/form/combobox/FilteredOptions/FilteredOptions.tsx +3 -3
  205. package/src/form/combobox/FilteredOptions/filteredOptionsContext.tsx +19 -29
  206. package/src/form/combobox/Input/{inputContext.tsx → Input.context.tsx} +30 -33
  207. package/src/form/combobox/Input/Input.tsx +1 -1
  208. package/src/form/combobox/Input/InputController.tsx +102 -0
  209. package/src/form/combobox/{ToggleListButton.tsx → Input/ToggleListButton.tsx} +1 -1
  210. package/src/form/combobox/SelectedOptions/SelectedOptions.tsx +1 -1
  211. package/src/form/combobox/SelectedOptions/selectedOptionsContext.tsx +12 -26
  212. package/src/form/combobox/{combobox-utils.test.ts → __tests__/combobox-utils.test.ts} +1 -1
  213. package/src/form/combobox/{combobox.test.tsx → __tests__/combobox.test.tsx} +2 -3
  214. package/src/form/combobox/customOptionsContext.tsx +14 -18
  215. package/src/form/combobox/types.ts +3 -1
  216. package/src/index.ts +1 -0
  217. package/src/overlay/README.md +5 -0
  218. package/src/overlay/dismiss/DismissableLayer.tsx +368 -0
  219. package/src/overlay/dismiss/util/dispatchCustomEvent.ts +77 -0
  220. package/src/overlay/dismiss/util/useEscapeKeydown.ts +21 -0
  221. package/src/overlay/dismiss/util/useFocusOutside.ts +52 -0
  222. package/src/overlay/dismiss/util/usePointerDownOutside.ts +95 -0
  223. package/src/overlays/floating/Floating.tsx +399 -0
  224. package/src/overlays/floating/Floating.utils.ts +63 -0
  225. package/src/popover/Popover.tsx +38 -70
  226. package/src/progress-bar/ProgressBar.tsx +149 -0
  227. package/src/progress-bar/index.ts +2 -0
  228. package/src/tabs/Tabs.context.ts +2 -0
  229. package/src/toggle-group/ToggleGroup.context.ts +1 -0
  230. package/src/typography/BodyLong.tsx +7 -7
  231. package/src/typography/BodyShort.tsx +5 -5
  232. package/src/typography/Detail.tsx +5 -5
  233. package/src/typography/ErrorMessage.tsx +5 -5
  234. package/src/typography/Heading.tsx +6 -6
  235. package/src/typography/Label.tsx +5 -5
  236. package/src/typography/types.ts +3 -3
  237. package/src/util/hooks/descendants/useDescendant.tsx +55 -68
  238. package/src/util/types/AsChild.ts +15 -0
  239. package/cjs/form/combobox/ClearButton.d.ts +0 -7
  240. package/cjs/form/combobox/ClearButton.js +0 -28
  241. package/cjs/form/combobox/ClearButton.js.map +0 -1
  242. package/cjs/form/combobox/FilteredOptions/CheckIcon.d.ts +0 -3
  243. package/cjs/form/combobox/FilteredOptions/CheckIcon.js +0 -12
  244. package/cjs/form/combobox/FilteredOptions/CheckIcon.js.map +0 -1
  245. package/cjs/form/combobox/Input/inputContext.js.map +0 -1
  246. package/cjs/form/combobox/ToggleListButton.js.map +0 -1
  247. package/esm/form/combobox/ClearButton.d.ts +0 -7
  248. package/esm/form/combobox/ClearButton.js +0 -21
  249. package/esm/form/combobox/ClearButton.js.map +0 -1
  250. package/esm/form/combobox/FilteredOptions/CheckIcon.d.ts +0 -3
  251. package/esm/form/combobox/FilteredOptions/CheckIcon.js +0 -7
  252. package/esm/form/combobox/FilteredOptions/CheckIcon.js.map +0 -1
  253. package/esm/form/combobox/Input/inputContext.js.map +0 -1
  254. package/esm/form/combobox/ToggleListButton.js.map +0 -1
  255. package/src/form/combobox/ClearButton.tsx +0 -29
  256. package/src/form/combobox/FilteredOptions/CheckIcon.tsx +0 -23
  257. /package/cjs/form/combobox/{ToggleListButton.d.ts → Input/ToggleListButton.d.ts} +0 -0
  258. /package/esm/form/combobox/{ToggleListButton.d.ts → Input/ToggleListButton.d.ts} +0 -0
@@ -4,22 +4,14 @@ import {
4
4
  offset as flOffset,
5
5
  flip,
6
6
  shift,
7
- useClick,
8
- useDismiss,
9
7
  useFloating,
10
- useInteractions,
11
8
  } from "@floating-ui/react";
12
9
  import cl from "clsx";
13
- import React, {
14
- HTMLAttributes,
15
- forwardRef,
16
- useCallback,
17
- useContext,
18
- useRef,
19
- } from "react";
10
+ import React, { HTMLAttributes, forwardRef, useContext, useRef } from "react";
20
11
  import { DateContext } from "../date/context";
21
12
  import { useModalContext } from "../modal/Modal.context";
22
- import { useClientLayoutEffect, useEventListener } from "../util/hooks";
13
+ import { DismissableLayer } from "../overlay/dismiss/DismissableLayer";
14
+ import { useClientLayoutEffect } from "../util/hooks";
23
15
  import { useMergeRefs } from "../util/hooks/useMergeRefs";
24
16
  import PopoverContent, { PopoverContentType } from "./PopoverContent";
25
17
 
@@ -133,19 +125,15 @@ export const Popover = forwardRef<HTMLDivElement, PopoverProps>(
133
125
  const chosenFlip = isInDatepicker ? false : _flip;
134
126
 
135
127
  const {
136
- x,
137
- y,
138
- strategy,
139
- context,
140
128
  update,
141
129
  refs,
142
130
  placement: flPlacement,
143
131
  middlewareData: { arrow: { x: arrowX, y: arrowY } = {} },
132
+ floatingStyles,
144
133
  } = useFloating({
145
134
  strategy: chosenStrategy,
146
135
  placement,
147
136
  open,
148
- onOpenChange: () => onClose(),
149
137
  middleware: [
150
138
  flOffset(offset ?? (arrow ? 16 : 4)),
151
139
  chosenFlip &&
@@ -155,11 +143,6 @@ export const Popover = forwardRef<HTMLDivElement, PopoverProps>(
155
143
  ],
156
144
  });
157
145
 
158
- const { getFloatingProps } = useInteractions([
159
- useClick(context),
160
- useDismiss(context),
161
- ]);
162
-
163
146
  useClientLayoutEffect(() => {
164
147
  refs.setReference(anchorEl);
165
148
  }, [anchorEl]);
@@ -176,24 +159,6 @@ export const Popover = forwardRef<HTMLDivElement, PopoverProps>(
176
159
  return () => cleanup();
177
160
  }, [refs.floating, refs.reference, update, open, anchorEl]);
178
161
 
179
- useEventListener(
180
- "focusin",
181
- useCallback(
182
- (e: FocusEvent) => {
183
- if (
184
- e.target instanceof HTMLElement &&
185
- ![anchorEl, refs.floating.current].some(
186
- (element) => element?.contains(e.target as Node),
187
- ) &&
188
- !e.target.contains(refs.floating.current)
189
- ) {
190
- open && onClose();
191
- }
192
- },
193
- [anchorEl, refs, open, onClose],
194
- ),
195
- );
196
-
197
162
  const staticSide = {
198
163
  top: "bottom",
199
164
  right: "left",
@@ -202,38 +167,41 @@ export const Popover = forwardRef<HTMLDivElement, PopoverProps>(
202
167
  }[flPlacement.split("-")[0]];
203
168
 
204
169
  return (
205
- <div
206
- className={cl("navds-popover", className, {
207
- "navds-popover--hidden": !open || !anchorEl,
208
- })}
209
- data-placement={flPlacement}
210
- aria-hidden={!open || !anchorEl}
211
- {...getFloatingProps({
212
- ref: floatingRef,
213
- style: {
214
- position: strategy,
215
- top: y ?? 0,
216
- left: x ?? 0,
217
- },
218
- tabIndex: undefined,
219
- })}
220
- {...rest}
170
+ <DismissableLayer
171
+ asChild
172
+ safeZone={{
173
+ anchor: anchorEl,
174
+ dismissable: refs.floating.current,
175
+ }}
176
+ onDismiss={() => open && onClose?.()}
177
+ enabled={open}
221
178
  >
222
- {children}
223
- {arrow && (
224
- <div
225
- ref={(node) => {
226
- arrowRef.current = node;
227
- }}
228
- style={{
229
- ...(arrowX != null ? { left: arrowX } : {}),
230
- ...(arrowY != null ? { top: arrowY } : {}),
231
- ...(staticSide ? { [staticSide]: "-0.5rem" } : {}),
232
- }}
233
- className="navds-popover__arrow"
234
- />
235
- )}
236
- </div>
179
+ <div
180
+ ref={floatingRef}
181
+ {...rest}
182
+ className={cl("navds-popover", className, {
183
+ "navds-popover--hidden": !open || !anchorEl,
184
+ })}
185
+ style={{ ...rest.style, ...floatingStyles }}
186
+ data-placement={flPlacement}
187
+ aria-hidden={!open || !anchorEl}
188
+ >
189
+ {children}
190
+ {arrow && (
191
+ <div
192
+ ref={(node) => {
193
+ arrowRef.current = node;
194
+ }}
195
+ style={{
196
+ ...(arrowX != null ? { left: arrowX } : {}),
197
+ ...(arrowY != null ? { top: arrowY } : {}),
198
+ ...(staticSide ? { [staticSide]: "-0.5rem" } : {}),
199
+ }}
200
+ className="navds-popover__arrow"
201
+ />
202
+ )}
203
+ </div>
204
+ </DismissableLayer>
237
205
  );
238
206
  },
239
207
  ) as PopoverComponent;
@@ -0,0 +1,149 @@
1
+ import cl from "clsx";
2
+ import React, { HTMLAttributes, forwardRef, useRef } from "react";
3
+
4
+ interface ProgressBarPropsBase
5
+ extends Omit<HTMLAttributes<HTMLDivElement>, "role"> {
6
+ /**
7
+ * Changes height.
8
+ * @default "medium"
9
+ */
10
+ size?: "large" | "medium" | "small";
11
+ /**
12
+ * Current progress. If set, the `simulated` prop overrides `value`.
13
+ */
14
+ value?: number;
15
+ /**
16
+ * Maximum progress.
17
+ * @default 100
18
+ */
19
+ valueMax?: number;
20
+ /**
21
+ * Visually simulates loading.
22
+ * ProgressBar grows with a preset animation for set number of seconds,
23
+ * then shows an indeterminate animation on timeout.
24
+ */
25
+ simulated?: {
26
+ /**
27
+ * Duration in seconds.
28
+ */
29
+ seconds: number;
30
+ /**
31
+ * Callback function when progress is indeterminate.
32
+ */
33
+ onTimeout: () => void;
34
+ };
35
+ /**
36
+ * String ID of the element that labels the progress bar.
37
+ * Not needed if `aria-label` is used.
38
+ */
39
+ "aria-labelledby"?: string;
40
+ /**
41
+ * String value that labels the progress bar.
42
+ * Not needed if `aria-labelledby` is used.
43
+ */
44
+ "aria-label"?: string;
45
+ }
46
+
47
+ export type ProgressBarProps = ProgressBarPropsBase &
48
+ (
49
+ | {
50
+ "aria-hidden": true;
51
+ }
52
+ | {
53
+ "aria-labelledby": string;
54
+ "aria-label"?: never;
55
+ }
56
+ | {
57
+ "aria-label": string;
58
+ "aria-labelledby"?: never;
59
+ }
60
+ );
61
+
62
+ /**
63
+ * ProgressBar
64
+ * A component for visualizing progression in a process.
65
+ *
66
+ * @see [📝 Documentation](https://aksel.nav.no/komponenter/core/progress-bar)
67
+ * @see 🏷️ {@link ProgressBarProps}
68
+ *
69
+ * @example
70
+ * // For loading content with an approximate duration in sec.
71
+ * <ProgressBar simulated={{
72
+ * seconds: 30,
73
+ * onTimeout: () => console.log("Oops, this is taking more time than expected!")
74
+ * }}
75
+ * />
76
+ *
77
+ * @example
78
+ * // As a step indicator for forms, questionnaires, etc.
79
+ * <ProgressBar value={2} valueMax={7} />
80
+ */
81
+ export const ProgressBar = forwardRef<HTMLDivElement, ProgressBarProps>(
82
+ (
83
+ {
84
+ size = "medium",
85
+ value = 0,
86
+ valueMax = 100,
87
+ "aria-labelledby": ariaLabelledBy,
88
+ "aria-label": ariaLabel,
89
+ className,
90
+ simulated,
91
+ ...rest
92
+ },
93
+ ref,
94
+ ) => {
95
+ const translate = 100 - (Math.round(value) / valueMax) * 100;
96
+ const onTimeoutRef = useRef<() => void>();
97
+ onTimeoutRef.current = simulated?.onTimeout;
98
+
99
+ React.useEffect(() => {
100
+ if (simulated?.seconds && onTimeoutRef.current) {
101
+ const timeout = setTimeout(
102
+ onTimeoutRef.current,
103
+ simulated.seconds * 1000,
104
+ );
105
+ return () => clearTimeout(timeout);
106
+ }
107
+ }, [simulated?.seconds]);
108
+
109
+ return (
110
+ <div
111
+ ref={ref}
112
+ className={cl(
113
+ "navds-progress-bar",
114
+ `navds-progress-bar--${size}`,
115
+ className,
116
+ )}
117
+ aria-valuemax={simulated?.seconds ? 0 : Math.round(valueMax)}
118
+ aria-valuenow={simulated?.seconds ? 0 : Math.round(value)}
119
+ aria-valuetext={
120
+ simulated?.seconds
121
+ ? `Fremdrift kan ikke beregnes, antatt tid er: ${simulated?.seconds} sekunder`
122
+ : `${Math.round(value)} av ${Math.round(valueMax)}`
123
+ }
124
+ role="progressbar"
125
+ aria-labelledby={ariaLabelledBy}
126
+ aria-label={ariaLabel}
127
+ {...rest}
128
+ >
129
+ <div
130
+ className={cl("navds-progress-bar__foreground", {
131
+ "navds-progress-bar__foreground--indeterminate": Number.isInteger(
132
+ simulated?.seconds,
133
+ ),
134
+ })}
135
+ style={{
136
+ "--__ac-progress-bar-simulated": Number.isInteger(
137
+ simulated?.seconds,
138
+ )
139
+ ? `${simulated?.seconds}s`
140
+ : undefined,
141
+ "--__ac-progress-bar-translate": `-${translate}%`,
142
+ }}
143
+ />
144
+ </div>
145
+ );
146
+ },
147
+ );
148
+
149
+ export default ProgressBar;
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ export { default as ProgressBar, type ProgressBarProps } from "./ProgressBar";
@@ -21,4 +21,6 @@ export const [TabsProvider, useTabsContext] = createContext<TabsProviderProps>({
21
21
  name: "TabsContext",
22
22
  hookName: "useTabsContext",
23
23
  providerName: "TabsProvider",
24
+ errorMessage:
25
+ "Tabs.List, Tabs.Tag and Tabs.Panel needs to be wrapped within <Tabs>",
24
26
  });
@@ -28,4 +28,5 @@ export const [ToggleGroupProvider, useToggleGroupContext] =
28
28
  name: "ToggleGroupContext",
29
29
  hookName: "useToggleGroupContext",
30
30
  providerName: "ToggleGroupProvider",
31
+ errorMessage: "<ToggleGroup.Item> needs to be wrapped within <ToggleGroup>",
31
32
  });
@@ -8,12 +8,12 @@ export interface BodyLongProps
8
8
  extends TypoProps,
9
9
  React.HTMLAttributes<HTMLParagraphElement> {
10
10
  /**
11
- * large: 20px, medium: 18px, small: 16px
11
+ * large: 20px, medium: 18px, small: 16px.
12
12
  * @default "medium"
13
13
  */
14
14
  size?: "large" | "medium" | "small";
15
15
  /**
16
- * Text
16
+ * Text.
17
17
  */
18
18
  children: React.ReactNode;
19
19
  }
@@ -27,11 +27,11 @@ export interface BodyLongProps
27
27
  *
28
28
  * @example
29
29
  * ```jsx
30
- * <BodyLong>
31
- * Hvis du ikke bor sammen med begge foreldrene dine,
32
- * kan du ha rett til barnebidrag fra en eller begge foreldre mens du
33
- * fullfører videregående skole eller tilsvarende.
34
- * </BodyLong>
30
+ * <BodyLong>
31
+ * Hvis du ikke bor sammen med begge foreldrene dine,
32
+ * kan du ha rett til barnebidrag fra en eller begge foreldre mens du
33
+ * fullfører videregående skole eller tilsvarende.
34
+ * </BodyLong>
35
35
  * ```
36
36
  */
37
37
  export const BodyLong: OverridableComponent<
@@ -8,12 +8,12 @@ export interface BodyShortProps
8
8
  extends TypoProps,
9
9
  React.HTMLAttributes<HTMLParagraphElement> {
10
10
  /**
11
- * large: 20px, medium: 18px, small: 16px
11
+ * large: 20px, medium: 18px, small: 16px.
12
12
  * @default "medium"
13
13
  */
14
14
  size?: "large" | "medium" | "small";
15
15
  /**
16
- * Paragraph text
16
+ * Paragraph text.
17
17
  */
18
18
  children: React.ReactNode;
19
19
  }
@@ -27,9 +27,9 @@ export interface BodyShortProps
27
27
  *
28
28
  * @example
29
29
  * ```jsx
30
- * <BodyShort>
31
- * Du må gjøre en filtrering for å se brukere i listen.
32
- * </BodyShort>
30
+ * <BodyShort>
31
+ * Du må gjøre en filtrering for å se brukere i listen.
32
+ * </BodyShort>
33
33
  * ```
34
34
  */
35
35
  export const BodyShort: OverridableComponent<
@@ -12,11 +12,11 @@ export interface DetailProps
12
12
  */
13
13
  size?: "medium" | "small";
14
14
  /**
15
- * Paragraph text
15
+ * Text.
16
16
  */
17
17
  children: React.ReactNode;
18
18
  /**
19
- * All caps
19
+ * ALL CAPS.
20
20
  */
21
21
  uppercase?: boolean;
22
22
  }
@@ -30,9 +30,9 @@ export interface DetailProps
30
30
  *
31
31
  * @example
32
32
  * ```jsx
33
- * <Detail>
34
- * Du må gjøre en filtrering for å se brukere i listen.
35
- * </Detail>
33
+ * <Detail>
34
+ * Du må gjøre en filtrering for å se brukere i listen.
35
+ * </Detail>
36
36
  * ```
37
37
  */
38
38
  export const Detail: OverridableComponent<DetailProps, HTMLParagraphElement> =
@@ -8,12 +8,12 @@ export interface ErrorMessageProps
8
8
  extends Pick<TypoProps, "spacing">,
9
9
  React.HTMLAttributes<HTMLParagraphElement> {
10
10
  /**
11
- * medium: 18px, small: 16px
11
+ * medium: 18px, small: 16px.
12
12
  * @default "medium"
13
13
  */
14
14
  size?: "medium" | "small";
15
15
  /**
16
- * Error text
16
+ * Error text.
17
17
  */
18
18
  children: React.ReactNode;
19
19
  }
@@ -27,9 +27,9 @@ export interface ErrorMessageProps
27
27
  *
28
28
  * @example
29
29
  * ```jsx
30
- * <ErrorMessage>
31
- * Du må fylle ut: Oppgi årsaken til at du har ventet mer enn 6 måneder med å søke om refusjon
32
- * </ErrorMessage>
30
+ * <ErrorMessage>
31
+ * Du må fylle ut: Oppgi årsaken til at du har ventet mer enn 6 måneder med å søke om refusjon
32
+ * </ErrorMessage>
33
33
  * ```
34
34
  */
35
35
  export const ErrorMessage: OverridableComponent<
@@ -8,16 +8,16 @@ export interface HeadingProps
8
8
  extends Pick<TypoProps, "spacing" | "visuallyHidden" | "align" | "textColor">,
9
9
  React.HTMLAttributes<HTMLHeadingElement> {
10
10
  /**
11
- * Heading level
11
+ * Heading level.
12
12
  * @default "1"
13
13
  */
14
14
  level?: "1" | "2" | "3" | "4" | "5" | "6";
15
15
  /**
16
- * Changes text-sizing
16
+ * xlarge: 40px, large: 32px, medium: 24px, small: 20px, xsmall: 18px.
17
17
  */
18
18
  size: "xlarge" | "large" | "medium" | "small" | "xsmall";
19
19
  /**
20
- * Heading text
20
+ * Heading text.
21
21
  */
22
22
  children: React.ReactNode;
23
23
  }
@@ -31,9 +31,9 @@ export interface HeadingProps
31
31
  *
32
32
  * @example
33
33
  * ```jsx
34
- * <Heading level="1" size="xlarge">
35
- * Hva kan vi hjelpe deg med?
36
- * </Heading>
34
+ * <Heading level="1" size="xlarge">
35
+ * Hva kan vi hjelpe deg med?
36
+ * </Heading>
37
37
  * ```
38
38
  */
39
39
  export const Heading: OverridableComponent<HeadingProps, HTMLHeadingElement> =
@@ -8,12 +8,12 @@ export interface LabelProps
8
8
  extends Omit<TypoProps, "weight" | "align" | "truncate">,
9
9
  React.LabelHTMLAttributes<HTMLLabelElement> {
10
10
  /**
11
- * medium: 18px, small: 16px
11
+ * medium: 18px, small: 16px.
12
12
  * @default "medium"
13
13
  */
14
14
  size?: "medium" | "small";
15
15
  /**
16
- * Paragraph text
16
+ * Label text.
17
17
  */
18
18
  children: React.ReactNode;
19
19
  }
@@ -27,9 +27,9 @@ export interface LabelProps
27
27
  *
28
28
  * @example
29
29
  * ```jsx
30
- * <Label>
31
- * Oppgi årsaken til at du har ventet mer enn 6 måneder med å søke om refusjon
32
- * </Label>
30
+ * <Label>
31
+ * Oppgi årsaken til at du har ventet mer enn 6 måneder med å søke om refusjon
32
+ * </Label>
33
33
  * ```
34
34
  */
35
35
  export const Label: OverridableComponent<LabelProps, HTMLLabelElement> =
@@ -12,15 +12,15 @@ export type TypoProps = {
12
12
  */
13
13
  align?: "start" | "center" | "end";
14
14
  /**
15
- * Visually hide text. Text will still be accessible for screenreaders
15
+ * Visually hide text. Text will still be accessible for screenreaders.
16
16
  */
17
17
  visuallyHidden?: boolean;
18
18
  /**
19
- * Adds spacing below text
19
+ * Adds spacing below text.
20
20
  */
21
21
  spacing?: boolean;
22
22
  /**
23
- * Adjusts color
23
+ * Adjusts color.
24
24
  */
25
25
  textColor?: "default" | "subtle";
26
26
  };
@@ -8,68 +8,6 @@ import { mergeRefs } from "../useMergeRefs";
8
8
  import { DescendantOptions, DescendantsManager } from "./descendant";
9
9
  import { cast } from "./utils";
10
10
 
11
- /**
12
- * @internal
13
- * Initializing DescendantsManager
14
- */
15
- function useDescendants<
16
- T extends HTMLElement = HTMLElement,
17
- K extends Record<string, any> = object,
18
- >() {
19
- const descendants = useRef(new DescendantsManager<T, K>()).current;
20
-
21
- return descendants;
22
- }
23
-
24
- const [DescendantsContextProvider, useDescendantsContext] = createContext<
25
- ReturnType<typeof useDescendants>
26
- >({
27
- name: "DescendantsProvider",
28
- errorMessage: "useDescendantsContext must be used within DescendantsProvider",
29
- });
30
-
31
- /**
32
- * @internal
33
- * This hook provides information to descendant component:
34
- * - Index compared to other descendants
35
- * - ref callback to register the descendant
36
- * - Its enabled index compared to other enabled descendants
37
- */
38
- function useDescendant<
39
- T extends HTMLElement = HTMLElement,
40
- K extends Record<string, any> = object,
41
- >(options?: DescendantOptions<K>) {
42
- const descendants = useDescendantsContext();
43
- const [index, setIndex] = useState(-1);
44
- const ref = useRef<T>(null);
45
-
46
- useClientLayoutEffect(() => {
47
- return () => {
48
- if (!ref.current) return;
49
- descendants.unregister(ref.current);
50
- };
51
- }, []);
52
-
53
- useClientLayoutEffect(() => {
54
- if (!ref.current) return;
55
- const dataIndex = Number(ref.current.dataset["index"]);
56
- if (index != dataIndex && !Number.isNaN(dataIndex)) {
57
- setIndex(dataIndex);
58
- }
59
- });
60
-
61
- const refCallback = options
62
- ? cast<React.RefCallback<T>>(descendants.register(options))
63
- : cast<React.RefCallback<T>>(descendants.register);
64
-
65
- return {
66
- descendants,
67
- index,
68
- enabledIndex: descendants.enabledIndexOf(ref.current),
69
- register: mergeRefs([refCallback, ref]),
70
- };
71
- }
72
-
73
11
  /**
74
12
  * Provides strongly typed versions of the context provider and hooks above.
75
13
  */
@@ -77,6 +15,14 @@ export function createDescendantContext<
77
15
  T extends HTMLElement = HTMLElement,
78
16
  K extends Record<string, any> = object,
79
17
  >() {
18
+ const [DescendantsContextProvider, useDescendantsContext] = createContext<
19
+ ReturnType<typeof _useDescendants>
20
+ >({
21
+ name: "DescendantsProvider",
22
+ errorMessage:
23
+ "useDescendantsContext must be used within DescendantsProvider",
24
+ });
25
+
80
26
  const ContextProvider = cast<React.Provider<DescendantsManager<T, K>>>(
81
27
  (props) => (
82
28
  <DescendantsContextProvider {...props.value}>
@@ -85,19 +31,60 @@ export function createDescendantContext<
85
31
  ),
86
32
  );
87
33
 
88
- const _useDescendantsContext = () =>
89
- cast<DescendantsManager<T, K>>(useDescendantsContext());
34
+ /**
35
+ * @internal
36
+ * This hook provides information to descendant component:
37
+ * - Index compared to other descendants
38
+ * - ref callback to register the descendant
39
+ * - Its enabled index compared to other enabled descendants
40
+ */
41
+ function _useDescendant(options?: DescendantOptions<K>) {
42
+ const descendants = useDescendantsContext();
43
+ const [index, setIndex] = useState(-1);
44
+ const ref = useRef<T>(null);
45
+
46
+ useClientLayoutEffect(() => {
47
+ return () => {
48
+ if (!ref.current) return;
49
+ descendants.unregister(ref.current);
50
+ };
51
+ }, []);
52
+
53
+ useClientLayoutEffect(() => {
54
+ if (!ref.current) return;
55
+ const dataIndex = Number(ref.current.dataset["index"]);
56
+ if (index != dataIndex && !Number.isNaN(dataIndex)) {
57
+ setIndex(dataIndex);
58
+ }
59
+ });
60
+
61
+ const refCallback = options
62
+ ? cast<React.RefCallback<T>>(descendants.register(options))
63
+ : cast<React.RefCallback<T>>(descendants.register);
64
+
65
+ return {
66
+ descendants,
67
+ index,
68
+ enabledIndex: descendants.enabledIndexOf(ref.current),
69
+ register: mergeRefs([refCallback, ref]),
70
+ };
71
+ }
90
72
 
91
- const _useDescendant = (options?: DescendantOptions<K>) =>
92
- useDescendant<T, K>(options);
73
+ /**
74
+ * @internal
75
+ * Initializing DescendantsManager
76
+ */
77
+ function _useDescendants() {
78
+ const descendants = useRef(new DescendantsManager<T, K>()).current;
93
79
 
94
- const _useDescendants = () => useDescendants<T, K>();
80
+ return descendants;
81
+ }
95
82
 
96
83
  return [
97
84
  // context provider
98
85
  ContextProvider,
99
86
  // call this when you need to read from context
100
- _useDescendantsContext,
87
+ useDescendantsContext,
101
88
  // descendants state information, to be called and passed to `ContextProvider`
102
89
  _useDescendants,
103
90
  // descendant index information
@@ -0,0 +1,15 @@
1
+ export type AsChild =
2
+ | {
3
+ children: React.ReactElement;
4
+ /**
5
+ * Renders the children as a child of the component. Merges the props of the component with the props of the child.
6
+ */
7
+ asChild: true;
8
+ }
9
+ | {
10
+ children: React.ReactNode;
11
+ /**
12
+ * Renders the children as a child of the component. Merges the props of the component with the props of the child.
13
+ */
14
+ asChild?: false;
15
+ };