@dt-dds/react-dropdown 1.0.0-beta.77 → 1.0.0-beta.79

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/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # @dt-ui/react-dropdown
2
2
 
3
+ ## 1.0.0-beta.79
4
+
5
+ ### Patch Changes
6
+
7
+ - fix(config): update ESLint, TS, and Storybook config
8
+ - fix(icon-button): add missing @dt-dds/react-icon devDependency
9
+ - Updated dependencies
10
+ - Updated dependencies
11
+ - Updated dependencies [223664b]
12
+ - @dt-dds/react-core@1.0.0-beta.52
13
+ - @dt-dds/react-icon@1.0.0-beta.55
14
+ - @dt-dds/react-icon-button@1.0.0-beta.21
15
+ - @dt-dds/react-typography@1.0.0-beta.43
16
+ - @dt-dds/themes@1.0.0-beta.10
17
+ - @dt-dds/react-box@1.0.0-beta.58
18
+
19
+ ## 1.0.0-beta.78
20
+
21
+ ### Minor Changes
22
+
23
+ - feat: add accessibility to Dropdown
24
+
25
+ ### Patch Changes
26
+
27
+ - refactor: fix sonar issues on Dropdown and Select
28
+ - Updated dependencies [223664b]
29
+ - @dt-dds/react-box@1.0.0-beta.57
30
+
3
31
  ## 1.0.0-beta.77
4
32
 
5
33
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -1,15 +1,7 @@
1
1
  import { CustomTheme } from '@dt-dds/themes';
2
- import { BaseProps } from '@dt-dds/react-core';
3
2
  import * as react from 'react';
4
- import react__default, { RefObject } from 'react';
5
-
6
- interface DropdownOptionProps extends BaseProps, react__default.LiHTMLAttributes<HTMLLIElement> {
7
- isDisabled?: boolean;
8
- isSelected?: boolean;
9
- isHighlighted?: boolean;
10
- isMulti?: boolean;
11
- }
12
- declare const DropdownOption: react__default.ForwardRefExoticComponent<DropdownOptionProps & react__default.RefAttributes<HTMLLIElement>>;
3
+ import { RefObject, ElementType, ComponentPropsWithoutRef, Ref, ReactElement } from 'react';
4
+ import { BaseProps } from '@dt-dds/react-core';
13
5
 
14
6
  type DropdownVariant = 'outlined' | 'bottom-line';
15
7
  type DropdownFill = 'default' | 'contrast' | 'light';
@@ -24,14 +16,38 @@ interface DropdownProps extends BaseProps {
24
16
  onClose?: () => void;
25
17
  as?: keyof JSX.IntrinsicElements;
26
18
  placement?: DropdownPlacement;
19
+ isFocusable?: boolean;
27
20
  }
28
21
  declare const Dropdown: react.ForwardRefExoticComponent<DropdownProps & react.RefAttributes<HTMLElement>> & {
29
- Option: react.ForwardRefExoticComponent<DropdownOptionProps & react.RefAttributes<HTMLLIElement>>;
22
+ Option: <E extends react.ElementType = "li">(props: (BaseProps & {
23
+ isDisabled?: boolean;
24
+ isSelected?: boolean;
25
+ isHighlighted?: boolean;
26
+ isMulti?: boolean;
27
+ } & {
28
+ as?: E | undefined;
29
+ } & react.PropsWithoutRef<react.ComponentProps<E>>) & {
30
+ ref?: react.Ref<Element>;
31
+ }) => react.ReactElement | null;
32
+ };
33
+
34
+ type DropdownOptionBaseProps = BaseProps & {
35
+ isDisabled?: boolean;
36
+ isSelected?: boolean;
37
+ isHighlighted?: boolean;
38
+ isMulti?: boolean;
30
39
  };
40
+ type DropdownOptionProps<E extends ElementType = 'li'> = DropdownOptionBaseProps & {
41
+ as?: E;
42
+ } & ComponentPropsWithoutRef<E>;
43
+ type DropdownOptionComponent = <E extends ElementType = 'li'>(props: DropdownOptionProps<E> & {
44
+ ref?: Ref<Element>;
45
+ }) => ReactElement | null;
46
+ declare const DropdownOption: DropdownOptionComponent;
31
47
 
32
48
  declare module '@emotion/react' {
33
49
  interface Theme extends CustomTheme {
34
50
  }
35
51
  }
36
52
 
37
- export { Dropdown, type DropdownFill, DropdownOption, type DropdownOptionProps, type DropdownPlacement, type DropdownProps, type DropdownVariant };
53
+ export { Dropdown, type DropdownFill, DropdownOption, type DropdownPlacement, type DropdownProps, type DropdownVariant };
package/dist/index.d.ts CHANGED
@@ -1,15 +1,7 @@
1
1
  import { CustomTheme } from '@dt-dds/themes';
2
- import { BaseProps } from '@dt-dds/react-core';
3
2
  import * as react from 'react';
4
- import react__default, { RefObject } from 'react';
5
-
6
- interface DropdownOptionProps extends BaseProps, react__default.LiHTMLAttributes<HTMLLIElement> {
7
- isDisabled?: boolean;
8
- isSelected?: boolean;
9
- isHighlighted?: boolean;
10
- isMulti?: boolean;
11
- }
12
- declare const DropdownOption: react__default.ForwardRefExoticComponent<DropdownOptionProps & react__default.RefAttributes<HTMLLIElement>>;
3
+ import { RefObject, ElementType, ComponentPropsWithoutRef, Ref, ReactElement } from 'react';
4
+ import { BaseProps } from '@dt-dds/react-core';
13
5
 
14
6
  type DropdownVariant = 'outlined' | 'bottom-line';
15
7
  type DropdownFill = 'default' | 'contrast' | 'light';
@@ -24,14 +16,38 @@ interface DropdownProps extends BaseProps {
24
16
  onClose?: () => void;
25
17
  as?: keyof JSX.IntrinsicElements;
26
18
  placement?: DropdownPlacement;
19
+ isFocusable?: boolean;
27
20
  }
28
21
  declare const Dropdown: react.ForwardRefExoticComponent<DropdownProps & react.RefAttributes<HTMLElement>> & {
29
- Option: react.ForwardRefExoticComponent<DropdownOptionProps & react.RefAttributes<HTMLLIElement>>;
22
+ Option: <E extends react.ElementType = "li">(props: (BaseProps & {
23
+ isDisabled?: boolean;
24
+ isSelected?: boolean;
25
+ isHighlighted?: boolean;
26
+ isMulti?: boolean;
27
+ } & {
28
+ as?: E | undefined;
29
+ } & react.PropsWithoutRef<react.ComponentProps<E>>) & {
30
+ ref?: react.Ref<Element>;
31
+ }) => react.ReactElement | null;
32
+ };
33
+
34
+ type DropdownOptionBaseProps = BaseProps & {
35
+ isDisabled?: boolean;
36
+ isSelected?: boolean;
37
+ isHighlighted?: boolean;
38
+ isMulti?: boolean;
30
39
  };
40
+ type DropdownOptionProps<E extends ElementType = 'li'> = DropdownOptionBaseProps & {
41
+ as?: E;
42
+ } & ComponentPropsWithoutRef<E>;
43
+ type DropdownOptionComponent = <E extends ElementType = 'li'>(props: DropdownOptionProps<E> & {
44
+ ref?: Ref<Element>;
45
+ }) => ReactElement | null;
46
+ declare const DropdownOption: DropdownOptionComponent;
31
47
 
32
48
  declare module '@emotion/react' {
33
49
  interface Theme extends CustomTheme {
34
50
  }
35
51
  }
36
52
 
37
- export { Dropdown, type DropdownFill, DropdownOption, type DropdownOptionProps, type DropdownPlacement, type DropdownProps, type DropdownVariant };
53
+ export { Dropdown, type DropdownFill, DropdownOption, type DropdownPlacement, type DropdownProps, type DropdownVariant };
package/dist/index.js CHANGED
@@ -65,8 +65,9 @@ __export(index_exports, {
65
65
  module.exports = __toCommonJS(index_exports);
66
66
 
67
67
  // src/Dropdown.tsx
68
- var import_react_core2 = require("@dt-dds/react-core");
69
68
  var import_react3 = require("react");
69
+ var import_focus_trap_react = require("focus-trap-react");
70
+ var import_react_core2 = require("@dt-dds/react-core");
70
71
 
71
72
  // src/components/option/DropdownOption.tsx
72
73
  var import_react = require("react");
@@ -76,9 +77,10 @@ var import_styled = __toESM(require("@emotion/styled"));
76
77
  var DropdownOptionStyled = import_styled.default.li`
77
78
  ${({ theme }) => `
78
79
  ${theme.fontStyles.bodyMdRegular};
79
-
80
+
81
+ display: block;
80
82
  color: ${theme.palette.content.default};
81
- padding: ${theme.spacing.spacing_40} ${theme.spacing.spacing_50};
83
+ padding: ${theme.spacing.spacing_40} ${theme.spacing.spacing_50};
82
84
  list-style: none;
83
85
  text-overflow: ellipsis;
84
86
  overflow-x: hidden;
@@ -93,6 +95,11 @@ var DropdownOptionStyled = import_styled.default.li`
93
95
  background: ${theme.palette.accent.light};
94
96
  cursor: pointer;
95
97
  }
98
+
99
+ &:focus-visible {
100
+ outline: 2px solid ${theme.palette.primary.default};
101
+ outline-offset: -2px;
102
+ }
96
103
  }
97
104
 
98
105
  &[aria-disabled="true"] {
@@ -138,7 +145,9 @@ var DropdownOption = (0, import_react.forwardRef)(
138
145
  };
139
146
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
140
147
  DropdownOptionStyled,
141
- __spreadProps(__spreadValues({}, rest), {
148
+ __spreadProps(__spreadValues({
149
+ tabIndex: isDisabled ? -1 : 0
150
+ }, rest), {
142
151
  "aria-disabled": isDisabled,
143
152
  "aria-selected": isSelected,
144
153
  "data-highlighted": isHighlighted,
@@ -161,8 +170,8 @@ var DropdownStyled = import_styled2.default.div`
161
170
  `;
162
171
 
163
172
  // src/hooks/useFloatingPosition.ts
164
- var import_react_core = require("@dt-dds/react-core");
165
173
  var import_react2 = require("react");
174
+ var import_react_core = require("@dt-dds/react-core");
166
175
  function basePos({
167
176
  placement,
168
177
  anchor,
@@ -301,7 +310,8 @@ var Dropdown = Object.assign(
301
310
  offsetY,
302
311
  as = "div",
303
312
  onClose,
304
- placement
313
+ placement,
314
+ isFocusable = true
305
315
  } = _b, rest = __objRest(_b, [
306
316
  "children",
307
317
  "style",
@@ -313,7 +323,8 @@ var Dropdown = Object.assign(
313
323
  "offsetY",
314
324
  "as",
315
325
  "onClose",
316
- "placement"
326
+ "placement",
327
+ "isFocusable"
317
328
  ]);
318
329
  const localMenuRef = (0, import_react3.useRef)(null);
319
330
  const setMenuRef = (0, import_react3.useCallback)(
@@ -338,7 +349,7 @@ var Dropdown = Object.assign(
338
349
  refs: [localMenuRef, anchorRef],
339
350
  handler: () => onClose == null ? void 0 : onClose()
340
351
  });
341
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_core2.Portal, { isOpen: true, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
352
+ const dropdownNode = /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
342
353
  DropdownStyled,
343
354
  __spreadProps(__spreadValues({
344
355
  as,
@@ -351,7 +362,26 @@ var Dropdown = Object.assign(
351
362
  onMouseDown: (e) => e.preventDefault(),
352
363
  children
353
364
  })
354
- ) });
365
+ );
366
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_core2.Portal, { isOpen: true, children: isFocusable ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
367
+ import_focus_trap_react.FocusTrap,
368
+ {
369
+ active: isOpen,
370
+ focusTrapOptions: {
371
+ initialFocus: () => {
372
+ var _a2;
373
+ return (_a2 = localMenuRef == null ? void 0 : localMenuRef.current) != null ? _a2 : false;
374
+ },
375
+ fallbackFocus: () => document.body,
376
+ escapeDeactivates: true,
377
+ allowOutsideClick: true,
378
+ onDeactivate: () => {
379
+ onClose == null ? void 0 : onClose();
380
+ }
381
+ },
382
+ children: dropdownNode
383
+ }
384
+ ) : dropdownNode });
355
385
  }
356
386
  ),
357
387
  {
package/dist/index.mjs CHANGED
@@ -31,20 +31,24 @@ var __objRest = (source, exclude) => {
31
31
  };
32
32
 
33
33
  // src/Dropdown.tsx
34
- import { Portal, useClickOutside } from "@dt-dds/react-core";
35
34
  import { forwardRef as forwardRef2, useCallback, useRef } from "react";
35
+ import { FocusTrap } from "focus-trap-react";
36
+ import { Portal, useClickOutside } from "@dt-dds/react-core";
36
37
 
37
38
  // src/components/option/DropdownOption.tsx
38
- import { forwardRef } from "react";
39
+ import {
40
+ forwardRef
41
+ } from "react";
39
42
 
40
43
  // src/components/option/DropdownOption.styled.ts
41
44
  import styled from "@emotion/styled";
42
45
  var DropdownOptionStyled = styled.li`
43
46
  ${({ theme }) => `
44
47
  ${theme.fontStyles.bodyMdRegular};
45
-
48
+
49
+ display: block;
46
50
  color: ${theme.palette.content.default};
47
- padding: ${theme.spacing.spacing_40} ${theme.spacing.spacing_50};
51
+ padding: ${theme.spacing.spacing_40} ${theme.spacing.spacing_50};
48
52
  list-style: none;
49
53
  text-overflow: ellipsis;
50
54
  overflow-x: hidden;
@@ -59,6 +63,11 @@ var DropdownOptionStyled = styled.li`
59
63
  background: ${theme.palette.accent.light};
60
64
  cursor: pointer;
61
65
  }
66
+
67
+ &:focus-visible {
68
+ outline: 2px solid ${theme.palette.primary.default};
69
+ outline-offset: -2px;
70
+ }
62
71
  }
63
72
 
64
73
  &[aria-disabled="true"] {
@@ -104,7 +113,9 @@ var DropdownOption = forwardRef(
104
113
  };
105
114
  return /* @__PURE__ */ jsx(
106
115
  DropdownOptionStyled,
107
- __spreadProps(__spreadValues({}, rest), {
116
+ __spreadProps(__spreadValues({
117
+ tabIndex: isDisabled ? -1 : 0
118
+ }, rest), {
108
119
  "aria-disabled": isDisabled,
109
120
  "aria-selected": isSelected,
110
121
  "data-highlighted": isHighlighted,
@@ -127,8 +138,8 @@ var DropdownStyled = styled2.div`
127
138
  `;
128
139
 
129
140
  // src/hooks/useFloatingPosition.ts
130
- import { DROPDOWN_MENU_Z_INDEX } from "@dt-dds/react-core";
131
141
  import { useLayoutEffect, useState } from "react";
142
+ import { DROPDOWN_MENU_Z_INDEX } from "@dt-dds/react-core";
132
143
  function basePos({
133
144
  placement,
134
145
  anchor,
@@ -267,7 +278,8 @@ var Dropdown = Object.assign(
267
278
  offsetY,
268
279
  as = "div",
269
280
  onClose,
270
- placement
281
+ placement,
282
+ isFocusable = true
271
283
  } = _b, rest = __objRest(_b, [
272
284
  "children",
273
285
  "style",
@@ -279,7 +291,8 @@ var Dropdown = Object.assign(
279
291
  "offsetY",
280
292
  "as",
281
293
  "onClose",
282
- "placement"
294
+ "placement",
295
+ "isFocusable"
283
296
  ]);
284
297
  const localMenuRef = useRef(null);
285
298
  const setMenuRef = useCallback(
@@ -304,7 +317,7 @@ var Dropdown = Object.assign(
304
317
  refs: [localMenuRef, anchorRef],
305
318
  handler: () => onClose == null ? void 0 : onClose()
306
319
  });
307
- return /* @__PURE__ */ jsx2(Portal, { isOpen: true, children: /* @__PURE__ */ jsx2(
320
+ const dropdownNode = /* @__PURE__ */ jsx2(
308
321
  DropdownStyled,
309
322
  __spreadProps(__spreadValues({
310
323
  as,
@@ -317,7 +330,26 @@ var Dropdown = Object.assign(
317
330
  onMouseDown: (e) => e.preventDefault(),
318
331
  children
319
332
  })
320
- ) });
333
+ );
334
+ return /* @__PURE__ */ jsx2(Portal, { isOpen: true, children: isFocusable ? /* @__PURE__ */ jsx2(
335
+ FocusTrap,
336
+ {
337
+ active: isOpen,
338
+ focusTrapOptions: {
339
+ initialFocus: () => {
340
+ var _a2;
341
+ return (_a2 = localMenuRef == null ? void 0 : localMenuRef.current) != null ? _a2 : false;
342
+ },
343
+ fallbackFocus: () => document.body,
344
+ escapeDeactivates: true,
345
+ allowOutsideClick: true,
346
+ onDeactivate: () => {
347
+ onClose == null ? void 0 : onClose();
348
+ }
349
+ },
350
+ children: dropdownNode
351
+ }
352
+ ) : dropdownNode });
321
353
  }
322
354
  ),
323
355
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dt-dds/react-dropdown",
3
- "version": "1.0.0-beta.77",
3
+ "version": "1.0.0-beta.79",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": "./dist/index.js"
@@ -20,12 +20,13 @@
20
20
  "test:update:snapshot": "jest -u"
21
21
  },
22
22
  "dependencies": {
23
- "@dt-dds/react-box": "1.0.0-beta.56",
24
- "@dt-dds/react-core": "1.0.0-beta.51",
25
- "@dt-dds/react-icon": "1.0.0-beta.54",
26
- "@dt-dds/react-icon-button": "1.0.0-beta.20",
27
- "@dt-dds/react-typography": "1.0.0-beta.42",
28
- "@dt-dds/themes": "1.0.0-beta.9"
23
+ "@dt-dds/react-box": "1.0.0-beta.58",
24
+ "@dt-dds/react-core": "1.0.0-beta.52",
25
+ "@dt-dds/react-icon": "1.0.0-beta.55",
26
+ "@dt-dds/react-icon-button": "1.0.0-beta.21",
27
+ "@dt-dds/react-typography": "1.0.0-beta.43",
28
+ "@dt-dds/themes": "1.0.0-beta.10",
29
+ "focus-trap-react": "^11.0.4"
29
30
  },
30
31
  "devDependencies": {
31
32
  "@babel/core": "^7.22.9",