@navikt/ds-react 7.33.2 → 7.33.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.
- package/cjs/form/textarea/Textarea.js +1 -8
- package/cjs/form/textarea/Textarea.js.map +1 -1
- package/cjs/overlays/action-menu/ActionMenu.d.ts +20 -0
- package/cjs/overlays/action-menu/ActionMenu.js +20 -0
- package/cjs/overlays/action-menu/ActionMenu.js.map +1 -1
- package/cjs/overlays/dismissablelayer/DismissableLayer.js +23 -32
- package/cjs/overlays/dismissablelayer/DismissableLayer.js.map +1 -1
- package/cjs/overlays/dismissablelayer/util/useEscapeKeydown.d.ts +1 -1
- package/cjs/overlays/dismissablelayer/util/useEscapeKeydown.js +8 -3
- package/cjs/overlays/dismissablelayer/util/useEscapeKeydown.js.map +1 -1
- package/cjs/overlays/dismissablelayer/util/useFocusOutside.d.ts +1 -1
- package/cjs/overlays/dismissablelayer/util/useFocusOutside.js +8 -3
- package/cjs/overlays/dismissablelayer/util/useFocusOutside.js.map +1 -1
- package/cjs/overlays/dismissablelayer/util/usePointerDownOutside.d.ts +1 -1
- package/cjs/overlays/dismissablelayer/util/usePointerDownOutside.js +5 -2
- package/cjs/overlays/dismissablelayer/util/usePointerDownOutside.js.map +1 -1
- package/cjs/util/TextareaAutoSize.js +5 -1
- package/cjs/util/TextareaAutoSize.js.map +1 -1
- package/esm/form/textarea/Textarea.js +1 -8
- package/esm/form/textarea/Textarea.js.map +1 -1
- package/esm/overlays/action-menu/ActionMenu.d.ts +20 -0
- package/esm/overlays/action-menu/ActionMenu.js +20 -0
- package/esm/overlays/action-menu/ActionMenu.js.map +1 -1
- package/esm/overlays/dismissablelayer/DismissableLayer.js +22 -31
- package/esm/overlays/dismissablelayer/DismissableLayer.js.map +1 -1
- package/esm/overlays/dismissablelayer/util/useEscapeKeydown.d.ts +1 -1
- package/esm/overlays/dismissablelayer/util/useEscapeKeydown.js +8 -3
- package/esm/overlays/dismissablelayer/util/useEscapeKeydown.js.map +1 -1
- package/esm/overlays/dismissablelayer/util/useFocusOutside.d.ts +1 -1
- package/esm/overlays/dismissablelayer/util/useFocusOutside.js +8 -3
- package/esm/overlays/dismissablelayer/util/useFocusOutside.js.map +1 -1
- package/esm/overlays/dismissablelayer/util/usePointerDownOutside.d.ts +1 -1
- package/esm/overlays/dismissablelayer/util/usePointerDownOutside.js +5 -2
- package/esm/overlays/dismissablelayer/util/usePointerDownOutside.js.map +1 -1
- package/esm/util/TextareaAutoSize.js +5 -1
- package/esm/util/TextareaAutoSize.js.map +1 -1
- package/package.json +5 -5
- package/src/form/textarea/Textarea.tsx +1 -9
- package/src/overlays/action-menu/ActionMenu.tsx +20 -0
- package/src/overlays/dismissablelayer/DismissableLayer.tsx +91 -97
- package/src/overlays/dismissablelayer/util/useEscapeKeydown.ts +9 -2
- package/src/overlays/dismissablelayer/util/useFocusOutside.ts +9 -2
- package/src/overlays/dismissablelayer/util/usePointerDownOutside.ts +6 -1
- package/src/util/TextareaAutoSize.tsx +6 -2
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React, { forwardRef, useContext, useEffect, useState } from "react";
|
|
2
2
|
import { Slot } from "../../slot/Slot";
|
|
3
|
-
import { omit } from "../../util";
|
|
4
3
|
import { composeEventHandlers } from "../../util/composeEventHandlers";
|
|
5
4
|
import { useMergeRefs } from "../../util/hooks";
|
|
6
5
|
import { ownerDocument } from "../../util/owner";
|
|
@@ -63,34 +62,7 @@ interface DismissableLayerBaseProps
|
|
|
63
62
|
|
|
64
63
|
type DismissableLayerProps = DismissableLayerBaseProps & AsChild;
|
|
65
64
|
|
|
66
|
-
|
|
67
|
-
({ enabled = true, ...restProps }: DismissableLayerProps, forwardedRef) => {
|
|
68
|
-
if (!enabled) {
|
|
69
|
-
const Component = restProps.asChild ? Slot : "div";
|
|
70
|
-
return (
|
|
71
|
-
<Component
|
|
72
|
-
{...omit(restProps, [
|
|
73
|
-
"asChild",
|
|
74
|
-
"disableOutsidePointerEvents",
|
|
75
|
-
"onDismiss",
|
|
76
|
-
"onEscapeKeyDown",
|
|
77
|
-
"onFocusOutside",
|
|
78
|
-
"onInteractOutside",
|
|
79
|
-
"onPointerDownOutside",
|
|
80
|
-
"safeZone",
|
|
81
|
-
])}
|
|
82
|
-
ref={forwardedRef}
|
|
83
|
-
/>
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return <DismissableLayerInternal {...restProps} ref={forwardedRef} />;
|
|
88
|
-
},
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
type DismissableLayerElement = React.ComponentRef<
|
|
92
|
-
typeof DismissableLayerInternal
|
|
93
|
-
>;
|
|
65
|
+
type DismissableLayerElement = React.ComponentRef<typeof DismissableLayer>;
|
|
94
66
|
|
|
95
67
|
const BranchedLayerContext =
|
|
96
68
|
React.createContext<DismissableLayerElement | null>(null);
|
|
@@ -108,10 +80,7 @@ const DismissableLayerContext = React.createContext({
|
|
|
108
80
|
layersWithOutsidePointerEventsDisabled: new Set<DismissableLayerElement>(),
|
|
109
81
|
});
|
|
110
82
|
|
|
111
|
-
const
|
|
112
|
-
HTMLDivElement,
|
|
113
|
-
DismissableLayerProps
|
|
114
|
-
>(
|
|
83
|
+
const DismissableLayer = forwardRef<HTMLDivElement, DismissableLayerProps>(
|
|
115
84
|
(
|
|
116
85
|
{
|
|
117
86
|
children,
|
|
@@ -123,6 +92,7 @@ const DismissableLayerInternal = forwardRef<
|
|
|
123
92
|
onPointerDownOutside,
|
|
124
93
|
safeZone,
|
|
125
94
|
asChild,
|
|
95
|
+
enabled = true,
|
|
126
96
|
...restProps
|
|
127
97
|
}: DismissableLayerProps,
|
|
128
98
|
forwardedRef,
|
|
@@ -194,73 +164,85 @@ const DismissableLayerInternal = forwardRef<
|
|
|
194
164
|
}
|
|
195
165
|
}
|
|
196
166
|
|
|
197
|
-
const pointerDownOutside = usePointerDownOutside(
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* We call these before letting `handleOutsideEvent` do its checks to give consumer a chance to preventDefault.
|
|
204
|
-
*/
|
|
205
|
-
onPointerDownOutside?.(event);
|
|
206
|
-
onInteractOutside?.(event);
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Add safeZone to prevent closing when interacting with trigger/anchor or its children.
|
|
210
|
-
*/
|
|
211
|
-
safeZone && handleOutsideEvent(event);
|
|
167
|
+
const pointerDownOutside = usePointerDownOutside(
|
|
168
|
+
(event) => {
|
|
169
|
+
if (!shouldEnablePointerEvents) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
212
172
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
173
|
+
/**
|
|
174
|
+
* We call these before letting `handleOutsideEvent` do its checks to give consumer a chance to preventDefault.
|
|
175
|
+
*/
|
|
176
|
+
onPointerDownOutside?.(event);
|
|
177
|
+
onInteractOutside?.(event);
|
|
217
178
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
onFocusOutside?.(event);
|
|
223
|
-
onInteractOutside?.(event);
|
|
179
|
+
/**
|
|
180
|
+
* Add safeZone to prevent closing when interacting with trigger/anchor or its children.
|
|
181
|
+
*/
|
|
182
|
+
safeZone && handleOutsideEvent(event);
|
|
224
183
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
184
|
+
if (!event.defaultPrevented && onDismiss) {
|
|
185
|
+
onDismiss();
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
ownerDoc,
|
|
189
|
+
enabled,
|
|
190
|
+
);
|
|
229
191
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
192
|
+
const focusOutside = useFocusOutside(
|
|
193
|
+
(event) => {
|
|
194
|
+
/**
|
|
195
|
+
* We call these before letting `handleOutsideEvent` do its checks to give consumer a chance to preventDefault.
|
|
196
|
+
*/
|
|
197
|
+
onFocusOutside?.(event);
|
|
198
|
+
onInteractOutside?.(event);
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Add safeZone to prevent closing when interacting with trigger/anchor or its children.
|
|
202
|
+
*/
|
|
203
|
+
safeZone && handleOutsideEvent(event);
|
|
204
|
+
|
|
205
|
+
if (!event.defaultPrevented && onDismiss) {
|
|
206
|
+
onDismiss();
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
ownerDoc,
|
|
210
|
+
enabled,
|
|
211
|
+
);
|
|
234
212
|
|
|
235
|
-
useEscapeKeydown(
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
213
|
+
useEscapeKeydown(
|
|
214
|
+
(event) => {
|
|
215
|
+
/**
|
|
216
|
+
* The deepest nested element will always be last in the descendants list.
|
|
217
|
+
* This allows us to only close the highest layer when pressing escape.
|
|
218
|
+
*/
|
|
219
|
+
const isHighestLayer = index === context.layers.size - 1;
|
|
220
|
+
if (!isHighestLayer) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
244
223
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
224
|
+
/**
|
|
225
|
+
* We call this before letting `handleOutsideEvent` do its checks to give consumer a chance to preventDefault based certain cases.
|
|
226
|
+
*/
|
|
227
|
+
onEscapeKeyDown?.(event);
|
|
228
|
+
/**
|
|
229
|
+
* `onEscapeKeyDown` is able to preventDefault the event, thus stopping call for `onDismiss`.
|
|
230
|
+
* We want to `preventDefault` the escape-event to avoid sideeffect from other elements on screen
|
|
231
|
+
*/
|
|
232
|
+
if (!event.defaultPrevented && onDismiss) {
|
|
233
|
+
event.preventDefault();
|
|
234
|
+
onDismiss();
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
ownerDoc,
|
|
238
|
+
enabled,
|
|
239
|
+
);
|
|
258
240
|
|
|
259
241
|
/**
|
|
260
242
|
* Handles registering `layers` and `layersWithOutsidePointerEventsDisabled`.
|
|
261
243
|
*/
|
|
262
244
|
useEffect(() => {
|
|
263
|
-
if (!node) {
|
|
245
|
+
if (!node || !enabled) {
|
|
264
246
|
return;
|
|
265
247
|
}
|
|
266
248
|
|
|
@@ -282,25 +264,32 @@ const DismissableLayerInternal = forwardRef<
|
|
|
282
264
|
ownerDoc.body.style.pointerEvents = originalBodyPointerEvents;
|
|
283
265
|
}
|
|
284
266
|
};
|
|
285
|
-
}, [node, disableOutsidePointerEvents, context, ownerDoc]);
|
|
267
|
+
}, [node, enabled, disableOutsidePointerEvents, context, ownerDoc]);
|
|
286
268
|
|
|
287
269
|
/**
|
|
288
270
|
* We purposefully prevent combining this effect with the `disableOutsidePointerEvents` effect
|
|
289
271
|
* because a change to `disableOutsidePointerEvents` would remove this layer from the stack
|
|
290
272
|
* and add it to the end again so the layering order wouldn't be creation order.
|
|
291
273
|
* We only want them to be removed from context stacks when unmounted.
|
|
274
|
+
*
|
|
275
|
+
* We depend on `enabled` to clean up when the layer is disabled.
|
|
292
276
|
*/
|
|
277
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: We need to clean up after enabled changes.
|
|
293
278
|
useEffect(() => {
|
|
294
279
|
return () => {
|
|
295
280
|
if (!node) {
|
|
296
281
|
return;
|
|
297
282
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
283
|
+
if (
|
|
284
|
+
context.layers.has(node) ||
|
|
285
|
+
context.layersWithOutsidePointerEventsDisabled.has(node)
|
|
286
|
+
) {
|
|
287
|
+
context.layers.delete(node);
|
|
288
|
+
context.layersWithOutsidePointerEventsDisabled.delete(node);
|
|
289
|
+
dispatchUpdate();
|
|
290
|
+
}
|
|
302
291
|
};
|
|
303
|
-
}, [node, context]);
|
|
292
|
+
}, [node, context, enabled]);
|
|
304
293
|
|
|
305
294
|
const parentBranchedLayer = useContext(BranchedLayerContext);
|
|
306
295
|
|
|
@@ -309,7 +298,12 @@ const DismissableLayerInternal = forwardRef<
|
|
|
309
298
|
* When this layer has a parent, we register it as a child of the parent.
|
|
310
299
|
*/
|
|
311
300
|
useEffect(() => {
|
|
312
|
-
if (
|
|
301
|
+
if (
|
|
302
|
+
!node ||
|
|
303
|
+
!enabled ||
|
|
304
|
+
!parentBranchedLayer ||
|
|
305
|
+
node === parentBranchedLayer
|
|
306
|
+
) {
|
|
313
307
|
return;
|
|
314
308
|
}
|
|
315
309
|
|
|
@@ -332,7 +326,7 @@ const DismissableLayerInternal = forwardRef<
|
|
|
332
326
|
|
|
333
327
|
dispatchUpdate();
|
|
334
328
|
};
|
|
335
|
-
}, [node, parentBranchedLayer, context]);
|
|
329
|
+
}, [node, enabled, parentBranchedLayer, context]);
|
|
336
330
|
|
|
337
331
|
/**
|
|
338
332
|
* Synchronizes layer state across all mounted `DismissableLayer` instances.
|
|
@@ -4,10 +4,15 @@ import { useCallbackRef } from "../../../util/hooks";
|
|
|
4
4
|
export function useEscapeKeydown(
|
|
5
5
|
callback?: (event: KeyboardEvent) => void,
|
|
6
6
|
ownerDocument: Document = globalThis?.document,
|
|
7
|
+
enabled: boolean = true,
|
|
7
8
|
) {
|
|
8
9
|
const onEscapeKeyDown = useCallbackRef(callback);
|
|
9
10
|
|
|
10
11
|
useEffect(() => {
|
|
12
|
+
if (!enabled) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
11
16
|
const handleKeyDown = (event: KeyboardEvent) => {
|
|
12
17
|
if (event.key === "Escape") {
|
|
13
18
|
onEscapeKeyDown(event);
|
|
@@ -15,7 +20,9 @@ export function useEscapeKeydown(
|
|
|
15
20
|
};
|
|
16
21
|
|
|
17
22
|
ownerDocument.addEventListener("keydown", handleKeyDown, true);
|
|
18
|
-
|
|
23
|
+
|
|
24
|
+
return () => {
|
|
19
25
|
ownerDocument.removeEventListener("keydown", handleKeyDown, true);
|
|
20
|
-
|
|
26
|
+
};
|
|
27
|
+
}, [onEscapeKeyDown, ownerDocument, enabled]);
|
|
21
28
|
}
|
|
@@ -12,11 +12,16 @@ import {
|
|
|
12
12
|
export function useFocusOutside(
|
|
13
13
|
callback?: (event: CustomFocusEvent) => void,
|
|
14
14
|
ownerDocument: Document = globalThis?.document,
|
|
15
|
+
enabled: boolean = true,
|
|
15
16
|
) {
|
|
16
17
|
const handleFocusOutside = useCallbackRef(callback) as EventListener;
|
|
17
18
|
const isFocusInsideReactTreeRef = useRef(false);
|
|
18
19
|
|
|
19
20
|
useEffect(() => {
|
|
21
|
+
if (!enabled) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
20
25
|
const handleFocus = (event: FocusEvent) => {
|
|
21
26
|
if (event.target && !isFocusInsideReactTreeRef.current) {
|
|
22
27
|
const eventDetail = { originalEvent: event };
|
|
@@ -38,8 +43,10 @@ export function useFocusOutside(
|
|
|
38
43
|
}
|
|
39
44
|
};
|
|
40
45
|
ownerDocument.addEventListener("focusin", handleFocus);
|
|
41
|
-
return () =>
|
|
42
|
-
|
|
46
|
+
return () => {
|
|
47
|
+
ownerDocument.removeEventListener("focusin", handleFocus);
|
|
48
|
+
};
|
|
49
|
+
}, [ownerDocument, handleFocusOutside, enabled]);
|
|
43
50
|
|
|
44
51
|
/**
|
|
45
52
|
* By directly setting isFocusInsideReactTreeRef on focus-events at the root of the "dismissable" element,
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
export function usePointerDownOutside(
|
|
17
17
|
callback?: (event: CustomPointerDownEvent) => void,
|
|
18
18
|
ownerDocument: Document = globalThis?.document,
|
|
19
|
+
enabled: boolean = true,
|
|
19
20
|
) {
|
|
20
21
|
const handlePointerDownOutside = useCallbackRef(callback) as EventListener;
|
|
21
22
|
const isPointerInsideReactTreeRef = useRef(false);
|
|
@@ -23,6 +24,10 @@ export function usePointerDownOutside(
|
|
|
23
24
|
const timeout = useTimeout();
|
|
24
25
|
|
|
25
26
|
useEffect(() => {
|
|
27
|
+
if (!enabled) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
26
31
|
const handlePointerDown = (event: PointerEvent) => {
|
|
27
32
|
/**
|
|
28
33
|
* The `DismisableLayer`-API is based on the ability to stop events from propagating and in the end calling `onDismiss`
|
|
@@ -87,7 +92,7 @@ export function usePointerDownOutside(
|
|
|
87
92
|
ownerDocument.removeEventListener("pointerdown", handlePointerDown);
|
|
88
93
|
ownerDocument.removeEventListener("click", handleClickRef.current);
|
|
89
94
|
};
|
|
90
|
-
}, [ownerDocument, handlePointerDownOutside, timeout]);
|
|
95
|
+
}, [ownerDocument, handlePointerDownOutside, timeout, enabled]);
|
|
91
96
|
|
|
92
97
|
return {
|
|
93
98
|
// ensures we check React component tree (not just DOM tree)
|
|
@@ -219,8 +219,12 @@ const TextareaAutosize = forwardRef<HTMLTextAreaElement, TextareaAutosizeProps>(
|
|
|
219
219
|
};
|
|
220
220
|
|
|
221
221
|
const mainStyle: React.CSSProperties = {
|
|
222
|
-
"--__ac-textarea-height": state.outerHeightStyle
|
|
223
|
-
|
|
222
|
+
"--__ac-textarea-height": state.outerHeightStyle
|
|
223
|
+
? state.outerHeightStyle + "px"
|
|
224
|
+
: "auto",
|
|
225
|
+
"--__axc-textarea-height": state.outerHeightStyle
|
|
226
|
+
? state.outerHeightStyle + "px"
|
|
227
|
+
: "auto",
|
|
224
228
|
// Need a large enough difference to allow scrolling.
|
|
225
229
|
// This prevents infinite rendering loop.
|
|
226
230
|
overflow:
|