@digigov/ui 0.33.0 → 0.35.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +19 -1
  2. package/admin/Dropdown/index.js +34 -27
  3. package/core/Table/Table.stories.d.ts +1 -0
  4. package/core/Table/Table.stories.js +14 -0
  5. package/core/Table/__stories__/Stacked.d.ts +2 -0
  6. package/core/Table/__stories__/Stacked.js +42 -0
  7. package/core/Table/__stories__/WithSortFilters.js +34 -54
  8. package/core/Table/index.d.ts +11 -19
  9. package/core/Table/index.js +85 -174
  10. package/es/admin/Dropdown/index.js +34 -27
  11. package/es/core/Table/Table.stories.js +1 -0
  12. package/es/core/Table/__stories__/Stacked.js +29 -0
  13. package/es/core/Table/__stories__/WithSortFilters.js +34 -54
  14. package/es/core/Table/index.js +70 -154
  15. package/es/hooks/useSort.js +54 -0
  16. package/es/registry.js +2 -0
  17. package/esm/admin/Dropdown/index.js +34 -27
  18. package/esm/core/Table/Table.stories.js +1 -0
  19. package/esm/core/Table/__stories__/Stacked.js +29 -0
  20. package/esm/core/Table/__stories__/WithSortFilters.js +34 -54
  21. package/esm/core/Table/index.js +70 -154
  22. package/esm/hooks/useSort.js +54 -0
  23. package/esm/index.js +1 -1
  24. package/esm/registry.js +2 -0
  25. package/hooks/useSort.d.ts +9 -0
  26. package/hooks/useSort.js +67 -0
  27. package/package.json +3 -3
  28. package/registry.d.ts +1 -0
  29. package/registry.js +3 -0
  30. package/src/admin/Dropdown/index.tsx +79 -63
  31. package/src/core/Table/Table.stories.js +1 -0
  32. package/src/core/Table/__stories__/Stacked.tsx +59 -0
  33. package/src/core/Table/__stories__/WithSortFilters.tsx +34 -71
  34. package/src/core/Table/index.tsx +92 -175
  35. package/src/hooks/useSort.tsx +53 -0
  36. package/src/registry.js +2 -0
@@ -1,171 +1,88 @@
1
- import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
2
1
  import _extends from "@babel/runtime/helpers/extends";
3
- import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
4
- import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
5
- var _excluded = ["sortedAscDesc", "sortedField", "sortedDirectionValue", "headerItems", "sortedData", "children"];
6
- import React, { useCallback, useState, useRef } from 'react';
2
+ import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
3
+ var _excluded = ["labels", "disabled", "children", "direction", "onSort"];
4
+ import React, { useRef } from 'react';
7
5
  import Table from '@digigov/react-core/Table';
8
- import { useMemo } from 'react';
9
6
  import { Dropdown, DropdownButton, DropdownContent } from '@digigov/ui/admin/Dropdown';
10
7
  import { NavVertical } from '@digigov/ui/core/NavList/NavVertical';
11
8
  import { NavVerticalItem } from '@digigov/ui/core/NavList/NavVerticalItem';
12
9
  import { CaretIcon } from '@digigov/ui/core/SvgIcon';
13
- import TableHeadCellBase from '@digigov/react-core/TableHeadCell';
14
10
  import CaretContainer from '@digigov/ui/core/CaretContainer';
15
11
 
16
- var useSortableData = function useSortableData(items) {
17
- var _useState = useState(''),
18
- _useState2 = _slicedToArray(_useState, 2),
19
- field = _useState2[0],
20
- setField = _useState2[1];
21
-
22
- var _useState3 = useState(0),
23
- _useState4 = _slicedToArray(_useState3, 2),
24
- directionValue = _useState4[0],
25
- setDirectionValue = _useState4[1];
26
-
27
- var sortedItems = useMemo(function () {
28
- var sortableItems = _toConsumableArray(items);
29
-
30
- if (sortableItems.length === 0) {
31
- return;
32
- }
33
-
34
- if (field) {
35
- sortableItems.sort(function (a, b) {
36
- if (a[field] === null) return 1;
37
- if (b[field] === null) return -1;
38
- if (a[field] === null && b[field] === null) return 0;
39
- return a[field].toString().localeCompare(b[field].toString(), undefined, {
40
- numeric: true
41
- }) * (directionValue > 0 ? 1 : -1);
42
- });
43
- }
44
-
45
- return sortableItems;
46
- }, [items, directionValue, field]);
47
-
48
- var sortAscDesc = function sortAscDesc(item, value) {
49
- setDirectionValue(value);
50
- setField(item);
51
- };
52
-
53
- return {
54
- sortedData: sortedItems,
55
- sortedProps: {
56
- sortedData: sortedItems,
57
- sortedDirectionValue: directionValue,
58
- sortedField: field,
59
- sortedAscDesc: sortAscDesc
60
- }
61
- };
62
- };
63
-
64
- var TableHeadCellSort = /*#__PURE__*/React.forwardRef(function TableHeadCellSort(_ref, ref) {
65
- var props = _extends({}, _ref);
66
-
67
- return /*#__PURE__*/React.createElement(TableHeadCellSortBase, _extends({
68
- ref: ref
69
- }, props));
12
+ var _ref2 = /*#__PURE__*/React.createElement(CaretIcon, {
13
+ direction: 'up',
14
+ marginRight: 1,
15
+ marginTop: 1,
16
+ size: "m"
70
17
  });
71
- export var TableHeadCellSortBase = /*#__PURE__*/React.forwardRef(function TableHeadCellSortBase(_ref2, ref) {
72
- var sortedAscDesc = _ref2.sortedAscDesc,
73
- sortedField = _ref2.sortedField,
74
- sortedDirectionValue = _ref2.sortedDirectionValue,
75
- headerItems = _ref2.headerItems,
76
- sortedData = _ref2.sortedData,
77
- children = _ref2.children,
78
- props = _objectWithoutProperties(_ref2, _excluded);
79
-
80
- var innerRef = useRef();
81
-
82
- var _ref3 = headerItems || {},
83
- name = _ref3.name,
84
- sortLabels = _ref3.sortLabels;
85
18
 
86
- var _useState5 = useState(0),
87
- _useState6 = _slicedToArray(_useState5, 2),
88
- sortDirection = _useState6[0],
89
- setSortDirection = _useState6[1];
90
-
91
- var setSortAscDesc = useCallback(function (name, value) {
92
- if (sortedAscDesc) {
93
- if (sortedField !== name) {
94
- sortedAscDesc('', 0);
95
- setSortDirection(value);
96
- sortedAscDesc(name, value);
97
- } else {
98
- if (value !== sortDirection) {
99
- setSortDirection(value);
100
- sortedAscDesc(name, value);
101
- } else {
102
- setSortDirection(0);
103
- sortedAscDesc('', 0);
104
- }
105
- }
106
- }
107
- }, [sortedField, sortedDirectionValue, sortDirection]);
108
-
109
- var _onKeyDown = useCallback(function (e, name, value) {
110
- if (e.key === 'Enter' && innerRef.current.contains(e.target)) {
111
- if (innerRef.current.open) {
112
- setSortAscDesc(name, value);
113
- innerRef.current.open = false;
114
- }
115
- }
116
- }, [name, sortDirection]);
19
+ var _ref3 = /*#__PURE__*/React.createElement(CaretIcon, {
20
+ direction: 'down',
21
+ marginRight: 1,
22
+ marginTop: 1,
23
+ size: "m"
24
+ });
117
25
 
118
- var setDisabled = useCallback(function (sortedData) {
119
- return sortedData === undefined || sortedData.length === 0 ? true : false;
120
- }, [sortedData]);
121
- var setCaretColor = useCallback(function (value) {
122
- if (sortedField === name) {
123
- return sortedDirectionValue === value ? 'dark' : 'gray';
124
- } else {
125
- return 'gray';
126
- }
127
- }, [sortedDirectionValue, sortedField]);
128
- return /*#__PURE__*/React.createElement(TableHeadCellBase, _extends({}, props, {
129
- ref: ref
130
- }), /*#__PURE__*/React.createElement(Dropdown, {
131
- tabIndex: 0,
132
- disabled: setDisabled(sortedData),
133
- ref: innerRef
134
- }, /*#__PURE__*/React.createElement(DropdownButton, {
26
+ export var TableSortLabel = /*#__PURE__*/React.forwardRef(function TableSortLabel(_ref, _ref4) {
27
+ var labels = _ref.labels,
28
+ disabled = _ref.disabled,
29
+ children = _ref.children,
30
+ _ref$direction = _ref.direction,
31
+ direction = _ref$direction === void 0 ? 0 : _ref$direction,
32
+ onSort = _ref.onSort,
33
+ props = _objectWithoutProperties(_ref, _excluded);
34
+
35
+ // TODO: this is a workaround for the dropdown component
36
+ // https://itnext.io/reusing-the-ref-from-forwardref-with-react-hooks-4ce9df693dd
37
+ var dropdownRef = useRef(null);
38
+ var active = [-1, 1].includes(direction);
39
+ return /*#__PURE__*/React.createElement(Dropdown, _extends({
40
+ ref: function ref(el) {
41
+ dropdownRef.current = el;
42
+ typeof _ref4 === 'function' && _ref4(el);
43
+ },
44
+ disabled: disabled
45
+ }, props), /*#__PURE__*/React.createElement(DropdownButton, {
135
46
  variant: "link",
136
- underline: sortedField === name ? true : false
47
+ tabIndex: 0,
48
+ underline: active
137
49
  }, children, /*#__PURE__*/React.createElement(CaretContainer, {
138
50
  marginLeft: 1
139
- }, sortLabels && sortLabels.length > 0 && sortLabels.map(function (obj, index) {
140
- return /*#__PURE__*/React.createElement(CaretIcon, {
141
- key: index,
142
- direction: obj.value == 1 ? 'up' : 'down',
143
- size: "m",
144
- variant: setCaretColor(obj.value)
145
- });
146
- }))), /*#__PURE__*/React.createElement(DropdownContent, null, sortLabels && sortLabels.length > 0 && sortLabels.map(function (obj, index) {
147
- return /*#__PURE__*/React.createElement(NavVertical, {
148
- key: index
149
- }, /*#__PURE__*/React.createElement(NavVerticalItem, _extends({}, sortedField === name && sortedDirectionValue === obj.value && {
150
- active: true
151
- }, {
152
- tabIndex: 0,
153
- onClick: function onClick() {
154
- if (setSortAscDesc) {
155
- setSortAscDesc(name, obj.value);
156
- innerRef.current.open = false;
157
- }
158
- },
159
- onKeyDown: function onKeyDown(e) {
160
- _onKeyDown(e, name, obj.value);
51
+ }, /*#__PURE__*/React.createElement(CaretIcon, {
52
+ direction: 'up',
53
+ size: "m",
54
+ variant: direction === 1 ? 'dark' : 'gray'
55
+ }), /*#__PURE__*/React.createElement(CaretIcon, {
56
+ direction: 'down',
57
+ size: "m",
58
+ variant: direction === -1 ? 'dark' : 'gray'
59
+ }))), /*#__PURE__*/React.createElement(DropdownContent, null, /*#__PURE__*/React.createElement(NavVertical, null, /*#__PURE__*/React.createElement(NavVerticalItem, {
60
+ active: direction === 1,
61
+ tabIndex: 0,
62
+ onClick: function onClick() {
63
+ onSort(1);
64
+ dropdownRef.current && (dropdownRef.current.open = false);
65
+ },
66
+ onKeyDown: function onKeyDown(e) {
67
+ if (e.key === 'Enter') {
68
+ onSort(1);
69
+ dropdownRef.current && (dropdownRef.current.open = false);
161
70
  }
162
- }), /*#__PURE__*/React.createElement(CaretIcon, {
163
- direction: obj.value == 1 ? 'up' : 'down',
164
- marginRight: 1,
165
- marginTop: 1,
166
- size: "m"
167
- }), obj.label));
168
- }))));
71
+ }
72
+ }, _ref2, labels.asc), /*#__PURE__*/React.createElement(NavVerticalItem, {
73
+ active: direction === -1,
74
+ tabIndex: 0,
75
+ onClick: function onClick() {
76
+ onSort(-1);
77
+ dropdownRef.current && (dropdownRef.current.open = false);
78
+ },
79
+ onKeyDown: function onKeyDown(e) {
80
+ if (e.key === 'Enter') {
81
+ onSort(-1);
82
+ dropdownRef.current && (dropdownRef.current.open = false);
83
+ }
84
+ }
85
+ }, _ref3, labels.desc))));
169
86
  });
170
87
  export * from '@digigov/react-core/TableContainer';
171
88
  export * from '@digigov/react-core/Table';
@@ -177,5 +94,4 @@ export * from '@digigov/react-core/TableHeadCell';
177
94
  export * from '@digigov/react-core/TableRow';
178
95
  export * from '@digigov/react-core/TableNoDataRow';
179
96
  export * from '@digigov/ui/core/Table/TableFloatingScroll';
180
- export { TableHeadCellSort, useSortableData };
181
97
  export default Table;
@@ -0,0 +1,54 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
+ import { useState } from 'react';
4
+ import { useMemo } from 'react';
5
+ export var useSort = function useSort(data) {
6
+ var _useState = useState(''),
7
+ _useState2 = _slicedToArray(_useState, 2),
8
+ sortDataBy = _useState2[0],
9
+ setSortDataBy = _useState2[1];
10
+
11
+ var _useState3 = useState(0),
12
+ _useState4 = _slicedToArray(_useState3, 2),
13
+ direction = _useState4[0],
14
+ setDirection = _useState4[1];
15
+
16
+ var sortedItems = useMemo(function () {
17
+ var sortableItems = _toConsumableArray(data);
18
+
19
+ if (sortableItems.length === 0) {
20
+ return [];
21
+ }
22
+
23
+ if (sortDataBy) {
24
+ sortableItems.sort(function (a, b) {
25
+ if (a[sortDataBy] === null) return 1;
26
+ if (b[sortDataBy] === null) return -1;
27
+ if (a[sortDataBy] === null && b[sortDataBy] === null) return 0;
28
+ return a[sortDataBy].toString().localeCompare(b[sortDataBy].toString(), undefined, {
29
+ numeric: true
30
+ }) * (direction > 0 ? 1 : -1);
31
+ });
32
+ }
33
+
34
+ return sortableItems;
35
+ }, [data, direction, sortDataBy]);
36
+
37
+ var setSortedField = function setSortedField(item, value) {
38
+ if (item === sortDataBy && value === direction) {
39
+ setDirection(0);
40
+ setSortDataBy('');
41
+ return;
42
+ }
43
+
44
+ setDirection(value);
45
+ setSortDataBy(item);
46
+ };
47
+
48
+ return {
49
+ sortedData: sortedItems,
50
+ setSortedField: setSortedField,
51
+ field: sortDataBy,
52
+ direction: direction
53
+ };
54
+ };
package/esm/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /** @license Digigov v0.33.0
1
+ /** @license Digigov v0.35.0
2
2
  *
3
3
  * This source code is licensed under the BSD-2-Clause license found in the
4
4
  * LICENSE file in the root directory of this source tree.
package/esm/registry.js CHANGED
@@ -161,6 +161,7 @@ import * as _digigov_ui_hooks_useLineHeight from '@digigov/ui/hooks/useLineHeigh
161
161
  import * as _digigov_ui_hooks_useNavList from '@digigov/ui/hooks/useNavList';
162
162
  import * as _digigov_ui_hooks_useOutdatedBrowserCheck from '@digigov/ui/hooks/useOutdatedBrowserCheck';
163
163
  import * as _digigov_ui_hooks_useSearch from '@digigov/ui/hooks/useSearch';
164
+ import * as _digigov_ui_hooks_useSort from '@digigov/ui/hooks/useSort';
164
165
  import * as _digigov_ui_hooks_useTheme from '@digigov/ui/hooks/useTheme';
165
166
  import * as _digigov_ui_hooks_useTogglableNav from '@digigov/ui/hooks/useTogglableNav';
166
167
  import * as _digigov_ui_hooks_useTogglableTab from '@digigov/ui/hooks/useTogglableTab';
@@ -374,6 +375,7 @@ export default {
374
375
  '@digigov/ui/hooks/useNavList': lazyImport(_digigov_ui_hooks_useNavList),
375
376
  '@digigov/ui/hooks/useOutdatedBrowserCheck': lazyImport(_digigov_ui_hooks_useOutdatedBrowserCheck),
376
377
  '@digigov/ui/hooks/useSearch': lazyImport(_digigov_ui_hooks_useSearch),
378
+ '@digigov/ui/hooks/useSort': lazyImport(_digigov_ui_hooks_useSort),
377
379
  '@digigov/ui/hooks/useTheme': lazyImport(_digigov_ui_hooks_useTheme),
378
380
  '@digigov/ui/hooks/useTogglableNav': lazyImport(_digigov_ui_hooks_useTogglableNav),
379
381
  '@digigov/ui/hooks/useTogglableTab': lazyImport(_digigov_ui_hooks_useTogglableTab),
@@ -0,0 +1,9 @@
1
+ import { SortDirection } from '@digigov/ui/core/Table';
2
+ export interface UseSortResult {
3
+ sortedData: any[];
4
+ setSortedField: (item: string, value: SortDirection) => void;
5
+ field: string;
6
+ direction: SortDirection;
7
+ }
8
+ export declare type SortData = Record<string, any>[];
9
+ export declare const useSort: (data: SortData) => UseSortResult;
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.useSort = void 0;
9
+
10
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
11
+
12
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
13
+
14
+ var _react = require("react");
15
+
16
+ var useSort = function useSort(data) {
17
+ var _useState = (0, _react.useState)(''),
18
+ _useState2 = (0, _slicedToArray2["default"])(_useState, 2),
19
+ sortDataBy = _useState2[0],
20
+ setSortDataBy = _useState2[1];
21
+
22
+ var _useState3 = (0, _react.useState)(0),
23
+ _useState4 = (0, _slicedToArray2["default"])(_useState3, 2),
24
+ direction = _useState4[0],
25
+ setDirection = _useState4[1];
26
+
27
+ var sortedItems = (0, _react.useMemo)(function () {
28
+ var sortableItems = (0, _toConsumableArray2["default"])(data);
29
+
30
+ if (sortableItems.length === 0) {
31
+ return [];
32
+ }
33
+
34
+ if (sortDataBy) {
35
+ sortableItems.sort(function (a, b) {
36
+ if (a[sortDataBy] === null) return 1;
37
+ if (b[sortDataBy] === null) return -1;
38
+ if (a[sortDataBy] === null && b[sortDataBy] === null) return 0;
39
+ return a[sortDataBy].toString().localeCompare(b[sortDataBy].toString(), undefined, {
40
+ numeric: true
41
+ }) * (direction > 0 ? 1 : -1);
42
+ });
43
+ }
44
+
45
+ return sortableItems;
46
+ }, [data, direction, sortDataBy]);
47
+
48
+ var setSortedField = function setSortedField(item, value) {
49
+ if (item === sortDataBy && value === direction) {
50
+ setDirection(0);
51
+ setSortDataBy('');
52
+ return;
53
+ }
54
+
55
+ setDirection(value);
56
+ setSortDataBy(item);
57
+ };
58
+
59
+ return {
60
+ sortedData: sortedItems,
61
+ setSortedField: setSortedField,
62
+ field: sortDataBy,
63
+ direction: direction
64
+ };
65
+ };
66
+
67
+ exports.useSort = useSort;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digigov/ui",
3
- "version": "0.33.0",
3
+ "version": "0.35.0",
4
4
  "description": "@digigov reusable components toolkit",
5
5
  "main": "./index.js",
6
6
  "module": "./esm/index.js",
@@ -20,8 +20,8 @@
20
20
  "clsx": "1.1.1",
21
21
  "react": "^16.8.0 || ^17.0.0",
22
22
  "react-dom": "^16.8.0 || ^17.0.0",
23
- "@digigov/react-core": "0.24.0",
24
- "@digigov/react-extensions": "0.22.0"
23
+ "@digigov/react-core": "0.25.1",
24
+ "@digigov/react-extensions": "0.23.0"
25
25
  },
26
26
  "gitHead": "c903a46306f77f55ad7fc4d2e274006f39a6c871",
27
27
  "private": false,
package/registry.d.ts CHANGED
@@ -162,6 +162,7 @@ declare var _default: {
162
162
  '@digigov/ui/hooks/useNavList': {};
163
163
  '@digigov/ui/hooks/useOutdatedBrowserCheck': {};
164
164
  '@digigov/ui/hooks/useSearch': {};
165
+ '@digigov/ui/hooks/useSort': {};
165
166
  '@digigov/ui/hooks/useTheme': {};
166
167
  '@digigov/ui/hooks/useTogglableNav': {};
167
168
  '@digigov/ui/hooks/useTogglableTab': {};
package/registry.js CHANGED
@@ -333,6 +333,8 @@ var _digigov_ui_hooks_useOutdatedBrowserCheck = _interopRequireWildcard(require(
333
333
 
334
334
  var _digigov_ui_hooks_useSearch = _interopRequireWildcard(require("@digigov/ui/hooks/useSearch"));
335
335
 
336
+ var _digigov_ui_hooks_useSort = _interopRequireWildcard(require("@digigov/ui/hooks/useSort"));
337
+
336
338
  var _digigov_ui_hooks_useTheme = _interopRequireWildcard(require("@digigov/ui/hooks/useTheme"));
337
339
 
338
340
  var _digigov_ui_hooks_useTogglableNav = _interopRequireWildcard(require("@digigov/ui/hooks/useTogglableNav"));
@@ -689,6 +691,7 @@ var _default = {
689
691
  '@digigov/ui/hooks/useNavList': lazyImport(_digigov_ui_hooks_useNavList),
690
692
  '@digigov/ui/hooks/useOutdatedBrowserCheck': lazyImport(_digigov_ui_hooks_useOutdatedBrowserCheck),
691
693
  '@digigov/ui/hooks/useSearch': lazyImport(_digigov_ui_hooks_useSearch),
694
+ '@digigov/ui/hooks/useSort': lazyImport(_digigov_ui_hooks_useSort),
692
695
  '@digigov/ui/hooks/useTheme': lazyImport(_digigov_ui_hooks_useTheme),
693
696
  '@digigov/ui/hooks/useTogglableNav': lazyImport(_digigov_ui_hooks_useTogglableNav),
694
697
  '@digigov/ui/hooks/useTogglableTab': lazyImport(_digigov_ui_hooks_useTogglableTab),
@@ -22,75 +22,91 @@ export interface DropdownProps extends DropdownBaseProps {
22
22
  * Dropdown component is used for showing more options with a button.
23
23
  */
24
24
 
25
- export const Dropdown = React.forwardRef(function Dropdown(
26
- { closeBehaviour = 'clickOutside', float = false, ...props }: DropdownProps,
27
- ref: React.MutableRefObject<HTMLDetailsElement>
28
- ): React.ReactElement {
29
- const innerRef =
30
- ref || (useRef() as React.MutableRefObject<HTMLDetailsElement>);
31
- useEffect(() => {
32
- const keyDownHandler = (event) => {
33
- if (event.key === 'Escape') {
34
- innerRef.current.open = false;
35
- event.preventDefault();
36
- }
37
- };
38
- const handleClickOutside = (event) => {
39
- if (innerRef.current && !innerRef.current.contains(event.target)) {
40
- innerRef.current.open = false;
41
- }
42
- };
25
+ export const Dropdown = React.forwardRef<HTMLDetailsElement, DropdownProps>(
26
+ function Dropdown(
27
+ { closeBehaviour = 'clickOutside', float = false, ...props },
28
+ ref
29
+ ) {
30
+ const innerRef = useRef<HTMLDetailsElement | null>(null);
43
31
 
44
- if (closeBehaviour === 'clickOutside') {
45
- document.addEventListener('click', handleClickOutside, true);
46
- }
47
- document.addEventListener('keydown', keyDownHandler);
48
- const toggleFloat = () => {
49
- const tbody = innerRef.current.closest('tbody') as HTMLElement;
50
- const parentElement = innerRef.current?.parentElement as HTMLElement;
51
- if (innerRef.current.open) {
52
- tbody.style.position = 'static';
53
- const rect = innerRef.current?.getBoundingClientRect();
54
- const parentRect = parentElement.getBoundingClientRect();
55
- innerRef.current.style.position = 'static';
56
- // arbitrary spacing of 12 pixels because CSS
57
- const top = rect.top + window.pageYOffset;
58
- const left = rect.left + window.pageXOffset;
59
- parentElement.style.height = `${parentRect.height}px`;
60
- parentElement.style.width = `${parentRect.width}px`;
61
- innerRef.current.style.top = `${top}px`;
62
- innerRef.current.style.left = `${left}px`;
63
- innerRef.current.style.position = `absolute`;
64
- innerRef.current.style.display = `block`;
65
- innerRef.current.style.background = 'white';
66
- } else {
67
- tbody.style.position = 'relative';
68
- parentElement.style.height = '';
69
- parentElement.style.width = '';
70
- innerRef.current.style.top = `0`;
71
- innerRef.current.style.left = `0`;
72
- innerRef.current.style.position = `relative`;
73
- innerRef.current.style.display = `table-cell`;
74
- innerRef.current.style.background = 'transparent';
32
+ useEffect(() => {
33
+ const element = innerRef.current;
34
+ if (!element) {
35
+ return;
75
36
  }
76
- };
77
- if (float) {
78
- innerRef.current.addEventListener('toggle', toggleFloat);
79
- }
80
- return () => {
37
+ const keyDownHandler = (event) => {
38
+ if (event.key === 'Escape') {
39
+ element.open = false;
40
+ event.preventDefault();
41
+ }
42
+ };
43
+ const handleClickOutside = (event) => {
44
+ if (element && !element.contains(event.target)) {
45
+ element.open = false;
46
+ }
47
+ };
48
+
81
49
  if (closeBehaviour === 'clickOutside') {
82
- document.removeEventListener('click', handleClickOutside, true);
50
+ document.addEventListener('click', handleClickOutside, true);
83
51
  }
52
+ document.addEventListener('keydown', keyDownHandler);
53
+ const toggleFloat = () => {
54
+ const tbody = element.closest('tbody') as HTMLElement;
55
+ const parentElement = element?.parentElement as HTMLElement;
56
+ if (element.open) {
57
+ tbody.style.position = 'static';
58
+ const rect = element?.getBoundingClientRect();
59
+ const parentRect = parentElement.getBoundingClientRect();
60
+ element.style.position = 'static';
61
+ // arbitrary spacing of 12 pixels because CSS
62
+ const top = rect.top + window.pageYOffset;
63
+ const left = rect.left + window.pageXOffset;
64
+ parentElement.style.height = `${parentRect.height}px`;
65
+ parentElement.style.width = `${parentRect.width}px`;
66
+ element.style.top = `${top}px`;
67
+ element.style.left = `${left}px`;
68
+ element.style.position = `absolute`;
69
+ element.style.display = `block`;
70
+ element.style.background = 'white';
71
+ } else {
72
+ tbody.style.position = 'relative';
73
+ parentElement.style.height = '';
74
+ parentElement.style.width = '';
75
+ element.style.top = `0`;
76
+ element.style.left = `0`;
77
+ element.style.position = `relative`;
78
+ element.style.display = `table-cell`;
79
+ // element.style.background = 'transparent';
80
+ }
81
+ };
84
82
  if (float) {
85
- innerRef.current.removeEventListener('toggle', toggleFloat);
83
+ element.addEventListener('toggle', toggleFloat);
86
84
  }
87
- document.removeEventListener('keydown', keyDownHandler);
88
- };
89
- }, []);
90
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
91
- // @ts-ignore
92
- return <DropdownBase ref={innerRef} {...props} />;
93
- });
85
+ return () => {
86
+ if (closeBehaviour === 'clickOutside') {
87
+ document.removeEventListener('click', handleClickOutside, true);
88
+ }
89
+ if (float) {
90
+ element.removeEventListener('toggle', toggleFloat);
91
+ }
92
+ document.removeEventListener('keydown', keyDownHandler);
93
+ };
94
+ }, []);
95
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
96
+ // @ts-ignore
97
+ return (
98
+ <DropdownBase
99
+ ref={(el) => {
100
+ innerRef.current = el;
101
+ if (typeof ref === 'function') {
102
+ ref(el);
103
+ }
104
+ }}
105
+ {...props}
106
+ />
107
+ );
108
+ }
109
+ );
94
110
 
95
111
  export { DropdownBase };
96
112
  export default Dropdown;
@@ -16,6 +16,7 @@ export * from './__stories__/VerticalHeaders';
16
16
  export * from './__stories__/ZebraProp';
17
17
  export * from './__stories__/NumericDataType';
18
18
  export * from './__stories__/VerticalBorders';
19
+ export * from './__stories__/Stacked';
19
20
  export * from './__stories__/DarkVariant';
20
21
  export * from './__stories__/DarkVariantWithVerticalHeaders';
21
22
  export * from './__stories__/WithLoader';