@navikt/ds-react 8.6.0 → 8.7.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.
- package/cjs/data/drag-and-drop/item/DataDragAndDropItem.d.ts +27 -0
- package/cjs/data/drag-and-drop/item/DataDragAndDropItem.js +91 -0
- package/cjs/data/drag-and-drop/item/DataDragAndDropItem.js.map +1 -0
- package/cjs/data/drag-and-drop/root/DataDragAndDrop.context.d.ts +5 -0
- package/cjs/data/drag-and-drop/root/DataDragAndDrop.context.js +6 -0
- package/cjs/data/drag-and-drop/root/DataDragAndDrop.context.js.map +1 -0
- package/cjs/data/drag-and-drop/root/DataDragAndDropRoot.d.ts +24 -0
- package/cjs/data/drag-and-drop/root/DataDragAndDropRoot.js +111 -0
- package/cjs/data/drag-and-drop/root/DataDragAndDropRoot.js.map +1 -0
- package/cjs/data/table/helpers/table-keyboard.d.ts +1 -0
- package/cjs/data/table/helpers/table-keyboard.js +5 -3
- package/cjs/data/table/helpers/table-keyboard.js.map +1 -1
- package/cjs/data/table/root/DataTableRoot.context.d.ts +8 -0
- package/cjs/data/table/root/DataTableRoot.context.js +11 -0
- package/cjs/data/table/root/DataTableRoot.context.js.map +1 -0
- package/cjs/data/table/root/DataTableRoot.js +5 -3
- package/cjs/data/table/root/DataTableRoot.js.map +1 -1
- package/cjs/data/table/th/DataTableTh.d.ts +18 -2
- package/cjs/data/table/th/DataTableTh.js +45 -20
- package/cjs/data/table/th/DataTableTh.js.map +1 -1
- package/cjs/data/table/tr/DataTableTr.js +9 -2
- package/cjs/data/table/tr/DataTableTr.js.map +1 -1
- package/cjs/data/token-filter/AutoSuggest.d.ts +6 -2
- package/cjs/data/token-filter/AutoSuggest.js +46 -11
- package/cjs/data/token-filter/AutoSuggest.js.map +1 -1
- package/cjs/data/token-filter/TokenFilter.d.ts +5 -5
- package/cjs/data/token-filter/TokenFilter.js +105 -42
- package/cjs/data/token-filter/TokenFilter.js.map +1 -1
- package/cjs/data/token-filter/TokenFilter.types.d.ts +51 -33
- package/cjs/data/token-filter/helpers/generate-autocomplete-options.d.ts +2 -3
- package/cjs/data/token-filter/helpers/generate-autocomplete-options.js +11 -15
- package/cjs/data/token-filter/helpers/generate-autocomplete-options.js.map +1 -1
- package/cjs/data/token-filter/helpers/operators.d.ts +6 -6
- package/cjs/data/token-filter/helpers/operators.js +3 -4
- package/cjs/data/token-filter/helpers/operators.js.map +1 -1
- package/cjs/data/token-filter/helpers/parse-query-text.d.ts +2 -20
- package/cjs/data/token-filter/helpers/parse-query-text.js +1 -1
- package/cjs/data/token-filter/helpers/parse-query-text.js.map +1 -1
- package/cjs/data/token-filter/helpers/query-builder.d.ts +2 -2
- package/cjs/data/token-filter/helpers/query-builder.js.map +1 -1
- package/cjs/date/Date.Dialog.d.ts +5 -1
- package/cjs/date/Date.Dialog.js +6 -2
- package/cjs/date/Date.Dialog.js.map +1 -1
- package/cjs/date/datepicker/DatePicker.js +3 -2
- package/cjs/date/datepicker/DatePicker.js.map +1 -1
- package/cjs/date/datepicker/hooks/useDatepicker.js +5 -2
- package/cjs/date/datepicker/hooks/useDatepicker.js.map +1 -1
- package/cjs/date/datepicker/hooks/useRangeDatepicker.js +3 -1
- package/cjs/date/datepicker/hooks/useRangeDatepicker.js.map +1 -1
- package/cjs/date/datepicker/parts/DatePicker.Months.d.ts +2 -1
- package/cjs/date/datepicker/parts/DatePicker.Months.js +3 -3
- package/cjs/date/datepicker/parts/DatePicker.Months.js.map +1 -1
- package/cjs/date/datepicker/parts/DatePicker.RDP.d.ts +5 -1
- package/cjs/date/datepicker/parts/DatePicker.RDP.js +2 -2
- package/cjs/date/datepicker/parts/DatePicker.RDP.js.map +1 -1
- package/cjs/date/monthpicker/MonthPicker.js +3 -2
- package/cjs/date/monthpicker/MonthPicker.js.map +1 -1
- package/cjs/date/monthpicker/hooks/useMonthPicker.js +3 -1
- package/cjs/date/monthpicker/hooks/useMonthPicker.js.map +1 -1
- package/cjs/date/monthpicker/parts/MonthPicker.Caption.d.ts +4 -1
- package/cjs/date/monthpicker/parts/MonthPicker.Caption.js +3 -2
- package/cjs/date/monthpicker/parts/MonthPicker.Caption.js.map +1 -1
- package/cjs/dropdown/Toggle.js +5 -12
- package/cjs/dropdown/Toggle.js.map +1 -1
- package/cjs/form/combobox/Input/Input.js +1 -1
- package/cjs/form/combobox/Input/Input.js.map +1 -1
- package/cjs/inline-message/root/InlineMessage.js +2 -2
- package/cjs/inline-message/root/InlineMessage.js.map +1 -1
- package/cjs/provider/Provider.d.ts +2 -2
- package/cjs/tooltip/Tooltip.js +1 -3
- package/cjs/tooltip/Tooltip.js.map +1 -1
- package/cjs/utils/components/HighlightText/HighlightText.d.ts +8 -0
- package/cjs/utils/components/HighlightText/HighlightText.js +27 -0
- package/cjs/utils/components/HighlightText/HighlightText.js.map +1 -0
- package/cjs/utils/components/Listbox/group/ListboxGroup.d.ts +7 -0
- package/cjs/utils/components/Listbox/group/ListboxGroup.js +15 -0
- package/cjs/utils/components/Listbox/group/ListboxGroup.js.map +1 -0
- package/cjs/utils/components/Listbox/input-slot/ListboxInputSlot.d.ts +7 -0
- package/cjs/utils/components/Listbox/input-slot/ListboxInputSlot.js +15 -0
- package/cjs/utils/components/Listbox/input-slot/ListboxInputSlot.js.map +1 -0
- package/cjs/utils/components/Listbox/item/ListboxItem.d.ts +24 -0
- package/cjs/utils/components/Listbox/item/ListboxItem.js +33 -0
- package/cjs/utils/components/Listbox/item/ListboxItem.js.map +1 -0
- package/cjs/utils/components/Listbox/list/ListboxList.d.ts +8 -0
- package/cjs/utils/components/Listbox/list/ListboxList.js +32 -0
- package/cjs/utils/components/Listbox/list/ListboxList.js.map +1 -0
- package/cjs/utils/components/Listbox/root/ListboxRoot.d.ts +20 -0
- package/cjs/utils/components/Listbox/root/ListboxRoot.js +84 -0
- package/cjs/utils/components/Listbox/root/ListboxRoot.js.map +1 -0
- package/cjs/utils/components/Listbox/root/domHelpers.d.ts +3 -0
- package/cjs/utils/components/Listbox/root/domHelpers.js +53 -0
- package/cjs/utils/components/Listbox/root/domHelpers.js.map +1 -0
- package/cjs/utils/components/focus-boundary/FocusBoundary.js +9 -64
- package/cjs/utils/components/focus-boundary/FocusBoundary.js.map +1 -1
- package/cjs/utils/helpers/focus.d.ts +14 -0
- package/cjs/utils/helpers/focus.js +63 -0
- package/cjs/utils/helpers/focus.js.map +1 -0
- package/cjs/utils/hooks/useDeferredValue.d.ts +1 -0
- package/cjs/utils/hooks/useDeferredValue.js +14 -0
- package/cjs/utils/hooks/useDeferredValue.js.map +1 -0
- package/esm/data/drag-and-drop/item/DataDragAndDropItem.d.ts +27 -0
- package/esm/data/drag-and-drop/item/DataDragAndDropItem.js +55 -0
- package/esm/data/drag-and-drop/item/DataDragAndDropItem.js.map +1 -0
- package/esm/data/drag-and-drop/root/DataDragAndDrop.context.d.ts +5 -0
- package/esm/data/drag-and-drop/root/DataDragAndDrop.context.js +3 -0
- package/esm/data/drag-and-drop/root/DataDragAndDrop.context.js.map +1 -0
- package/esm/data/drag-and-drop/root/DataDragAndDropRoot.d.ts +24 -0
- package/esm/data/drag-and-drop/root/DataDragAndDropRoot.js +71 -0
- package/esm/data/drag-and-drop/root/DataDragAndDropRoot.js.map +1 -0
- package/esm/data/table/helpers/table-keyboard.d.ts +1 -0
- package/esm/data/table/helpers/table-keyboard.js +5 -3
- package/esm/data/table/helpers/table-keyboard.js.map +1 -1
- package/esm/data/table/root/DataTableRoot.context.d.ts +8 -0
- package/esm/data/table/root/DataTableRoot.context.js +7 -0
- package/esm/data/table/root/DataTableRoot.context.js.map +1 -0
- package/esm/data/table/root/DataTableRoot.js +5 -3
- package/esm/data/table/root/DataTableRoot.js.map +1 -1
- package/esm/data/table/th/DataTableTh.d.ts +18 -2
- package/esm/data/table/th/DataTableTh.js +46 -21
- package/esm/data/table/th/DataTableTh.js.map +1 -1
- package/esm/data/table/tr/DataTableTr.js +9 -2
- package/esm/data/table/tr/DataTableTr.js.map +1 -1
- package/esm/data/token-filter/AutoSuggest.d.ts +6 -2
- package/esm/data/token-filter/AutoSuggest.js +45 -13
- package/esm/data/token-filter/AutoSuggest.js.map +1 -1
- package/esm/data/token-filter/TokenFilter.d.ts +5 -5
- package/esm/data/token-filter/TokenFilter.js +105 -42
- package/esm/data/token-filter/TokenFilter.js.map +1 -1
- package/esm/data/token-filter/TokenFilter.types.d.ts +51 -33
- package/esm/data/token-filter/helpers/generate-autocomplete-options.d.ts +2 -3
- package/esm/data/token-filter/helpers/generate-autocomplete-options.js +11 -15
- package/esm/data/token-filter/helpers/generate-autocomplete-options.js.map +1 -1
- package/esm/data/token-filter/helpers/operators.d.ts +6 -6
- package/esm/data/token-filter/helpers/operators.js +3 -4
- package/esm/data/token-filter/helpers/operators.js.map +1 -1
- package/esm/data/token-filter/helpers/parse-query-text.d.ts +2 -20
- package/esm/data/token-filter/helpers/parse-query-text.js +1 -1
- package/esm/data/token-filter/helpers/parse-query-text.js.map +1 -1
- package/esm/data/token-filter/helpers/query-builder.d.ts +2 -2
- package/esm/data/token-filter/helpers/query-builder.js.map +1 -1
- package/esm/date/Date.Dialog.d.ts +5 -1
- package/esm/date/Date.Dialog.js +6 -2
- package/esm/date/Date.Dialog.js.map +1 -1
- package/esm/date/datepicker/DatePicker.js +3 -2
- package/esm/date/datepicker/DatePicker.js.map +1 -1
- package/esm/date/datepicker/hooks/useDatepicker.js +5 -2
- package/esm/date/datepicker/hooks/useDatepicker.js.map +1 -1
- package/esm/date/datepicker/hooks/useRangeDatepicker.js +3 -1
- package/esm/date/datepicker/hooks/useRangeDatepicker.js.map +1 -1
- package/esm/date/datepicker/parts/DatePicker.Months.d.ts +2 -1
- package/esm/date/datepicker/parts/DatePicker.Months.js +3 -3
- package/esm/date/datepicker/parts/DatePicker.Months.js.map +1 -1
- package/esm/date/datepicker/parts/DatePicker.RDP.d.ts +5 -1
- package/esm/date/datepicker/parts/DatePicker.RDP.js +2 -2
- package/esm/date/datepicker/parts/DatePicker.RDP.js.map +1 -1
- package/esm/date/monthpicker/MonthPicker.js +3 -2
- package/esm/date/monthpicker/MonthPicker.js.map +1 -1
- package/esm/date/monthpicker/hooks/useMonthPicker.js +3 -1
- package/esm/date/monthpicker/hooks/useMonthPicker.js.map +1 -1
- package/esm/date/monthpicker/parts/MonthPicker.Caption.d.ts +4 -1
- package/esm/date/monthpicker/parts/MonthPicker.Caption.js +3 -2
- package/esm/date/monthpicker/parts/MonthPicker.Caption.js.map +1 -1
- package/esm/dropdown/Toggle.js +5 -12
- package/esm/dropdown/Toggle.js.map +1 -1
- package/esm/form/combobox/Input/Input.js +1 -1
- package/esm/form/combobox/Input/Input.js.map +1 -1
- package/esm/inline-message/root/InlineMessage.js +3 -3
- package/esm/inline-message/root/InlineMessage.js.map +1 -1
- package/esm/provider/Provider.d.ts +2 -2
- package/esm/tooltip/Tooltip.js +1 -3
- package/esm/tooltip/Tooltip.js.map +1 -1
- package/esm/utils/components/HighlightText/HighlightText.d.ts +8 -0
- package/esm/utils/components/HighlightText/HighlightText.js +21 -0
- package/esm/utils/components/HighlightText/HighlightText.js.map +1 -0
- package/esm/utils/components/Listbox/group/ListboxGroup.d.ts +7 -0
- package/esm/utils/components/Listbox/group/ListboxGroup.js +10 -0
- package/esm/utils/components/Listbox/group/ListboxGroup.js.map +1 -0
- package/esm/utils/components/Listbox/input-slot/ListboxInputSlot.d.ts +7 -0
- package/esm/utils/components/Listbox/input-slot/ListboxInputSlot.js +9 -0
- package/esm/utils/components/Listbox/input-slot/ListboxInputSlot.js.map +1 -0
- package/esm/utils/components/Listbox/item/ListboxItem.d.ts +24 -0
- package/esm/utils/components/Listbox/item/ListboxItem.js +27 -0
- package/esm/utils/components/Listbox/item/ListboxItem.js.map +1 -0
- package/esm/utils/components/Listbox/list/ListboxList.d.ts +8 -0
- package/esm/utils/components/Listbox/list/ListboxList.js +27 -0
- package/esm/utils/components/Listbox/list/ListboxList.js.map +1 -0
- package/esm/utils/components/Listbox/root/ListboxRoot.d.ts +20 -0
- package/esm/utils/components/Listbox/root/ListboxRoot.js +79 -0
- package/esm/utils/components/Listbox/root/ListboxRoot.js.map +1 -0
- package/esm/utils/components/Listbox/root/domHelpers.d.ts +3 -0
- package/esm/utils/components/Listbox/root/domHelpers.js +50 -0
- package/esm/utils/components/Listbox/root/domHelpers.js.map +1 -0
- package/esm/utils/components/focus-boundary/FocusBoundary.js +8 -63
- package/esm/utils/components/focus-boundary/FocusBoundary.js.map +1 -1
- package/esm/utils/helpers/focus.d.ts +14 -0
- package/esm/utils/helpers/focus.js +60 -0
- package/esm/utils/helpers/focus.js.map +1 -0
- package/esm/utils/hooks/useDeferredValue.d.ts +1 -0
- package/esm/utils/hooks/useDeferredValue.js +7 -0
- package/esm/utils/hooks/useDeferredValue.js.map +1 -0
- package/package.json +7 -7
- package/src/data/drag-and-drop/item/DataDragAndDropItem.tsx +101 -0
- package/src/data/drag-and-drop/root/DataDragAndDrop.context.tsx +9 -0
- package/src/data/drag-and-drop/root/DataDragAndDropRoot.tsx +98 -0
- package/src/data/table/helpers/table-keyboard.ts +7 -3
- package/src/data/table/root/DataTableRoot.context.ts +13 -0
- package/src/data/table/root/DataTableRoot.tsx +16 -13
- package/src/data/table/th/DataTableTh.tsx +110 -54
- package/src/data/table/tr/DataTableTr.tsx +13 -2
- package/src/data/token-filter/AutoSuggest.tsx +142 -29
- package/src/data/token-filter/TokenFilter.tsx +174 -79
- package/src/data/token-filter/TokenFilter.types.ts +70 -42
- package/src/data/token-filter/helpers/generate-autocomplete-options.test.ts +97 -97
- package/src/data/token-filter/helpers/generate-autocomplete-options.ts +31 -38
- package/src/data/token-filter/helpers/operators.test.ts +29 -29
- package/src/data/token-filter/helpers/operators.ts +16 -16
- package/src/data/token-filter/helpers/parse-query-text.test.ts +37 -35
- package/src/data/token-filter/helpers/parse-query-text.ts +7 -26
- package/src/data/token-filter/helpers/query-builder.ts +2 -2
- package/src/date/Date.Dialog.tsx +15 -0
- package/src/date/datepicker/DatePicker.tsx +3 -0
- package/src/date/datepicker/hooks/useDatepicker.tsx +7 -2
- package/src/date/datepicker/hooks/useRangeDatepicker.tsx +5 -1
- package/src/date/datepicker/parts/DatePicker.Months.tsx +9 -1
- package/src/date/datepicker/parts/DatePicker.RDP.tsx +7 -1
- package/src/date/monthpicker/MonthPicker.tsx +3 -1
- package/src/date/monthpicker/hooks/useMonthPicker.tsx +5 -1
- package/src/date/monthpicker/parts/MonthPicker.Caption.tsx +20 -2
- package/src/dropdown/Toggle.tsx +6 -12
- package/src/form/combobox/Input/Input.tsx +2 -2
- package/src/inline-message/root/InlineMessage.tsx +5 -5
- package/src/provider/Provider.tsx +2 -2
- package/src/tooltip/Tooltip.tsx +1 -3
- package/src/utils/components/HighlightText/HighlightText.tsx +34 -0
- package/src/utils/components/Listbox/group/ListboxGroup.tsx +26 -0
- package/src/utils/components/Listbox/input-slot/ListboxInputSlot.tsx +22 -0
- package/src/utils/components/Listbox/item/ListboxItem.tsx +57 -0
- package/src/utils/components/Listbox/list/ListboxList.tsx +38 -0
- package/src/utils/components/Listbox/root/ListboxRoot.tsx +104 -0
- package/src/utils/components/Listbox/root/domHelpers.ts +59 -0
- package/src/utils/components/focus-boundary/FocusBoundary.tsx +8 -78
- package/src/utils/helpers/focus.ts +75 -0
- package/src/utils/hooks/useDeferredValue.ts +12 -0
- package/cjs/data/table/th/DataTableThSortHandle.d.ts +0 -6
- package/cjs/data/table/th/DataTableThSortHandle.js +0 -82
- package/cjs/data/table/th/DataTableThSortHandle.js.map +0 -1
- package/esm/data/table/th/DataTableThSortHandle.d.ts +0 -6
- package/esm/data/table/th/DataTableThSortHandle.js +0 -47
- package/esm/data/table/th/DataTableThSortHandle.js.map +0 -1
- package/src/data/table/th/DataTableThSortHandle.tsx +0 -67
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { DragDropProvider, DragOverlay } from "@dnd-kit/react";
|
|
2
|
+
import { isSortable } from "@dnd-kit/react/sortable";
|
|
3
|
+
import React, { forwardRef, isValidElement } from "react";
|
|
4
|
+
import { VStack } from "../../../primitives/stack";
|
|
5
|
+
import DataDragAndDropItem, {
|
|
6
|
+
DataDragAndDropItemProps,
|
|
7
|
+
} from "../item/DataDragAndDropItem";
|
|
8
|
+
import { DataDragAndDropContext } from "./DataDragAndDrop.context";
|
|
9
|
+
|
|
10
|
+
interface DataDragAndDropProps extends React.HTMLAttributes<HTMLTableElement> {
|
|
11
|
+
children: any[];
|
|
12
|
+
setItems: React.Dispatch<React.SetStateAction<any[]>>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface DataDragAndDropRootComponent extends React.ForwardRefExoticComponent<
|
|
16
|
+
DataDragAndDropProps & React.RefAttributes<HTMLTableElement>
|
|
17
|
+
> {
|
|
18
|
+
/**
|
|
19
|
+
* @see 🏷️ {@link DataDragAndDropItemProps}
|
|
20
|
+
* * @example
|
|
21
|
+
* ```jsx
|
|
22
|
+
* <DragAndDrop>
|
|
23
|
+
* <DragAndDrop.Item id="1" index={0}>
|
|
24
|
+
* ...
|
|
25
|
+
* </DragAndDrop.Item>
|
|
26
|
+
* </DragAndDrop>
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
Item: typeof DataDragAndDropItem;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const DataDragAndDrop = forwardRef<HTMLDivElement, DataDragAndDropProps>(
|
|
33
|
+
({ setItems, children, ...rest }, forwardedRef) => {
|
|
34
|
+
const [inputMethod, setInputMethod] = React.useState<
|
|
35
|
+
"mouse" | "keyboard" | null
|
|
36
|
+
>(null);
|
|
37
|
+
|
|
38
|
+
const setItemOrder = (initalIndex: number, targetIndex: number) => {
|
|
39
|
+
setItems((items) => {
|
|
40
|
+
const newItems = [...items];
|
|
41
|
+
const [movedItem] = newItems.splice(initalIndex, 1);
|
|
42
|
+
newItems.splice(targetIndex, 0, movedItem);
|
|
43
|
+
return newItems;
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<DataDragAndDropContext.Provider value={{ inputMethod }}>
|
|
49
|
+
<DragDropProvider
|
|
50
|
+
// TODO Look into overriding default keybinds, might eliminate context need
|
|
51
|
+
onBeforeDragStart={(event) =>
|
|
52
|
+
setInputMethod(
|
|
53
|
+
event.operation.activatorEvent?.type === "pointerdown"
|
|
54
|
+
? "mouse"
|
|
55
|
+
: "keyboard",
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
onDragOver={(event) => {
|
|
59
|
+
if (event.operation.activatorEvent?.type === "pointerdown") {
|
|
60
|
+
// Prevents items to rearrange while dragging with mouse, but allows keyboard dragging to work as intended
|
|
61
|
+
event.preventDefault();
|
|
62
|
+
}
|
|
63
|
+
}}
|
|
64
|
+
onDragEnd={(event) => {
|
|
65
|
+
if (event.operation.activatorEvent?.type === "pointerdown") {
|
|
66
|
+
const { source, target } = event.operation;
|
|
67
|
+
if (!isSortable(source) || !isSortable(target)) return;
|
|
68
|
+
setItemOrder(source.initialIndex, target.index);
|
|
69
|
+
}
|
|
70
|
+
}}
|
|
71
|
+
>
|
|
72
|
+
<VStack asChild gap="space-12">
|
|
73
|
+
<div {...rest} ref={forwardedRef}>
|
|
74
|
+
{children}
|
|
75
|
+
</div>
|
|
76
|
+
</VStack>
|
|
77
|
+
<DragOverlay>
|
|
78
|
+
{(source) => {
|
|
79
|
+
// Overlay not needed and causes glitching when using keyboard
|
|
80
|
+
if (inputMethod === "keyboard") return null;
|
|
81
|
+
if (!isSortable(source)) return null;
|
|
82
|
+
if (isValidElement(children[source.initialIndex])) {
|
|
83
|
+
return children[source.initialIndex];
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}}
|
|
87
|
+
</DragOverlay>
|
|
88
|
+
</DragDropProvider>
|
|
89
|
+
</DataDragAndDropContext.Provider>
|
|
90
|
+
);
|
|
91
|
+
},
|
|
92
|
+
) as DataDragAndDropRootComponent;
|
|
93
|
+
|
|
94
|
+
DataDragAndDrop.Item = DataDragAndDropItem;
|
|
95
|
+
|
|
96
|
+
export { DataDragAndDrop, DataDragAndDropItem };
|
|
97
|
+
export default DataDragAndDrop;
|
|
98
|
+
export type { DataDragAndDropItemProps, DataDragAndDropProps };
|
|
@@ -52,6 +52,7 @@ function getNavigationAction(event: KeyboardEvent): NavigationAction | null {
|
|
|
52
52
|
* - Select arrow down/up for opening popup
|
|
53
53
|
* - User is navigating inside multiline textarea
|
|
54
54
|
* - contenteditable attrb is in use
|
|
55
|
+
* - element has attribute data-block-keyboard-nav="true"
|
|
55
56
|
*/
|
|
56
57
|
function shouldBlockNavigation(event: KeyboardEvent): boolean {
|
|
57
58
|
const key = event.key;
|
|
@@ -68,9 +69,9 @@ function shouldBlockNavigation(event: KeyboardEvent): boolean {
|
|
|
68
69
|
return true;
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
/* If not any of these elements,
|
|
72
|
+
/* If not any of these elements, assume "safe" to navigate */
|
|
72
73
|
const editable = el.closest(
|
|
73
|
-
'input, textarea, select, [contenteditable="true"]',
|
|
74
|
+
'input, textarea, select, [contenteditable="true"], [data-block-keyboard-nav="true"]',
|
|
74
75
|
);
|
|
75
76
|
|
|
76
77
|
if (!editable) {
|
|
@@ -92,7 +93,10 @@ function shouldBlockNavigation(event: KeyboardEvent): boolean {
|
|
|
92
93
|
return false;
|
|
93
94
|
}
|
|
94
95
|
|
|
95
|
-
return
|
|
96
|
+
return (
|
|
97
|
+
editable.hasAttribute("contenteditable") ||
|
|
98
|
+
editable.hasAttribute("data-block-keyboard-nav")
|
|
99
|
+
);
|
|
96
100
|
}
|
|
97
101
|
|
|
98
102
|
function shouldBlockInputArrow(input: HTMLInputElement, key: string): boolean {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createStrictContext } from "../../../utils/helpers";
|
|
2
|
+
|
|
3
|
+
interface DataTableContextProps {
|
|
4
|
+
layout: "fixed" | "auto";
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const { Provider: DataTableContextProvider, useContext: useDataTableContext } =
|
|
8
|
+
createStrictContext<DataTableContextProps>({
|
|
9
|
+
name: "DataTableContext",
|
|
10
|
+
errorMessage: "useDataTableContext must be used within DataTable",
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export { DataTableContextProvider, useDataTableContext };
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
type DataTableTheadProps,
|
|
21
21
|
} from "../thead/DataTableThead";
|
|
22
22
|
import { DataTableTr, type DataTableTrProps } from "../tr/DataTableTr";
|
|
23
|
+
import { DataTableContextProvider } from "./DataTableRoot.context";
|
|
23
24
|
import { useTableKeyboardNav } from "./useTableKeyboardNav";
|
|
24
25
|
|
|
25
26
|
interface DataTableProps extends React.HTMLAttributes<HTMLTableElement> {
|
|
@@ -193,20 +194,22 @@ const DataTable = forwardRef<HTMLTableElement, DataTableProps>(
|
|
|
193
194
|
});
|
|
194
195
|
|
|
195
196
|
return (
|
|
196
|
-
<
|
|
197
|
-
<div className="aksel-data-
|
|
198
|
-
<
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
197
|
+
<DataTableContextProvider layout={layout}>
|
|
198
|
+
<div className="aksel-data-table__border-wrapper">
|
|
199
|
+
<div className="aksel-data-table__scroll-wrapper">
|
|
200
|
+
<table
|
|
201
|
+
{...rest}
|
|
202
|
+
ref={mergedRef}
|
|
203
|
+
className={cl("aksel-data-table", className)}
|
|
204
|
+
data-zebra-stripes={zebraStripes}
|
|
205
|
+
data-truncate-content={truncateContent}
|
|
206
|
+
data-density={rowDensity}
|
|
207
|
+
data-layout={layout}
|
|
208
|
+
tabIndex={tabIndex}
|
|
209
|
+
/>
|
|
210
|
+
</div>
|
|
208
211
|
</div>
|
|
209
|
-
</
|
|
212
|
+
</DataTableContextProvider>
|
|
210
213
|
);
|
|
211
214
|
},
|
|
212
215
|
) as DataTableRootComponent;
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import React, { forwardRef } from "react";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import {
|
|
3
|
+
ArrowsUpDownIcon,
|
|
4
|
+
CaretLeftCircleFillIcon,
|
|
5
|
+
CaretRightCircleFillIcon,
|
|
6
|
+
SortDownIcon,
|
|
7
|
+
SortUpIcon,
|
|
8
|
+
} from "@navikt/aksel-icons";
|
|
5
9
|
import { cl } from "../../../utils/helpers";
|
|
6
|
-
|
|
7
|
-
|
|
10
|
+
|
|
11
|
+
type SortDirection = "asc" | "desc" | "none";
|
|
8
12
|
|
|
9
13
|
interface DataTableThProps extends React.HTMLAttributes<HTMLTableCellElement> {
|
|
10
14
|
resizeHandler?: (
|
|
@@ -13,8 +17,22 @@ interface DataTableThProps extends React.HTMLAttributes<HTMLTableCellElement> {
|
|
|
13
17
|
| React.TouchEvent<HTMLButtonElement>,
|
|
14
18
|
) => void;
|
|
15
19
|
size?: number; // TODO: size should be required when resizeHandler is set
|
|
16
|
-
|
|
17
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Makes the column header sortable. The entire header cell content becomes
|
|
22
|
+
* a clickable button when true.
|
|
23
|
+
*/
|
|
24
|
+
sortable?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Current sort direction. Only relevant when `sortable` is true.
|
|
27
|
+
* Uses values matching the `aria-sort` attribute directly.
|
|
28
|
+
* @default "none"
|
|
29
|
+
*/
|
|
30
|
+
sortDirection?: SortDirection;
|
|
31
|
+
/**
|
|
32
|
+
* Called when the user clicks the sortable header.
|
|
33
|
+
* The consumer is responsible for determining and setting the next sort state.
|
|
34
|
+
*/
|
|
35
|
+
onSortClick?: (event: React.MouseEvent<HTMLElement>) => void;
|
|
18
36
|
render?: {
|
|
19
37
|
filterMenu?: {
|
|
20
38
|
title: string;
|
|
@@ -26,8 +44,15 @@ interface DataTableThProps extends React.HTMLAttributes<HTMLTableCellElement> {
|
|
|
26
44
|
*/
|
|
27
45
|
colSpan?: number;
|
|
28
46
|
rowSpan?: number;
|
|
47
|
+
keyboardResizingHandler?: (size: number) => void;
|
|
29
48
|
}
|
|
30
49
|
|
|
50
|
+
const SORT_ICON: Record<SortDirection, React.ElementType | null> = {
|
|
51
|
+
asc: SortUpIcon,
|
|
52
|
+
desc: SortDownIcon,
|
|
53
|
+
none: ArrowsUpDownIcon,
|
|
54
|
+
};
|
|
55
|
+
|
|
31
56
|
/**
|
|
32
57
|
* TODO:
|
|
33
58
|
* - Plan for pinning: Move it into "settings" dialog like here: https://cloudscape.design/examples/react/table.html
|
|
@@ -39,79 +64,110 @@ const DataTableTh = forwardRef<HTMLTableCellElement, DataTableThProps>(
|
|
|
39
64
|
children,
|
|
40
65
|
resizeHandler,
|
|
41
66
|
size,
|
|
42
|
-
|
|
43
|
-
|
|
67
|
+
sortable = false,
|
|
68
|
+
sortDirection = "none",
|
|
69
|
+
onSortClick,
|
|
44
70
|
style,
|
|
45
|
-
|
|
71
|
+
keyboardResizingHandler,
|
|
46
72
|
...rest
|
|
47
73
|
},
|
|
48
74
|
forwardedRef,
|
|
49
75
|
) => {
|
|
50
|
-
const
|
|
76
|
+
const [resizeHandlerActive, setResizeHandlerActive] = React.useState(false);
|
|
77
|
+
const [isOverflowing, setIsOverflowing] = React.useState(false);
|
|
78
|
+
const contentRef = React.useRef<HTMLDivElement>(null);
|
|
79
|
+
|
|
80
|
+
const keyDownHandler = (event: React.KeyboardEvent<HTMLButtonElement>) => {
|
|
81
|
+
if (keyboardResizingHandler) {
|
|
82
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
83
|
+
event.preventDefault();
|
|
84
|
+
setResizeHandlerActive((active) => !active);
|
|
85
|
+
} else if (
|
|
86
|
+
resizeHandlerActive &&
|
|
87
|
+
(event.key === "ArrowLeft" || event.key === "ArrowRight")
|
|
88
|
+
) {
|
|
89
|
+
event.preventDefault();
|
|
90
|
+
keyboardResizingHandler(event.key === "ArrowRight" ? 10 : -10);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const SortIcon = sortable ? SORT_ICON[sortDirection] : null;
|
|
51
96
|
|
|
52
97
|
return (
|
|
53
98
|
<th
|
|
54
99
|
{...rest}
|
|
55
100
|
ref={forwardedRef}
|
|
56
101
|
className={cl("aksel-data-table__th", className)}
|
|
102
|
+
data-sortable={sortable}
|
|
57
103
|
style={{ width: size, ...style }}
|
|
104
|
+
aria-sort={sortable ? getAriaSort(sortDirection) : undefined}
|
|
105
|
+
onPointerEnter={() => {
|
|
106
|
+
const el = contentRef.current;
|
|
107
|
+
setIsOverflowing(el ? el.scrollWidth > el.offsetWidth : false);
|
|
108
|
+
console.info("is overflowing", isOverflowing);
|
|
109
|
+
}}
|
|
110
|
+
onPointerLeave={() => setIsOverflowing(false)}
|
|
58
111
|
>
|
|
59
|
-
|
|
60
|
-
<
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
{/* TODO: Sorting texts do not handle different data-types now */}
|
|
71
|
-
{sortDirection && (
|
|
72
|
-
<ActionMenu.Group label="Sortering">
|
|
73
|
-
<ActionMenu.Item
|
|
74
|
-
onSelect={(event) => onSortChange?.("desc", event)}
|
|
75
|
-
icon={<SortUpIcon aria-hidden />}
|
|
76
|
-
>
|
|
77
|
-
{sortDirection === "desc" ? "Fjern sortering" : "A-Z"}
|
|
78
|
-
</ActionMenu.Item>
|
|
79
|
-
<ActionMenu.Item
|
|
80
|
-
onSelect={(event) => onSortChange?.("asc", event)}
|
|
81
|
-
icon={<SortDownIcon aria-hidden />}
|
|
82
|
-
>
|
|
83
|
-
{sortDirection === "asc" ? "Fjern sortering" : "Z-A"}
|
|
84
|
-
</ActionMenu.Item>
|
|
85
|
-
</ActionMenu.Group>
|
|
86
|
-
)}
|
|
87
|
-
{filterMenu && (
|
|
88
|
-
<ActionMenu.Group label="Filter">
|
|
89
|
-
<ActionMenu.Sub>
|
|
90
|
-
<ActionMenu.SubTrigger icon={<FunnelIcon aria-hidden />}>
|
|
91
|
-
{filterMenu.title}
|
|
92
|
-
</ActionMenu.SubTrigger>
|
|
93
|
-
<ActionMenu.SubContent>
|
|
94
|
-
{/* TODO: ActionMenu stops tab from working, so user cant tab "into" filter now even when wrapper has focus */}
|
|
95
|
-
{filterMenu.content}
|
|
96
|
-
</ActionMenu.SubContent>
|
|
97
|
-
</ActionMenu.Sub>
|
|
98
|
-
</ActionMenu.Group>
|
|
112
|
+
{sortable ? (
|
|
113
|
+
<button
|
|
114
|
+
className="aksel-data-table__th-sort-button"
|
|
115
|
+
onClick={sortable ? onSortClick : undefined}
|
|
116
|
+
>
|
|
117
|
+
{SortIcon && (
|
|
118
|
+
<SortIcon
|
|
119
|
+
aria-hidden
|
|
120
|
+
data-sort-direction={sortDirection}
|
|
121
|
+
className="aksel-data-table__th-sort-icon"
|
|
122
|
+
/>
|
|
99
123
|
)}
|
|
100
|
-
|
|
101
|
-
|
|
124
|
+
<div ref={contentRef} className="aksel-data-table__th-content">
|
|
125
|
+
{children}
|
|
126
|
+
</div>
|
|
127
|
+
</button>
|
|
128
|
+
) : (
|
|
129
|
+
<div ref={contentRef} className="aksel-data-table__th-content">
|
|
130
|
+
{children}
|
|
131
|
+
</div>
|
|
132
|
+
)}
|
|
102
133
|
|
|
103
134
|
{resizeHandler && (
|
|
104
135
|
<button
|
|
105
136
|
// TODO: Should probably not be a button since it doesn't have onClick
|
|
106
137
|
onMouseDown={resizeHandler}
|
|
107
138
|
onTouchStart={resizeHandler}
|
|
139
|
+
onBlur={() => setResizeHandlerActive(false)}
|
|
108
140
|
className="aksel-data-table__th-resize-handle"
|
|
109
|
-
|
|
141
|
+
data-active={resizeHandlerActive}
|
|
142
|
+
// TODO Very open to a better name for this
|
|
143
|
+
data-block-keyboard-nav
|
|
144
|
+
onKeyDown={keyDownHandler}
|
|
145
|
+
>
|
|
146
|
+
{resizeHandlerActive && (
|
|
147
|
+
<>
|
|
148
|
+
<span className="aksel-data-table__th-resize-handle-indicator aksel-data-table__th-resize-handle-indicator--start">
|
|
149
|
+
<CaretLeftCircleFillIcon aria-hidden fontSize="1.5rem" />
|
|
150
|
+
</span>
|
|
151
|
+
<span className="aksel-data-table__th-resize-handle-indicator aksel-data-table__th-resize-handle-indicator--end">
|
|
152
|
+
<CaretRightCircleFillIcon aria-hidden fontSize="1.5rem" />
|
|
153
|
+
</span>
|
|
154
|
+
</>
|
|
155
|
+
)}
|
|
156
|
+
</button>
|
|
110
157
|
)}
|
|
111
158
|
</th>
|
|
112
159
|
);
|
|
113
160
|
},
|
|
114
161
|
);
|
|
115
162
|
|
|
163
|
+
function getAriaSort(
|
|
164
|
+
sortDirection: SortDirection | undefined,
|
|
165
|
+
): "ascending" | "descending" | "none" | undefined {
|
|
166
|
+
if (sortDirection === "asc") return "ascending";
|
|
167
|
+
if (sortDirection === "desc") return "descending";
|
|
168
|
+
if (sortDirection === "none") return "none";
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
|
|
116
172
|
export { DataTableTh };
|
|
117
173
|
export type { DataTableThProps };
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import React, { forwardRef } from "react";
|
|
2
2
|
import { cl } from "../../../utils/helpers";
|
|
3
|
+
import { useDataTableContext } from "../root/DataTableRoot.context";
|
|
3
4
|
|
|
4
5
|
type DataTableTrProps = React.HTMLAttributes<HTMLTableRowElement> & {
|
|
5
6
|
selected?: boolean;
|
|
6
7
|
};
|
|
7
8
|
|
|
8
9
|
const DataTableTr = forwardRef<HTMLTableRowElement, DataTableTrProps>(
|
|
9
|
-
({ className, selected = false, ...rest }, forwardedRef) => {
|
|
10
|
+
({ className, children, selected = false, ...rest }, forwardedRef) => {
|
|
11
|
+
const rootContext = useDataTableContext();
|
|
12
|
+
|
|
13
|
+
const renderFillerCell = rootContext.layout === "fixed" && children;
|
|
14
|
+
|
|
10
15
|
return (
|
|
11
16
|
<tr
|
|
12
17
|
{...rest}
|
|
@@ -14,7 +19,13 @@ const DataTableTr = forwardRef<HTMLTableRowElement, DataTableTrProps>(
|
|
|
14
19
|
className={cl("aksel-data-table__tr", className, {
|
|
15
20
|
"aksel-data-table__tr--selected": selected,
|
|
16
21
|
})}
|
|
17
|
-
|
|
22
|
+
>
|
|
23
|
+
{children}
|
|
24
|
+
{renderFillerCell && (
|
|
25
|
+
/* TODO: Consider chaning between th and td based on context */
|
|
26
|
+
<div className="aksel-data-table__th aksel-data-table__filler-cell" />
|
|
27
|
+
)}
|
|
28
|
+
</tr>
|
|
18
29
|
);
|
|
19
30
|
},
|
|
20
31
|
);
|
|
@@ -1,47 +1,160 @@
|
|
|
1
|
-
import React, { forwardRef } from "react";
|
|
2
|
-
import {
|
|
1
|
+
import React, { forwardRef, useState } from "react";
|
|
2
|
+
import { Search } from "../../form/search";
|
|
3
3
|
import { VStack } from "../../primitives/stack";
|
|
4
|
-
import { Label } from "../../typography";
|
|
4
|
+
import { Detail, Label } from "../../typography";
|
|
5
|
+
import { ListboxGroup } from "../../utils/components/Listbox/group/ListboxGroup";
|
|
6
|
+
import { ListboxItem } from "../../utils/components/Listbox/item/ListboxItem";
|
|
7
|
+
import Listbox from "../../utils/components/Listbox/root/ListboxRoot";
|
|
8
|
+
import { DismissableLayer } from "../../utils/components/dismissablelayer/DismissableLayer";
|
|
9
|
+
import { Floating } from "../../utils/components/floating/Floating";
|
|
10
|
+
import { useMergeRefsN } from "../../utils/hooks";
|
|
5
11
|
import type { AutoCompleteOption, OptionGroup } from "./AutoSuggest.types";
|
|
6
12
|
|
|
7
13
|
interface AutoSuggestProps {
|
|
8
14
|
options: OptionGroup<AutoCompleteOption>[];
|
|
9
|
-
onSelect: (
|
|
15
|
+
onSelect: (option: AutoCompleteOption) => boolean;
|
|
10
16
|
className?: string;
|
|
17
|
+
value: string;
|
|
18
|
+
onChange: (newValue: string) => void;
|
|
19
|
+
open: boolean;
|
|
20
|
+
setOpen: (open: boolean) => void;
|
|
11
21
|
}
|
|
12
22
|
|
|
13
|
-
const AutoSuggest = forwardRef<
|
|
14
|
-
({ options, onSelect }, ref) => {
|
|
23
|
+
const AutoSuggest = forwardRef<HTMLInputElement, AutoSuggestProps>(
|
|
24
|
+
({ options, onSelect, value, onChange, open, setOpen }, ref) => {
|
|
25
|
+
const [virtuallyFocusedItemId, setVirtuallyFocusedItemId] = useState("");
|
|
26
|
+
|
|
27
|
+
const [inputRef, setInputRef] = useState<HTMLInputElement | null>(null);
|
|
28
|
+
|
|
29
|
+
/* Unsure why N version works, but not regular here */
|
|
30
|
+
const mergedRef = useMergeRefsN([setInputRef, ref]);
|
|
31
|
+
|
|
32
|
+
const handleClose = () => {
|
|
33
|
+
setOpen(false);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const handleChange = (newValue: string) => {
|
|
37
|
+
onChange(newValue);
|
|
38
|
+
setOpen(true);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const handleSelectOption = (option: AutoCompleteOption) => {
|
|
42
|
+
const createdNewToken = onSelect(option);
|
|
43
|
+
|
|
44
|
+
if (createdNewToken) {
|
|
45
|
+
inputRef?.focus();
|
|
46
|
+
setOpen(false);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<Floating>
|
|
52
|
+
<Listbox setVirtuallyFocusedItemId={setVirtuallyFocusedItemId}>
|
|
53
|
+
<Floating.Anchor>
|
|
54
|
+
<Listbox.InputSlot>
|
|
55
|
+
<Search
|
|
56
|
+
label="Tabellsøk"
|
|
57
|
+
variant="simple"
|
|
58
|
+
className="aksel-property-filter__input"
|
|
59
|
+
placeholder="Type to filter..."
|
|
60
|
+
ref={mergedRef}
|
|
61
|
+
value={value}
|
|
62
|
+
onChange={handleChange}
|
|
63
|
+
onClick={() => {
|
|
64
|
+
setOpen(true);
|
|
65
|
+
}}
|
|
66
|
+
onFocus={() => setOpen(true)}
|
|
67
|
+
/* onKeyDown={(e) => {
|
|
68
|
+
if (e.key === "Enter") {
|
|
69
|
+
createToken(filterText);
|
|
70
|
+
}
|
|
71
|
+
}} */
|
|
72
|
+
/>
|
|
73
|
+
</Listbox.InputSlot>
|
|
74
|
+
</Floating.Anchor>
|
|
75
|
+
{open && (
|
|
76
|
+
<AutoSuggestPopup
|
|
77
|
+
options={options}
|
|
78
|
+
onSelect={handleSelectOption}
|
|
79
|
+
focusedValue={virtuallyFocusedItemId}
|
|
80
|
+
setFocusedValue={setVirtuallyFocusedItemId}
|
|
81
|
+
onClose={handleClose}
|
|
82
|
+
safeZoneAnchor={inputRef}
|
|
83
|
+
/>
|
|
84
|
+
)}
|
|
85
|
+
</Listbox>
|
|
86
|
+
</Floating>
|
|
87
|
+
);
|
|
88
|
+
},
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
type AutoSuggestPopupProps = {
|
|
92
|
+
options: OptionGroup<AutoCompleteOption>[];
|
|
93
|
+
onSelect: (option: AutoCompleteOption) => void;
|
|
94
|
+
focusedValue: string;
|
|
95
|
+
setFocusedValue: (value: string) => void;
|
|
96
|
+
onClose: () => void;
|
|
97
|
+
safeZoneAnchor: HTMLInputElement | null;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const AutoSuggestPopup = forwardRef<HTMLDivElement, AutoSuggestPopupProps>(
|
|
101
|
+
(
|
|
102
|
+
{
|
|
103
|
+
options,
|
|
104
|
+
onSelect,
|
|
105
|
+
focusedValue,
|
|
106
|
+
setFocusedValue,
|
|
107
|
+
onClose,
|
|
108
|
+
safeZoneAnchor,
|
|
109
|
+
},
|
|
110
|
+
ref,
|
|
111
|
+
) => {
|
|
15
112
|
return (
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
113
|
+
<DismissableLayer
|
|
114
|
+
asChild
|
|
115
|
+
onDismiss={onClose}
|
|
116
|
+
safeZone={{ anchor: safeZoneAnchor }}
|
|
117
|
+
>
|
|
118
|
+
<Floating.Content
|
|
119
|
+
ref={ref}
|
|
120
|
+
align="start"
|
|
121
|
+
side="bottom"
|
|
122
|
+
fallbackPlacements={[]}
|
|
123
|
+
sideOffset={8}
|
|
124
|
+
className="aksel-property-filter__popup"
|
|
125
|
+
>
|
|
126
|
+
<div className="aksel-property-filter__popup-inner">
|
|
127
|
+
<Listbox.List setVirtuallyFocusedItemId={setFocusedValue}>
|
|
128
|
+
{options.map((group) => (
|
|
129
|
+
<ListboxGroup key={group.label} label={group.label}>
|
|
130
|
+
{group.options.map((item) => (
|
|
131
|
+
<ListboxItem
|
|
132
|
+
key={item.value}
|
|
133
|
+
id={item.value}
|
|
134
|
+
onClick={() => onSelect(item)}
|
|
135
|
+
hasVirtualFocus={focusedValue === item.value}
|
|
27
136
|
>
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
137
|
+
<VStack gap="space-0">
|
|
138
|
+
<Label as="div">{item.label}</Label>
|
|
139
|
+
{item.description && (
|
|
140
|
+
<Detail as="div">{item.description}</Detail>
|
|
141
|
+
)}
|
|
142
|
+
</VStack>
|
|
143
|
+
{/* {item.tags && item.tags.length > 0 && (
|
|
31
144
|
<div>
|
|
32
|
-
{
|
|
145
|
+
{item.tags.map((tag) => (
|
|
33
146
|
<span key={tag}>{tag}</span>
|
|
34
147
|
))}
|
|
35
148
|
</div>
|
|
36
|
-
)}
|
|
37
|
-
</
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
</
|
|
149
|
+
)} */}
|
|
150
|
+
</ListboxItem>
|
|
151
|
+
))}
|
|
152
|
+
</ListboxGroup>
|
|
153
|
+
))}
|
|
154
|
+
</Listbox.List>
|
|
42
155
|
</div>
|
|
43
|
-
|
|
44
|
-
</
|
|
156
|
+
</Floating.Content>
|
|
157
|
+
</DismissableLayer>
|
|
45
158
|
);
|
|
46
159
|
},
|
|
47
160
|
);
|