@dbcdk/react-components 0.0.200 → 0.0.202
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/dist/components/alert/Alert.cjs +31 -3
- package/dist/components/alert/Alert.d.ts +11 -1
- package/dist/components/alert/Alert.js +31 -3
- package/dist/components/alert/Alert.module.css +26 -10
- package/dist/components/button/Button.cjs +38 -29
- package/dist/components/button/Button.js +39 -29
- package/dist/components/forms/checkbox/Checkbox.cjs +3 -0
- package/dist/components/forms/checkbox/Checkbox.d.ts +8 -1
- package/dist/components/forms/checkbox/Checkbox.js +3 -0
- package/dist/components/forms/checkbox/Checkbox.module.css +2 -1
- package/dist/components/forms/form-select/FormSelect.cjs +2 -0
- package/dist/components/forms/form-select/FormSelect.d.ts +1 -1
- package/dist/components/forms/form-select/FormSelect.js +2 -0
- package/dist/components/forms/input-container/InputContainer.cjs +1 -1
- package/dist/components/forms/input-container/InputContainer.js +1 -1
- package/dist/components/forms/select/Select.cjs +35 -19
- package/dist/components/forms/select/Select.d.ts +1 -1
- package/dist/components/forms/select/Select.js +35 -19
- package/dist/components/popover/Popover.cjs +1 -0
- package/dist/components/popover/Popover.js +1 -0
- package/package.json +1 -1
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
|
+
var lucideReact = require('lucide-react');
|
|
5
6
|
var styles = require('./Alert.module.css');
|
|
7
|
+
var Button = require('../button/Button');
|
|
6
8
|
var Headline = require('../headline/Headline');
|
|
7
9
|
var Icon = require('../icon/Icon');
|
|
8
10
|
|
|
@@ -14,12 +16,16 @@ function Alert({
|
|
|
14
16
|
children,
|
|
15
17
|
title,
|
|
16
18
|
headlineSize = 3,
|
|
19
|
+
headlineWeight = 600,
|
|
20
|
+
headlineVariant,
|
|
17
21
|
severity = "neutral",
|
|
18
22
|
customIcon,
|
|
19
23
|
disableIcon = false,
|
|
20
24
|
fullWidth = false,
|
|
21
25
|
maxWidth = "72ch",
|
|
22
|
-
role = "status"
|
|
26
|
+
role = "status",
|
|
27
|
+
onClose,
|
|
28
|
+
closeLabel = "Luk"
|
|
23
29
|
}) {
|
|
24
30
|
const hasLeading = Boolean(customIcon) || !disableIcon;
|
|
25
31
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -40,10 +46,32 @@ function Alert({
|
|
|
40
46
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.content, children: [
|
|
41
47
|
title ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.titleRow, children: [
|
|
42
48
|
hasLeading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.leading, children: customIcon != null ? customIcon : /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { severity }) }) : null,
|
|
43
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.title, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
49
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.title, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
50
|
+
Headline.Headline,
|
|
51
|
+
{
|
|
52
|
+
size: headlineSize,
|
|
53
|
+
weight: headlineWeight,
|
|
54
|
+
variant: headlineVariant,
|
|
55
|
+
disableMargin: true,
|
|
56
|
+
children: title
|
|
57
|
+
}
|
|
58
|
+
) })
|
|
44
59
|
] }) : null,
|
|
45
60
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.body, children })
|
|
46
|
-
] })
|
|
61
|
+
] }),
|
|
62
|
+
onClose ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
63
|
+
Button.Button,
|
|
64
|
+
{
|
|
65
|
+
type: "button",
|
|
66
|
+
variant: "inline",
|
|
67
|
+
shape: "round",
|
|
68
|
+
size: "sm",
|
|
69
|
+
className: styles__default.default.closeButton,
|
|
70
|
+
"aria-label": closeLabel,
|
|
71
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, {}),
|
|
72
|
+
onClick: onClose
|
|
73
|
+
}
|
|
74
|
+
) : null
|
|
47
75
|
]
|
|
48
76
|
}
|
|
49
77
|
);
|
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
import type { JSX, ReactNode } from 'react';
|
|
2
2
|
import type { Severity } from '../../constants/severity.types';
|
|
3
|
+
import { type HeadlineProps } from '../headline/Headline';
|
|
3
4
|
export interface AlertProps {
|
|
4
5
|
children: ReactNode;
|
|
5
6
|
title?: ReactNode;
|
|
6
7
|
headlineSize?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
8
|
+
headlineWeight?: HeadlineProps['weight'];
|
|
9
|
+
headlineVariant?: HeadlineProps['variant'];
|
|
7
10
|
severity?: Severity;
|
|
8
11
|
customIcon?: ReactNode;
|
|
9
12
|
disableIcon?: boolean;
|
|
10
13
|
fullWidth?: boolean;
|
|
11
14
|
maxWidth?: string | number;
|
|
12
15
|
role?: 'status' | 'alert';
|
|
16
|
+
/**
|
|
17
|
+
* Shows a close button that calls this. The alert has no open state of its
|
|
18
|
+
* own: the parent decides whether to keep rendering it.
|
|
19
|
+
*/
|
|
20
|
+
onClose?: () => void;
|
|
21
|
+
/** Accessible name for the close button. */
|
|
22
|
+
closeLabel?: string;
|
|
13
23
|
}
|
|
14
|
-
export declare function Alert({ children, title, headlineSize, severity, customIcon, disableIcon, fullWidth, maxWidth, role, }: AlertProps): JSX.Element;
|
|
24
|
+
export declare function Alert({ children, title, headlineSize, headlineWeight, headlineVariant, severity, customIcon, disableIcon, fullWidth, maxWidth, role, onClose, closeLabel, }: AlertProps): JSX.Element;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { X } from 'lucide-react';
|
|
3
4
|
import styles from './Alert.module.css';
|
|
5
|
+
import { Button } from '../button/Button';
|
|
4
6
|
import { Headline } from '../headline/Headline';
|
|
5
7
|
import { Icon } from '../icon/Icon';
|
|
6
8
|
|
|
@@ -8,12 +10,16 @@ function Alert({
|
|
|
8
10
|
children,
|
|
9
11
|
title,
|
|
10
12
|
headlineSize = 3,
|
|
13
|
+
headlineWeight = 600,
|
|
14
|
+
headlineVariant,
|
|
11
15
|
severity = "neutral",
|
|
12
16
|
customIcon,
|
|
13
17
|
disableIcon = false,
|
|
14
18
|
fullWidth = false,
|
|
15
19
|
maxWidth = "72ch",
|
|
16
|
-
role = "status"
|
|
20
|
+
role = "status",
|
|
21
|
+
onClose,
|
|
22
|
+
closeLabel = "Luk"
|
|
17
23
|
}) {
|
|
18
24
|
const hasLeading = Boolean(customIcon) || !disableIcon;
|
|
19
25
|
return /* @__PURE__ */ jsxs(
|
|
@@ -34,10 +40,32 @@ function Alert({
|
|
|
34
40
|
/* @__PURE__ */ jsxs("div", { className: styles.content, children: [
|
|
35
41
|
title ? /* @__PURE__ */ jsxs("div", { className: styles.titleRow, children: [
|
|
36
42
|
hasLeading ? /* @__PURE__ */ jsx("div", { className: styles.leading, children: customIcon != null ? customIcon : /* @__PURE__ */ jsx(Icon, { severity }) }) : null,
|
|
37
|
-
/* @__PURE__ */ jsx("div", { className: styles.title, children: /* @__PURE__ */ jsx(
|
|
43
|
+
/* @__PURE__ */ jsx("div", { className: styles.title, children: /* @__PURE__ */ jsx(
|
|
44
|
+
Headline,
|
|
45
|
+
{
|
|
46
|
+
size: headlineSize,
|
|
47
|
+
weight: headlineWeight,
|
|
48
|
+
variant: headlineVariant,
|
|
49
|
+
disableMargin: true,
|
|
50
|
+
children: title
|
|
51
|
+
}
|
|
52
|
+
) })
|
|
38
53
|
] }) : null,
|
|
39
54
|
/* @__PURE__ */ jsx("div", { className: styles.body, children })
|
|
40
|
-
] })
|
|
55
|
+
] }),
|
|
56
|
+
onClose ? /* @__PURE__ */ jsx(
|
|
57
|
+
Button,
|
|
58
|
+
{
|
|
59
|
+
type: "button",
|
|
60
|
+
variant: "inline",
|
|
61
|
+
shape: "round",
|
|
62
|
+
size: "sm",
|
|
63
|
+
className: styles.closeButton,
|
|
64
|
+
"aria-label": closeLabel,
|
|
65
|
+
icon: /* @__PURE__ */ jsx(X, {}),
|
|
66
|
+
onClick: onClose
|
|
67
|
+
}
|
|
68
|
+
) : null
|
|
41
69
|
]
|
|
42
70
|
}
|
|
43
71
|
);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
.container {
|
|
2
2
|
--alert-bg: var(--color-bg-toolbar);
|
|
3
3
|
--alert-fg: var(--color-fg-default);
|
|
4
|
-
--alert-border: var(--color-border-subtle);
|
|
5
4
|
|
|
6
5
|
display: flex;
|
|
7
6
|
align-items: flex-start;
|
|
@@ -9,10 +8,11 @@
|
|
|
9
8
|
inline-size: min(100%, var(--alert-max-width, 72ch));
|
|
10
9
|
max-inline-size: 100%;
|
|
11
10
|
padding: var(--spacing-sm) var(--spacing-md);
|
|
12
|
-
border: 1px solid var(--alert-border);
|
|
13
11
|
border-radius: var(--border-radius-default);
|
|
14
12
|
background: var(--alert-bg);
|
|
15
13
|
color: var(--alert-fg);
|
|
14
|
+
/* Severity stripe on the left edge. An inset shadow keeps size and padding unchanged. */
|
|
15
|
+
box-shadow: inset var(--border-width-thick) 0 0 var(--alert-accent, transparent);
|
|
16
16
|
box-sizing: border-box;
|
|
17
17
|
}
|
|
18
18
|
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
.content {
|
|
43
43
|
display: flex;
|
|
44
44
|
flex-direction: column;
|
|
45
|
-
gap: var(--spacing-
|
|
45
|
+
gap: var(--spacing-sm);
|
|
46
46
|
min-width: 0;
|
|
47
47
|
flex: 1 1 auto;
|
|
48
48
|
}
|
|
@@ -59,44 +59,60 @@
|
|
|
59
59
|
font-size: var(--font-size-sm);
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
.closeButton {
|
|
63
|
+
flex: 0 0 auto;
|
|
64
|
+
margin-inline-start: auto;
|
|
65
|
+
align-self: flex-start;
|
|
66
|
+
}
|
|
67
|
+
|
|
62
68
|
.neutral {
|
|
63
69
|
--alert-bg: var(--color-bg-toolbar);
|
|
64
70
|
--alert-fg: var(--color-fg-default);
|
|
65
|
-
--alert-border: var(--color-border-subtle);
|
|
66
71
|
}
|
|
67
72
|
|
|
68
73
|
.success {
|
|
69
74
|
--alert-bg: var(--color-status-success-bg);
|
|
70
75
|
--alert-fg: var(--color-status-success-fg);
|
|
71
|
-
--alert-
|
|
76
|
+
--alert-accent: var(--color-status-success);
|
|
72
77
|
}
|
|
73
78
|
|
|
74
79
|
.warning {
|
|
75
80
|
--alert-bg: var(--color-status-warning-bg);
|
|
76
81
|
--alert-fg: var(--color-status-warning-fg);
|
|
77
|
-
--alert-
|
|
82
|
+
--alert-accent: var(--color-status-warning);
|
|
78
83
|
}
|
|
79
84
|
|
|
80
85
|
.error {
|
|
81
86
|
--alert-bg: var(--color-status-error-bg);
|
|
82
87
|
--alert-fg: var(--color-status-error-fg);
|
|
83
|
-
--alert-
|
|
88
|
+
--alert-accent: var(--color-status-error);
|
|
84
89
|
}
|
|
85
90
|
|
|
86
91
|
.info {
|
|
87
92
|
--alert-bg: var(--color-status-info-bg);
|
|
88
93
|
--alert-fg: var(--color-status-info-fg);
|
|
89
|
-
--alert-
|
|
94
|
+
--alert-accent: var(--color-status-info);
|
|
90
95
|
}
|
|
91
96
|
|
|
92
97
|
.brand {
|
|
93
98
|
--alert-bg: color-mix(in srgb, var(--color-brand) 10%, var(--color-bg-surface));
|
|
94
99
|
--alert-fg: var(--color-brand);
|
|
95
|
-
--alert-
|
|
100
|
+
--alert-accent: var(--color-brand);
|
|
96
101
|
}
|
|
97
102
|
|
|
98
103
|
.accent {
|
|
99
104
|
--alert-bg: var(--color-accent-bg);
|
|
100
105
|
--alert-fg: var(--color-accent-fg);
|
|
101
|
-
--alert-
|
|
106
|
+
--alert-accent: var(--color-accent);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* Square corners on the striped edge, so the stripe stays straight. */
|
|
110
|
+
.success,
|
|
111
|
+
.warning,
|
|
112
|
+
.error,
|
|
113
|
+
.info,
|
|
114
|
+
.brand,
|
|
115
|
+
.accent {
|
|
116
|
+
border-top-left-radius: 0;
|
|
117
|
+
border-bottom-left-radius: 0;
|
|
102
118
|
}
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
|
-
var lucideReact = require('lucide-react');
|
|
6
5
|
var React = require('react');
|
|
6
|
+
var lucideReact = require('lucide-react');
|
|
7
7
|
var useTooltipTrigger = require('../../components/overlay/tooltip/useTooltipTrigger');
|
|
8
|
+
var refs_utils = require('../../utils/refs.utils');
|
|
8
9
|
var styles = require('./Button.module.css');
|
|
9
10
|
|
|
10
11
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -33,15 +34,6 @@ var styles__default = /*#__PURE__*/_interopDefault(styles);
|
|
|
33
34
|
function cx(...parts) {
|
|
34
35
|
return parts.filter(Boolean).join(" ");
|
|
35
36
|
}
|
|
36
|
-
function mergeRefs(...refs) {
|
|
37
|
-
return (node) => {
|
|
38
|
-
for (const ref of refs) {
|
|
39
|
-
if (!ref) continue;
|
|
40
|
-
if (typeof ref === "function") ref(node);
|
|
41
|
-
else ref.current = node;
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
37
|
const Button = React__namespace.forwardRef(function Button2({
|
|
46
38
|
variant = "outlined",
|
|
47
39
|
shape = "default",
|
|
@@ -58,7 +50,6 @@ const Button = React__namespace.forwardRef(function Button2({
|
|
|
58
50
|
type = "button",
|
|
59
51
|
...rest
|
|
60
52
|
}, ref) {
|
|
61
|
-
var _a;
|
|
62
53
|
const { className: userClassName, ...buttonProps } = rest;
|
|
63
54
|
const computedClassName = cx(
|
|
64
55
|
styles__default.default.button,
|
|
@@ -71,17 +62,26 @@ const Button = React__namespace.forwardRef(function Button2({
|
|
|
71
62
|
userClassName
|
|
72
63
|
);
|
|
73
64
|
const tooltipEnabled = Boolean(tooltip);
|
|
74
|
-
const
|
|
75
|
-
const
|
|
65
|
+
const linkChild = isLink && React__namespace.isValidElement(children) ? children : null;
|
|
66
|
+
const childRef = linkChild == null ? void 0 : linkChild.props.ref;
|
|
76
67
|
const { triggerProps, id: tooltipId } = useTooltipTrigger.useTooltipTrigger({
|
|
77
68
|
content: tooltipEnabled ? tooltip : null,
|
|
78
69
|
placement: tooltipPlacement,
|
|
79
70
|
offset: 8
|
|
80
71
|
});
|
|
81
|
-
const { ref: hoverRef,
|
|
72
|
+
const { ref: hoverRef, ...tooltipTriggerProps } = triggerProps;
|
|
73
|
+
const { onPointerEnter: hoverEnter, onPointerLeave: hoverLeave } = tooltipTriggerProps;
|
|
74
|
+
const isDisabled = Boolean(buttonProps.disabled);
|
|
75
|
+
const tooltipOnControl = tooltipEnabled && (Boolean(linkChild) || !isDisabled);
|
|
76
|
+
const tooltipRef = tooltipOnControl ? hoverRef : void 0;
|
|
77
|
+
const mergedRef = React__namespace.useMemo(
|
|
78
|
+
() => refs_utils.mergeRefs(childRef, ref, tooltipRef),
|
|
79
|
+
[childRef, ref, tooltipRef]
|
|
80
|
+
);
|
|
82
81
|
const describedBy = (() => {
|
|
83
82
|
const existing = typeof buttonProps["aria-describedby"] === "string" ? buttonProps["aria-describedby"] : "";
|
|
84
83
|
const ids = [existing, tooltipEnabled ? tooltipId : ""].filter(Boolean);
|
|
84
|
+
if (linkChild == null ? void 0 : linkChild.props["aria-describedby"]) ids.unshift(linkChild.props["aria-describedby"]);
|
|
85
85
|
return ids.length ? ids.join(" ") : void 0;
|
|
86
86
|
})();
|
|
87
87
|
const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -90,39 +90,48 @@ const Button = React__namespace.forwardRef(function Button2({
|
|
|
90
90
|
loading && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { display: "flex", opacity: 0.5 }, className: "spin", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.LoaderCircle, {}) })
|
|
91
91
|
] });
|
|
92
92
|
let buttonEl;
|
|
93
|
-
if (
|
|
94
|
-
const
|
|
93
|
+
if (linkChild) {
|
|
94
|
+
const Link = linkChild.type;
|
|
95
|
+
const childClassName = typeof linkChild.props.className === "string" ? linkChild.props.className : "";
|
|
95
96
|
const { disabled, onClick, ...linkButtonProps } = buttonProps;
|
|
96
97
|
const handleClick = (e) => {
|
|
98
|
+
var _a, _b;
|
|
97
99
|
if (disabled) {
|
|
98
100
|
e.preventDefault();
|
|
99
101
|
return;
|
|
100
102
|
}
|
|
103
|
+
(_b = (_a = linkChild.props).onClick) == null ? void 0 : _b.call(_a, e);
|
|
104
|
+
if (e.defaultPrevented) return;
|
|
101
105
|
onClick == null ? void 0 : onClick(e);
|
|
102
106
|
};
|
|
103
|
-
buttonEl =
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
107
|
+
buttonEl = /* @__PURE__ */ React.createElement(
|
|
108
|
+
Link,
|
|
109
|
+
{
|
|
110
|
+
...linkChild.props,
|
|
111
|
+
...linkButtonProps,
|
|
112
|
+
...tooltipEnabled ? tooltipTriggerProps : {},
|
|
113
|
+
key: linkChild.key,
|
|
114
|
+
ref: mergedRef,
|
|
115
|
+
className: cx(childClassName, computedClassName, styles__default.default.buttonLink),
|
|
116
|
+
"aria-describedby": describedBy,
|
|
117
|
+
"aria-disabled": disabled ? "true" : void 0,
|
|
118
|
+
onClick: handleClick
|
|
119
|
+
},
|
|
120
|
+
/* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
112
121
|
icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cx(styles__default.default.icon, spinIcon ? "spin" : ""), children: icon }),
|
|
113
|
-
|
|
122
|
+
linkChild.props.children,
|
|
114
123
|
loading && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { display: "flex", opacity: 0.5 }, className: "spin", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.LoaderCircle, {}) })
|
|
115
124
|
] })
|
|
116
|
-
|
|
125
|
+
);
|
|
117
126
|
} else {
|
|
118
|
-
const isDisabled = Boolean(buttonProps.disabled);
|
|
119
127
|
buttonEl = /* @__PURE__ */ jsxRuntime.jsx(
|
|
120
128
|
"button",
|
|
121
129
|
{
|
|
130
|
+
ref: mergedRef,
|
|
122
131
|
className: computedClassName,
|
|
123
132
|
type,
|
|
124
133
|
...buttonProps,
|
|
125
|
-
...
|
|
134
|
+
...tooltipOnControl ? tooltipTriggerProps : {},
|
|
126
135
|
"aria-describedby": describedBy,
|
|
127
136
|
children: content
|
|
128
137
|
}
|
|
@@ -1,22 +1,15 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
3
|
-
import { LoaderCircle } from 'lucide-react';
|
|
4
3
|
import * as React from 'react';
|
|
4
|
+
import { createElement } from 'react';
|
|
5
|
+
import { LoaderCircle } from 'lucide-react';
|
|
5
6
|
import { useTooltipTrigger } from '../../components/overlay/tooltip/useTooltipTrigger';
|
|
7
|
+
import { mergeRefs } from '../../utils/refs.utils';
|
|
6
8
|
import styles from './Button.module.css';
|
|
7
9
|
|
|
8
10
|
function cx(...parts) {
|
|
9
11
|
return parts.filter(Boolean).join(" ");
|
|
10
12
|
}
|
|
11
|
-
function mergeRefs(...refs) {
|
|
12
|
-
return (node) => {
|
|
13
|
-
for (const ref of refs) {
|
|
14
|
-
if (!ref) continue;
|
|
15
|
-
if (typeof ref === "function") ref(node);
|
|
16
|
-
else ref.current = node;
|
|
17
|
-
}
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
13
|
const Button = React.forwardRef(function Button2({
|
|
21
14
|
variant = "outlined",
|
|
22
15
|
shape = "default",
|
|
@@ -33,7 +26,6 @@ const Button = React.forwardRef(function Button2({
|
|
|
33
26
|
type = "button",
|
|
34
27
|
...rest
|
|
35
28
|
}, ref) {
|
|
36
|
-
var _a;
|
|
37
29
|
const { className: userClassName, ...buttonProps } = rest;
|
|
38
30
|
const computedClassName = cx(
|
|
39
31
|
styles.button,
|
|
@@ -46,17 +38,26 @@ const Button = React.forwardRef(function Button2({
|
|
|
46
38
|
userClassName
|
|
47
39
|
);
|
|
48
40
|
const tooltipEnabled = Boolean(tooltip);
|
|
49
|
-
const
|
|
50
|
-
const
|
|
41
|
+
const linkChild = isLink && React.isValidElement(children) ? children : null;
|
|
42
|
+
const childRef = linkChild == null ? void 0 : linkChild.props.ref;
|
|
51
43
|
const { triggerProps, id: tooltipId } = useTooltipTrigger({
|
|
52
44
|
content: tooltipEnabled ? tooltip : null,
|
|
53
45
|
placement: tooltipPlacement,
|
|
54
46
|
offset: 8
|
|
55
47
|
});
|
|
56
|
-
const { ref: hoverRef,
|
|
48
|
+
const { ref: hoverRef, ...tooltipTriggerProps } = triggerProps;
|
|
49
|
+
const { onPointerEnter: hoverEnter, onPointerLeave: hoverLeave } = tooltipTriggerProps;
|
|
50
|
+
const isDisabled = Boolean(buttonProps.disabled);
|
|
51
|
+
const tooltipOnControl = tooltipEnabled && (Boolean(linkChild) || !isDisabled);
|
|
52
|
+
const tooltipRef = tooltipOnControl ? hoverRef : void 0;
|
|
53
|
+
const mergedRef = React.useMemo(
|
|
54
|
+
() => mergeRefs(childRef, ref, tooltipRef),
|
|
55
|
+
[childRef, ref, tooltipRef]
|
|
56
|
+
);
|
|
57
57
|
const describedBy = (() => {
|
|
58
58
|
const existing = typeof buttonProps["aria-describedby"] === "string" ? buttonProps["aria-describedby"] : "";
|
|
59
59
|
const ids = [existing, tooltipEnabled ? tooltipId : ""].filter(Boolean);
|
|
60
|
+
if (linkChild == null ? void 0 : linkChild.props["aria-describedby"]) ids.unshift(linkChild.props["aria-describedby"]);
|
|
60
61
|
return ids.length ? ids.join(" ") : void 0;
|
|
61
62
|
})();
|
|
62
63
|
const content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -65,39 +66,48 @@ const Button = React.forwardRef(function Button2({
|
|
|
65
66
|
loading && /* @__PURE__ */ jsx("span", { style: { display: "flex", opacity: 0.5 }, className: "spin", children: /* @__PURE__ */ jsx(LoaderCircle, {}) })
|
|
66
67
|
] });
|
|
67
68
|
let buttonEl;
|
|
68
|
-
if (
|
|
69
|
-
const
|
|
69
|
+
if (linkChild) {
|
|
70
|
+
const Link = linkChild.type;
|
|
71
|
+
const childClassName = typeof linkChild.props.className === "string" ? linkChild.props.className : "";
|
|
70
72
|
const { disabled, onClick, ...linkButtonProps } = buttonProps;
|
|
71
73
|
const handleClick = (e) => {
|
|
74
|
+
var _a, _b;
|
|
72
75
|
if (disabled) {
|
|
73
76
|
e.preventDefault();
|
|
74
77
|
return;
|
|
75
78
|
}
|
|
79
|
+
(_b = (_a = linkChild.props).onClick) == null ? void 0 : _b.call(_a, e);
|
|
80
|
+
if (e.defaultPrevented) return;
|
|
76
81
|
onClick == null ? void 0 : onClick(e);
|
|
77
82
|
};
|
|
78
|
-
buttonEl =
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
buttonEl = /* @__PURE__ */ createElement(
|
|
84
|
+
Link,
|
|
85
|
+
{
|
|
86
|
+
...linkChild.props,
|
|
87
|
+
...linkButtonProps,
|
|
88
|
+
...tooltipEnabled ? tooltipTriggerProps : {},
|
|
89
|
+
key: linkChild.key,
|
|
90
|
+
ref: mergedRef,
|
|
91
|
+
className: cx(childClassName, computedClassName, styles.buttonLink),
|
|
92
|
+
"aria-describedby": describedBy,
|
|
93
|
+
"aria-disabled": disabled ? "true" : void 0,
|
|
94
|
+
onClick: handleClick
|
|
95
|
+
},
|
|
96
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
87
97
|
icon && /* @__PURE__ */ jsx("span", { className: cx(styles.icon, spinIcon ? "spin" : ""), children: icon }),
|
|
88
|
-
|
|
98
|
+
linkChild.props.children,
|
|
89
99
|
loading && /* @__PURE__ */ jsx("span", { style: { display: "flex", opacity: 0.5 }, className: "spin", children: /* @__PURE__ */ jsx(LoaderCircle, {}) })
|
|
90
100
|
] })
|
|
91
|
-
|
|
101
|
+
);
|
|
92
102
|
} else {
|
|
93
|
-
const isDisabled = Boolean(buttonProps.disabled);
|
|
94
103
|
buttonEl = /* @__PURE__ */ jsx(
|
|
95
104
|
"button",
|
|
96
105
|
{
|
|
106
|
+
ref: mergedRef,
|
|
97
107
|
className: computedClassName,
|
|
98
108
|
type,
|
|
99
109
|
...buttonProps,
|
|
100
|
-
...
|
|
110
|
+
...tooltipOnControl ? tooltipTriggerProps : {},
|
|
101
111
|
"aria-describedby": describedBy,
|
|
102
112
|
children: content
|
|
103
113
|
}
|
|
@@ -21,6 +21,7 @@ function Checkbox({
|
|
|
21
21
|
labelAs = "label",
|
|
22
22
|
endAdornment,
|
|
23
23
|
endAdornmentAriaHidden = true,
|
|
24
|
+
labelAction,
|
|
24
25
|
size = "md",
|
|
25
26
|
modified,
|
|
26
27
|
containerLabel,
|
|
@@ -78,6 +79,7 @@ function Checkbox({
|
|
|
78
79
|
}
|
|
79
80
|
) }),
|
|
80
81
|
label && (labelAs === "label" ? /* @__PURE__ */ jsxRuntime.jsx("label", { className: styles__default.default.label, htmlFor: controlId, children: label }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.label, children: label })),
|
|
82
|
+
labelAction && !containerLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.labelAction, "data-checkbox-label-action": "true", children: labelAction }),
|
|
81
83
|
endAdornment && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.endAdornment, "aria-hidden": endAdornmentAriaHidden, children: endAdornment })
|
|
82
84
|
]
|
|
83
85
|
}
|
|
@@ -88,6 +90,7 @@ function Checkbox({
|
|
|
88
90
|
{
|
|
89
91
|
modified,
|
|
90
92
|
label: containerLabel,
|
|
93
|
+
labelAction: containerLabel ? labelAction : void 0,
|
|
91
94
|
htmlFor: controlId,
|
|
92
95
|
error,
|
|
93
96
|
helpText,
|
|
@@ -21,6 +21,13 @@ interface CheckboxProps {
|
|
|
21
21
|
* Defaults to true since endAdornment is typically decorative.
|
|
22
22
|
*/
|
|
23
23
|
endAdornmentAriaHidden?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Content next to the label, e.g. a help button or other additional content.
|
|
26
|
+
* Rendered next to `containerLabel` when set, otherwise after the per-item
|
|
27
|
+
* `label`.
|
|
28
|
+
* Unlike `endAdornment`, it is never hidden from assistive tech.
|
|
29
|
+
*/
|
|
30
|
+
labelAction?: ReactNode;
|
|
24
31
|
size?: Size;
|
|
25
32
|
containerLabel?: string;
|
|
26
33
|
error?: string;
|
|
@@ -35,5 +42,5 @@ interface CheckboxProps {
|
|
|
35
42
|
tooltip?: ReactNode;
|
|
36
43
|
tooltipPlacement?: TooltipPlacement;
|
|
37
44
|
}
|
|
38
|
-
export declare function Checkbox({ checked: controlled, onChange, variant, disabled, label, labelAs, endAdornment, endAdornmentAriaHidden, size, modified, containerLabel, error, helpText, orientation, labelWidth, fullWidth, required, noContainer, id, 'data-cy': dataCy, tooltip, tooltipPlacement, }: CheckboxProps): JSX.Element;
|
|
45
|
+
export declare function Checkbox({ checked: controlled, onChange, variant, disabled, label, labelAs, endAdornment, endAdornmentAriaHidden, labelAction, size, modified, containerLabel, error, helpText, orientation, labelWidth, fullWidth, required, noContainer, id, 'data-cy': dataCy, tooltip, tooltipPlacement, }: CheckboxProps): JSX.Element;
|
|
39
46
|
export {};
|
|
@@ -15,6 +15,7 @@ function Checkbox({
|
|
|
15
15
|
labelAs = "label",
|
|
16
16
|
endAdornment,
|
|
17
17
|
endAdornmentAriaHidden = true,
|
|
18
|
+
labelAction,
|
|
18
19
|
size = "md",
|
|
19
20
|
modified,
|
|
20
21
|
containerLabel,
|
|
@@ -72,6 +73,7 @@ function Checkbox({
|
|
|
72
73
|
}
|
|
73
74
|
) }),
|
|
74
75
|
label && (labelAs === "label" ? /* @__PURE__ */ jsx("label", { className: styles.label, htmlFor: controlId, children: label }) : /* @__PURE__ */ jsx("span", { className: styles.label, children: label })),
|
|
76
|
+
labelAction && !containerLabel && /* @__PURE__ */ jsx("span", { className: styles.labelAction, "data-checkbox-label-action": "true", children: labelAction }),
|
|
75
77
|
endAdornment && /* @__PURE__ */ jsx("span", { className: styles.endAdornment, "aria-hidden": endAdornmentAriaHidden, children: endAdornment })
|
|
76
78
|
]
|
|
77
79
|
}
|
|
@@ -82,6 +84,7 @@ function Checkbox({
|
|
|
82
84
|
{
|
|
83
85
|
modified,
|
|
84
86
|
label: containerLabel,
|
|
87
|
+
labelAction: containerLabel ? labelAction : void 0,
|
|
85
88
|
htmlFor: controlId,
|
|
86
89
|
error,
|
|
87
90
|
helpText,
|
|
@@ -55,6 +55,7 @@ function findSelectedOption(options, selectedValue, datakey) {
|
|
|
55
55
|
function FormSelect({
|
|
56
56
|
// InputContainer props
|
|
57
57
|
label,
|
|
58
|
+
labelAction,
|
|
58
59
|
error,
|
|
59
60
|
helpText,
|
|
60
61
|
orientation = "vertical",
|
|
@@ -119,6 +120,7 @@ function FormSelect({
|
|
|
119
120
|
InputContainer.InputContainer,
|
|
120
121
|
{
|
|
121
122
|
label,
|
|
123
|
+
labelAction,
|
|
122
124
|
htmlFor: controlId,
|
|
123
125
|
fullWidth,
|
|
124
126
|
error,
|
|
@@ -31,5 +31,5 @@ export type FormSelectProps<T> = Omit<InputContainerProps, 'children' | 'htmlFor
|
|
|
31
31
|
*/
|
|
32
32
|
allowClearWhenRequired?: boolean;
|
|
33
33
|
};
|
|
34
|
-
export declare function FormSelect<T extends string | number | Record<string, any>>({ label, error, helpText, orientation, labelWidth, fullWidth, required, tooltip, tooltipPlacement, modified, id, name, options, selectedValue, onChange, placeholder, size, variant, onClear, datakey, dataCy, disabled, includePlaceholderOption, allowClearWhenRequired, }: FormSelectProps<T>): React.ReactNode;
|
|
34
|
+
export declare function FormSelect<T extends string | number | Record<string, any>>({ label, labelAction, error, helpText, orientation, labelWidth, fullWidth, required, tooltip, tooltipPlacement, modified, id, name, options, selectedValue, onChange, placeholder, size, variant, onClear, datakey, dataCy, disabled, includePlaceholderOption, allowClearWhenRequired, }: FormSelectProps<T>): React.ReactNode;
|
|
35
35
|
export {};
|
|
@@ -30,6 +30,7 @@ function findSelectedOption(options, selectedValue, datakey) {
|
|
|
30
30
|
function FormSelect({
|
|
31
31
|
// InputContainer props
|
|
32
32
|
label,
|
|
33
|
+
labelAction,
|
|
33
34
|
error,
|
|
34
35
|
helpText,
|
|
35
36
|
orientation = "vertical",
|
|
@@ -94,6 +95,7 @@ function FormSelect({
|
|
|
94
95
|
InputContainer,
|
|
95
96
|
{
|
|
96
97
|
label,
|
|
98
|
+
labelAction,
|
|
97
99
|
htmlFor: controlId,
|
|
98
100
|
fullWidth,
|
|
99
101
|
error,
|
|
@@ -24,7 +24,7 @@ function InputContainer({
|
|
|
24
24
|
labelAlignment = "center",
|
|
25
25
|
modified = false
|
|
26
26
|
}) {
|
|
27
|
-
const renderLabelRow = (label || labelAction) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${styles__default.default.labelRow} dbc-flex dbc-items-center dbc-gap-
|
|
27
|
+
const renderLabelRow = (label || labelAction) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${styles__default.default.labelRow} dbc-flex dbc-items-center dbc-gap-xs`, children: [
|
|
28
28
|
label && /* @__PURE__ */ jsxRuntime.jsxs("label", { className: styles__default.default.label, htmlFor, children: [
|
|
29
29
|
label,
|
|
30
30
|
required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.required, children: " *" })
|
|
@@ -18,7 +18,7 @@ function InputContainer({
|
|
|
18
18
|
labelAlignment = "center",
|
|
19
19
|
modified = false
|
|
20
20
|
}) {
|
|
21
|
-
const renderLabelRow = (label || labelAction) && /* @__PURE__ */ jsxs("div", { className: `${styles.labelRow} dbc-flex dbc-items-center dbc-gap-
|
|
21
|
+
const renderLabelRow = (label || labelAction) && /* @__PURE__ */ jsxs("div", { className: `${styles.labelRow} dbc-flex dbc-items-center dbc-gap-xs`, children: [
|
|
22
22
|
label && /* @__PURE__ */ jsxs("label", { className: styles.label, htmlFor, children: [
|
|
23
23
|
label,
|
|
24
24
|
required && /* @__PURE__ */ jsx("span", { className: styles.required, children: " *" })
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
|
-
var lucideReact = require('lucide-react');
|
|
6
5
|
var react = require('react');
|
|
7
6
|
var useTooltipTrigger = require('../../../components/overlay/tooltip/useTooltipTrigger');
|
|
8
7
|
var styles = require('./Select.module.css');
|
|
@@ -18,6 +17,7 @@ var styles__default = /*#__PURE__*/_interopDefault(styles);
|
|
|
18
17
|
|
|
19
18
|
function Select({
|
|
20
19
|
label,
|
|
20
|
+
labelAction,
|
|
21
21
|
error,
|
|
22
22
|
helpText,
|
|
23
23
|
orientation = "vertical",
|
|
@@ -46,6 +46,7 @@ function Select({
|
|
|
46
46
|
const describedById = `${controlId}-desc`;
|
|
47
47
|
const listboxId = `${controlId}-listbox`;
|
|
48
48
|
const popoverRef = react.useRef(null);
|
|
49
|
+
const triggerRef = react.useRef(null);
|
|
49
50
|
const optionRefs = react.useRef([]);
|
|
50
51
|
const typeaheadRef = react.useRef("");
|
|
51
52
|
const typeaheadTimeoutRef = react.useRef(null);
|
|
@@ -61,9 +62,15 @@ function Select({
|
|
|
61
62
|
};
|
|
62
63
|
}, []);
|
|
63
64
|
react.useEffect(() => {
|
|
64
|
-
var _a;
|
|
65
65
|
if (!open) return;
|
|
66
|
-
|
|
66
|
+
const focusActive = () => {
|
|
67
|
+
var _a, _b, _c;
|
|
68
|
+
(_a = optionRefs.current[activeIndex]) == null ? void 0 : _a.focus();
|
|
69
|
+
(_c = (_b = optionRefs.current[activeIndex]) == null ? void 0 : _b.scrollIntoView) == null ? void 0 : _c.call(_b, { block: "nearest" });
|
|
70
|
+
};
|
|
71
|
+
focusActive();
|
|
72
|
+
const frame = requestAnimationFrame(focusActive);
|
|
73
|
+
return () => cancelAnimationFrame(frame);
|
|
67
74
|
}, [activeIndex, open]);
|
|
68
75
|
const resetActiveToSelected = () => setActiveIndex(selectedIndex >= 0 ? selectedIndex : 0);
|
|
69
76
|
const findTypeaheadMatch = (query, startIndex) => {
|
|
@@ -99,25 +106,30 @@ function Select({
|
|
|
99
106
|
if (!open) setOpen(true);
|
|
100
107
|
};
|
|
101
108
|
const handleKeyDown = (e) => {
|
|
102
|
-
var _a, _b;
|
|
109
|
+
var _a, _b, _c, _d, _e;
|
|
103
110
|
if (e.key.length === 1 && !e.altKey && !e.ctrlKey && !e.metaKey && !/\s/.test(e.key)) {
|
|
104
111
|
e.preventDefault();
|
|
105
112
|
handleTypeahead(e.key);
|
|
106
113
|
return;
|
|
107
114
|
}
|
|
108
115
|
switch (e.key) {
|
|
109
|
-
case "ArrowDown":
|
|
110
|
-
e.preventDefault();
|
|
111
|
-
if (!open) {
|
|
112
|
-
setOpen(true);
|
|
113
|
-
}
|
|
114
|
-
break;
|
|
115
|
-
}
|
|
116
|
+
case "ArrowDown":
|
|
116
117
|
case "ArrowUp": {
|
|
117
118
|
e.preventDefault();
|
|
119
|
+
e.stopPropagation();
|
|
118
120
|
if (!open) {
|
|
121
|
+
resetActiveToSelected();
|
|
119
122
|
setOpen(true);
|
|
123
|
+
break;
|
|
120
124
|
}
|
|
125
|
+
if (options.length === 0) break;
|
|
126
|
+
const nextIndex = Math.max(
|
|
127
|
+
0,
|
|
128
|
+
Math.min(activeIndex + (e.key === "ArrowDown" ? 1 : -1), options.length - 1)
|
|
129
|
+
);
|
|
130
|
+
setActiveIndex(nextIndex);
|
|
131
|
+
(_a = optionRefs.current[nextIndex]) == null ? void 0 : _a.focus();
|
|
132
|
+
(_c = (_b = optionRefs.current[nextIndex]) == null ? void 0 : _b.scrollIntoView) == null ? void 0 : _c.call(_b, { block: "nearest" });
|
|
121
133
|
break;
|
|
122
134
|
}
|
|
123
135
|
case "Enter":
|
|
@@ -129,20 +141,21 @@ function Select({
|
|
|
129
141
|
typeaheadTimeoutRef.current = null;
|
|
130
142
|
}
|
|
131
143
|
if (!open) {
|
|
144
|
+
resetActiveToSelected();
|
|
132
145
|
setOpen(true);
|
|
133
146
|
return;
|
|
134
147
|
}
|
|
135
148
|
const opt = options[activeIndex];
|
|
136
149
|
if (opt) {
|
|
137
150
|
onChange(opt.value);
|
|
138
|
-
(
|
|
151
|
+
(_d = popoverRef.current) == null ? void 0 : _d.close();
|
|
139
152
|
}
|
|
140
153
|
break;
|
|
141
154
|
}
|
|
142
155
|
case "Escape": {
|
|
143
156
|
if (!open) return;
|
|
144
157
|
e.preventDefault();
|
|
145
|
-
(
|
|
158
|
+
(_e = popoverRef.current) == null ? void 0 : _e.close();
|
|
146
159
|
break;
|
|
147
160
|
}
|
|
148
161
|
case "Home": {
|
|
@@ -176,6 +189,7 @@ function Select({
|
|
|
176
189
|
InputContainer.InputContainer,
|
|
177
190
|
{
|
|
178
191
|
label,
|
|
192
|
+
labelAction,
|
|
179
193
|
htmlFor: controlId,
|
|
180
194
|
fullWidth,
|
|
181
195
|
error,
|
|
@@ -189,6 +203,7 @@ function Select({
|
|
|
189
203
|
Popover.Popover,
|
|
190
204
|
{
|
|
191
205
|
ref: popoverRef,
|
|
206
|
+
anchorRef: triggerRef,
|
|
192
207
|
open,
|
|
193
208
|
fullWidth,
|
|
194
209
|
onOpenChange: (next) => {
|
|
@@ -203,6 +218,10 @@ function Select({
|
|
|
203
218
|
{
|
|
204
219
|
disabled,
|
|
205
220
|
...tooltipEnabled ? triggerProps : {},
|
|
221
|
+
ref: (node) => {
|
|
222
|
+
triggerRef.current = node;
|
|
223
|
+
if (tooltipEnabled) triggerProps.ref(node);
|
|
224
|
+
},
|
|
206
225
|
id: controlId,
|
|
207
226
|
"data-cy": dataCy != null ? dataCy : "select-button",
|
|
208
227
|
onKeyDown: handleKeyDown,
|
|
@@ -246,7 +265,7 @@ function Select({
|
|
|
246
265
|
)
|
|
247
266
|
}
|
|
248
267
|
),
|
|
249
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(Menu.Menu, {
|
|
268
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(Menu.Menu, { onKeyDownCapture: handleKeyDown, role: "listbox", className: styles__default.default.menu, children: [
|
|
250
269
|
menuHeader ? /* @__PURE__ */ jsxRuntime.jsx(Menu.Menu.Header, { children: menuHeader }) : null,
|
|
251
270
|
options.map((opt, index) => {
|
|
252
271
|
const isSelected = typeof opt.value === "object" && typeof selectedValue === "object" && datakey ? (selectedValue == null ? void 0 : selectedValue[datakey]) === opt.value[datakey] : opt.value === selectedValue;
|
|
@@ -258,7 +277,7 @@ function Select({
|
|
|
258
277
|
selected: isSelected,
|
|
259
278
|
itemRole: "option",
|
|
260
279
|
className: isSelected ? styles__default.default.selectedOption : void 0,
|
|
261
|
-
children: /* @__PURE__ */ jsxRuntime.
|
|
280
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
262
281
|
"button",
|
|
263
282
|
{
|
|
264
283
|
ref: (el) => {
|
|
@@ -273,10 +292,7 @@ function Select({
|
|
|
273
292
|
},
|
|
274
293
|
onFocus: () => setActiveIndex(index),
|
|
275
294
|
style: { display: "flex", alignItems: "center", width: "100%" },
|
|
276
|
-
children:
|
|
277
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { width: 16, display: "inline-flex", justifyContent: "center" }, children: isSelected ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, {}) : null }),
|
|
278
|
-
opt.label
|
|
279
|
-
]
|
|
295
|
+
children: opt.label
|
|
280
296
|
}
|
|
281
297
|
)
|
|
282
298
|
},
|
|
@@ -20,5 +20,5 @@ export type SelectProps<T> = Omit<InputContainerProps, 'children' | 'htmlFor' |
|
|
|
20
20
|
tooltip?: React.ReactNode;
|
|
21
21
|
tooltipPlacement?: 'top' | 'right' | 'bottom' | 'left';
|
|
22
22
|
};
|
|
23
|
-
export declare function Select<T extends string | number | Record<string, any>>({ label, error, helpText, orientation, labelWidth, fullWidth, required, tooltip, tooltipPlacement, modified, id, options, selectedValue, onChange, placeholder, size, variant, onClear, datakey, dataCy, disabled, minWidth, menuHeader, }: SelectProps<T>): React.ReactNode;
|
|
23
|
+
export declare function Select<T extends string | number | Record<string, any>>({ label, labelAction, error, helpText, orientation, labelWidth, fullWidth, required, tooltip, tooltipPlacement, modified, id, options, selectedValue, onChange, placeholder, size, variant, onClear, datakey, dataCy, disabled, minWidth, menuHeader, }: SelectProps<T>): React.ReactNode;
|
|
24
24
|
export {};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
-
import { Check } from 'lucide-react';
|
|
4
3
|
import { useId, useRef, useMemo, useState, useEffect } from 'react';
|
|
5
4
|
import { useTooltipTrigger } from '../../../components/overlay/tooltip/useTooltipTrigger';
|
|
6
5
|
import styles from './Select.module.css';
|
|
@@ -12,6 +11,7 @@ import { InputContainer } from '../input-container/InputContainer';
|
|
|
12
11
|
|
|
13
12
|
function Select({
|
|
14
13
|
label,
|
|
14
|
+
labelAction,
|
|
15
15
|
error,
|
|
16
16
|
helpText,
|
|
17
17
|
orientation = "vertical",
|
|
@@ -40,6 +40,7 @@ function Select({
|
|
|
40
40
|
const describedById = `${controlId}-desc`;
|
|
41
41
|
const listboxId = `${controlId}-listbox`;
|
|
42
42
|
const popoverRef = useRef(null);
|
|
43
|
+
const triggerRef = useRef(null);
|
|
43
44
|
const optionRefs = useRef([]);
|
|
44
45
|
const typeaheadRef = useRef("");
|
|
45
46
|
const typeaheadTimeoutRef = useRef(null);
|
|
@@ -55,9 +56,15 @@ function Select({
|
|
|
55
56
|
};
|
|
56
57
|
}, []);
|
|
57
58
|
useEffect(() => {
|
|
58
|
-
var _a;
|
|
59
59
|
if (!open) return;
|
|
60
|
-
|
|
60
|
+
const focusActive = () => {
|
|
61
|
+
var _a, _b, _c;
|
|
62
|
+
(_a = optionRefs.current[activeIndex]) == null ? void 0 : _a.focus();
|
|
63
|
+
(_c = (_b = optionRefs.current[activeIndex]) == null ? void 0 : _b.scrollIntoView) == null ? void 0 : _c.call(_b, { block: "nearest" });
|
|
64
|
+
};
|
|
65
|
+
focusActive();
|
|
66
|
+
const frame = requestAnimationFrame(focusActive);
|
|
67
|
+
return () => cancelAnimationFrame(frame);
|
|
61
68
|
}, [activeIndex, open]);
|
|
62
69
|
const resetActiveToSelected = () => setActiveIndex(selectedIndex >= 0 ? selectedIndex : 0);
|
|
63
70
|
const findTypeaheadMatch = (query, startIndex) => {
|
|
@@ -93,25 +100,30 @@ function Select({
|
|
|
93
100
|
if (!open) setOpen(true);
|
|
94
101
|
};
|
|
95
102
|
const handleKeyDown = (e) => {
|
|
96
|
-
var _a, _b;
|
|
103
|
+
var _a, _b, _c, _d, _e;
|
|
97
104
|
if (e.key.length === 1 && !e.altKey && !e.ctrlKey && !e.metaKey && !/\s/.test(e.key)) {
|
|
98
105
|
e.preventDefault();
|
|
99
106
|
handleTypeahead(e.key);
|
|
100
107
|
return;
|
|
101
108
|
}
|
|
102
109
|
switch (e.key) {
|
|
103
|
-
case "ArrowDown":
|
|
104
|
-
e.preventDefault();
|
|
105
|
-
if (!open) {
|
|
106
|
-
setOpen(true);
|
|
107
|
-
}
|
|
108
|
-
break;
|
|
109
|
-
}
|
|
110
|
+
case "ArrowDown":
|
|
110
111
|
case "ArrowUp": {
|
|
111
112
|
e.preventDefault();
|
|
113
|
+
e.stopPropagation();
|
|
112
114
|
if (!open) {
|
|
115
|
+
resetActiveToSelected();
|
|
113
116
|
setOpen(true);
|
|
117
|
+
break;
|
|
114
118
|
}
|
|
119
|
+
if (options.length === 0) break;
|
|
120
|
+
const nextIndex = Math.max(
|
|
121
|
+
0,
|
|
122
|
+
Math.min(activeIndex + (e.key === "ArrowDown" ? 1 : -1), options.length - 1)
|
|
123
|
+
);
|
|
124
|
+
setActiveIndex(nextIndex);
|
|
125
|
+
(_a = optionRefs.current[nextIndex]) == null ? void 0 : _a.focus();
|
|
126
|
+
(_c = (_b = optionRefs.current[nextIndex]) == null ? void 0 : _b.scrollIntoView) == null ? void 0 : _c.call(_b, { block: "nearest" });
|
|
115
127
|
break;
|
|
116
128
|
}
|
|
117
129
|
case "Enter":
|
|
@@ -123,20 +135,21 @@ function Select({
|
|
|
123
135
|
typeaheadTimeoutRef.current = null;
|
|
124
136
|
}
|
|
125
137
|
if (!open) {
|
|
138
|
+
resetActiveToSelected();
|
|
126
139
|
setOpen(true);
|
|
127
140
|
return;
|
|
128
141
|
}
|
|
129
142
|
const opt = options[activeIndex];
|
|
130
143
|
if (opt) {
|
|
131
144
|
onChange(opt.value);
|
|
132
|
-
(
|
|
145
|
+
(_d = popoverRef.current) == null ? void 0 : _d.close();
|
|
133
146
|
}
|
|
134
147
|
break;
|
|
135
148
|
}
|
|
136
149
|
case "Escape": {
|
|
137
150
|
if (!open) return;
|
|
138
151
|
e.preventDefault();
|
|
139
|
-
(
|
|
152
|
+
(_e = popoverRef.current) == null ? void 0 : _e.close();
|
|
140
153
|
break;
|
|
141
154
|
}
|
|
142
155
|
case "Home": {
|
|
@@ -170,6 +183,7 @@ function Select({
|
|
|
170
183
|
InputContainer,
|
|
171
184
|
{
|
|
172
185
|
label,
|
|
186
|
+
labelAction,
|
|
173
187
|
htmlFor: controlId,
|
|
174
188
|
fullWidth,
|
|
175
189
|
error,
|
|
@@ -183,6 +197,7 @@ function Select({
|
|
|
183
197
|
Popover,
|
|
184
198
|
{
|
|
185
199
|
ref: popoverRef,
|
|
200
|
+
anchorRef: triggerRef,
|
|
186
201
|
open,
|
|
187
202
|
fullWidth,
|
|
188
203
|
onOpenChange: (next) => {
|
|
@@ -197,6 +212,10 @@ function Select({
|
|
|
197
212
|
{
|
|
198
213
|
disabled,
|
|
199
214
|
...tooltipEnabled ? triggerProps : {},
|
|
215
|
+
ref: (node) => {
|
|
216
|
+
triggerRef.current = node;
|
|
217
|
+
if (tooltipEnabled) triggerProps.ref(node);
|
|
218
|
+
},
|
|
200
219
|
id: controlId,
|
|
201
220
|
"data-cy": dataCy != null ? dataCy : "select-button",
|
|
202
221
|
onKeyDown: handleKeyDown,
|
|
@@ -240,7 +259,7 @@ function Select({
|
|
|
240
259
|
)
|
|
241
260
|
}
|
|
242
261
|
),
|
|
243
|
-
children: /* @__PURE__ */ jsxs(Menu, {
|
|
262
|
+
children: /* @__PURE__ */ jsxs(Menu, { onKeyDownCapture: handleKeyDown, role: "listbox", className: styles.menu, children: [
|
|
244
263
|
menuHeader ? /* @__PURE__ */ jsx(Menu.Header, { children: menuHeader }) : null,
|
|
245
264
|
options.map((opt, index) => {
|
|
246
265
|
const isSelected = typeof opt.value === "object" && typeof selectedValue === "object" && datakey ? (selectedValue == null ? void 0 : selectedValue[datakey]) === opt.value[datakey] : opt.value === selectedValue;
|
|
@@ -252,7 +271,7 @@ function Select({
|
|
|
252
271
|
selected: isSelected,
|
|
253
272
|
itemRole: "option",
|
|
254
273
|
className: isSelected ? styles.selectedOption : void 0,
|
|
255
|
-
children: /* @__PURE__ */
|
|
274
|
+
children: /* @__PURE__ */ jsx(
|
|
256
275
|
"button",
|
|
257
276
|
{
|
|
258
277
|
ref: (el) => {
|
|
@@ -267,10 +286,7 @@ function Select({
|
|
|
267
286
|
},
|
|
268
287
|
onFocus: () => setActiveIndex(index),
|
|
269
288
|
style: { display: "flex", alignItems: "center", width: "100%" },
|
|
270
|
-
children:
|
|
271
|
-
/* @__PURE__ */ jsx("span", { style: { width: 16, display: "inline-flex", justifyContent: "center" }, children: isSelected ? /* @__PURE__ */ jsx(Check, {}) : null }),
|
|
272
|
-
opt.label
|
|
273
|
-
]
|
|
289
|
+
children: opt.label
|
|
274
290
|
}
|
|
275
291
|
)
|
|
276
292
|
},
|
|
@@ -225,6 +225,7 @@ const Popover = React.forwardRef(function Popover2({
|
|
|
225
225
|
if (!isOpen) return;
|
|
226
226
|
const content = contentRef.current;
|
|
227
227
|
if (!content) return;
|
|
228
|
+
if (anchorRef == null ? void 0 : anchorRef.current) triggerElRef.current = anchorRef.current;
|
|
228
229
|
const triggerEl = (_b = (_a = anchorRef == null ? void 0 : anchorRef.current) != null ? _a : triggerElRef.current) != null ? _b : containerRef.current;
|
|
229
230
|
if (autoFocusContent) {
|
|
230
231
|
const focusables = getFocusable(content);
|
|
@@ -201,6 +201,7 @@ const Popover = forwardRef(function Popover2({
|
|
|
201
201
|
if (!isOpen) return;
|
|
202
202
|
const content = contentRef.current;
|
|
203
203
|
if (!content) return;
|
|
204
|
+
if (anchorRef == null ? void 0 : anchorRef.current) triggerElRef.current = anchorRef.current;
|
|
204
205
|
const triggerEl = (_b = (_a = anchorRef == null ? void 0 : anchorRef.current) != null ? _a : triggerElRef.current) != null ? _b : containerRef.current;
|
|
205
206
|
if (autoFocusContent) {
|
|
206
207
|
const focusables = getFocusable(content);
|