@equinor/eds-core-react 2.3.7 → 2.4.0-beta.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/build/index.css +389 -39
- package/build/index.min.css +1 -1
- package/dist/eds-core-react.cjs +29 -23
- package/dist/esm/components/Autocomplete/AutocompleteContext.js +2 -2
- package/dist/esm/components/Autocomplete/MultipleInput.js +2 -2
- package/dist/esm/components/Autocomplete/OptionList.js +6 -4
- package/dist/esm/components/Autocomplete/useAutocomplete.js +4 -0
- package/dist/esm/components/Datepicker/calendars/CalendarGrid.js +4 -8
- package/dist/esm/components/Datepicker/calendars/CalendarHeader.js +6 -6
- package/dist/esm/components/Datepicker/fields/DateSegment.js +4 -1
- package/dist/esm/components/InputWrapper/InputWrapper.js +1 -1
- package/dist/esm/components/Popover/Popover.js +4 -4
- package/dist/esm/components/Textarea/Textarea.js +1 -1
- package/dist/esm-next/components/next/Banner/Banner.js +88 -0
- package/dist/esm-next/components/next/Button/Button.js +1 -0
- package/dist/esm-next/components/next/Icon/Icon.js +27 -1
- package/dist/esm-next/components/next/Input/Input.js +1 -1
- package/dist/esm-next/components/next/Link/Link.js +24 -0
- package/dist/esm-next/components/next/Search/Search.js +118 -0
- package/dist/esm-next/components/next/TextArea/TextArea.js +131 -0
- package/dist/esm-next/components/next/Tooltip/Tooltip.js +84 -0
- package/dist/esm-next/index.next.js +5 -0
- package/dist/index.next.cjs +445 -6
- package/dist/types/components/Autocomplete/AutocompleteContext.d.ts +2 -2
- package/dist/types/components/Autocomplete/useAutocomplete.d.ts +2 -2
- package/dist/types/components/next/Banner/Banner.d.ts +23 -0
- package/dist/types/components/next/Banner/Banner.figma.d.ts +1 -0
- package/dist/types/components/next/Banner/Banner.types.d.ts +33 -0
- package/dist/types/components/next/Banner/index.d.ts +2 -0
- package/dist/types/components/next/Icon/Icon.d.ts +0 -1
- package/dist/types/components/next/Input/Input.types.d.ts +4 -1
- package/dist/types/components/next/Link/Link.d.ts +4 -0
- package/dist/types/components/next/Link/Link.figma.d.ts +1 -0
- package/dist/types/components/next/Link/Link.types.d.ts +11 -0
- package/dist/types/components/next/Link/index.d.ts +2 -0
- package/dist/types/components/next/Search/Search.d.ts +9 -0
- package/dist/types/components/next/Search/Search.figma.d.ts +1 -0
- package/dist/types/components/next/Search/Search.types.d.ts +16 -0
- package/dist/types/components/next/Search/index.d.ts +2 -0
- package/dist/types/components/next/TextArea/TextArea.d.ts +11 -0
- package/dist/types/components/next/TextArea/TextArea.figma.d.ts +1 -0
- package/dist/types/components/next/TextArea/TextArea.types.d.ts +21 -0
- package/dist/types/components/next/TextArea/index.d.ts +2 -0
- package/dist/types/components/next/Tooltip/Tooltip.d.ts +7 -0
- package/dist/types/components/next/Tooltip/Tooltip.figma.d.ts +1 -0
- package/dist/types/components/next/Tooltip/Tooltip.types.d.ts +17 -0
- package/dist/types/components/next/Tooltip/index.d.ts +2 -0
- package/dist/types/components/next/index.d.ts +10 -0
- package/package.json +41 -34
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { forwardRef, useId, useRef, cloneElement } from 'react';
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
const Tooltip = /*#__PURE__*/forwardRef(function Tooltip({
|
|
5
|
+
title,
|
|
6
|
+
placement = 'top',
|
|
7
|
+
disabled,
|
|
8
|
+
children,
|
|
9
|
+
className,
|
|
10
|
+
onMouseEnter: onMouseEnterProp,
|
|
11
|
+
onMouseLeave: onMouseLeaveProp,
|
|
12
|
+
...rest
|
|
13
|
+
}, ref) {
|
|
14
|
+
const uid = useId();
|
|
15
|
+
const tooltipId = `eds-tooltip-${uid.replace(/:/g, '')}`;
|
|
16
|
+
const anchorName = `--${tooltipId}`;
|
|
17
|
+
const tooltipRef = useRef(null);
|
|
18
|
+
const hideTimer = useRef(null);
|
|
19
|
+
const active = Boolean(title) && !disabled;
|
|
20
|
+
const show = () => {
|
|
21
|
+
if (hideTimer.current) clearTimeout(hideTimer.current);
|
|
22
|
+
if (!tooltipRef.current?.matches(':popover-open')) {
|
|
23
|
+
tooltipRef.current?.showPopover();
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// Short delay so mouse can travel from trigger to tooltip (WCAG 1.4.13 — hoverable)
|
|
28
|
+
const hide = () => {
|
|
29
|
+
hideTimer.current = setTimeout(() => {
|
|
30
|
+
if (tooltipRef.current?.matches(':popover-open')) {
|
|
31
|
+
tooltipRef.current.hidePopover();
|
|
32
|
+
}
|
|
33
|
+
}, 100);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// Merge forwarded ref with internal ref
|
|
37
|
+
const setRef = node => {
|
|
38
|
+
tooltipRef.current = node;
|
|
39
|
+
if (typeof ref === 'function') ref(node);else if (ref) ref.current = node;
|
|
40
|
+
};
|
|
41
|
+
if (!active) return children;
|
|
42
|
+
return /*#__PURE__*/jsxs("span", {
|
|
43
|
+
className: "eds-tooltip-anchor",
|
|
44
|
+
style: {
|
|
45
|
+
'--tooltip-anchor-name': anchorName
|
|
46
|
+
},
|
|
47
|
+
onMouseEnter: show,
|
|
48
|
+
onMouseLeave: hide,
|
|
49
|
+
onFocus: show,
|
|
50
|
+
onBlur: hide,
|
|
51
|
+
children: [/*#__PURE__*/cloneElement(children, {
|
|
52
|
+
'aria-describedby': tooltipId
|
|
53
|
+
}), /*#__PURE__*/jsx("div", {
|
|
54
|
+
ref: setRef,
|
|
55
|
+
id: tooltipId,
|
|
56
|
+
role: "tooltip"
|
|
57
|
+
// hint: top-layer + Escape/light-dismiss. Safari falls back to manual (no Escape).
|
|
58
|
+
,
|
|
59
|
+
popover: "hint",
|
|
60
|
+
className: ['eds-tooltip', className].filter(Boolean).join(' '),
|
|
61
|
+
"data-placement": placement,
|
|
62
|
+
"data-space-proportions": "squished",
|
|
63
|
+
...rest,
|
|
64
|
+
onMouseEnter: e => {
|
|
65
|
+
if (hideTimer.current) clearTimeout(hideTimer.current);
|
|
66
|
+
onMouseEnterProp?.(e);
|
|
67
|
+
},
|
|
68
|
+
onMouseLeave: e => {
|
|
69
|
+
hide();
|
|
70
|
+
onMouseLeaveProp?.(e);
|
|
71
|
+
},
|
|
72
|
+
children: /*#__PURE__*/jsx("span", {
|
|
73
|
+
className: "label",
|
|
74
|
+
"data-font-family": "ui",
|
|
75
|
+
"data-font-size": "sm",
|
|
76
|
+
"data-baseline": "center",
|
|
77
|
+
children: title
|
|
78
|
+
})
|
|
79
|
+
})]
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
Tooltip.displayName = 'Tooltip';
|
|
83
|
+
|
|
84
|
+
export { Tooltip };
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
export { Banner } from './components/next/Banner/Banner.js';
|
|
1
2
|
export { Button } from './components/next/Button/Button.js';
|
|
2
3
|
export { Checkbox } from './components/next/Checkbox/Checkbox.js';
|
|
3
4
|
export { Field } from './components/next/Field/Field.js';
|
|
4
5
|
export { Icon } from './components/next/Icon/Icon.js';
|
|
5
6
|
export { Input } from './components/next/Input/Input.js';
|
|
7
|
+
export { Link } from './components/next/Link/Link.js';
|
|
6
8
|
export { Radio } from './components/next/Radio/Radio.js';
|
|
9
|
+
export { Search } from './components/next/Search/Search.js';
|
|
7
10
|
export { Switch } from './components/next/Switch/Switch.js';
|
|
11
|
+
export { TextArea } from './components/next/TextArea/TextArea.js';
|
|
8
12
|
export { TextField } from './components/next/TextField/TextField.js';
|
|
13
|
+
export { Tooltip } from './components/next/Tooltip/Tooltip.js';
|
|
9
14
|
export { useFieldIds } from './components/next/Field/useFieldIds.js';
|
package/dist/index.next.cjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var react = require('react');
|
|
4
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
5
4
|
var edsIcons = require('@equinor/eds-icons');
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
var edsUtils = require('@equinor/eds-utils');
|
|
6
7
|
var reactDom = require('react-dom');
|
|
7
8
|
var styled = require('styled-components');
|
|
8
|
-
var edsUtils = require('@equinor/eds-utils');
|
|
9
9
|
var edsTokens = require('@equinor/eds-tokens');
|
|
10
10
|
var react$1 = require('@floating-ui/react');
|
|
11
11
|
|
|
@@ -112,6 +112,7 @@ const Button = /*#__PURE__*/react.forwardRef(function Button({
|
|
|
112
112
|
...rest,
|
|
113
113
|
children: icon ? children : /*#__PURE__*/jsxRuntime.jsx(TypographyNext, {
|
|
114
114
|
as: "span",
|
|
115
|
+
className: "eds-button__label",
|
|
115
116
|
family: "ui",
|
|
116
117
|
size: typographySize,
|
|
117
118
|
lineHeight: "squished",
|
|
@@ -122,6 +123,32 @@ const Button = /*#__PURE__*/react.forwardRef(function Button({
|
|
|
122
123
|
});
|
|
123
124
|
Button.displayName = 'Button';
|
|
124
125
|
|
|
126
|
+
/**
|
|
127
|
+
* Icon component for EDS 2.0
|
|
128
|
+
*
|
|
129
|
+
* Features:
|
|
130
|
+
* - Automatic sizing from parent's data-font-size via --eds-typography-icon-size
|
|
131
|
+
* - Dynamic fallback sizing (1.5em) when no tokens are set
|
|
132
|
+
* - Explicit size prop for standalone usage
|
|
133
|
+
* - WCAG 2.1 AA accessible with optional title for semantic icons
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```tsx
|
|
137
|
+
* import { Icon } from '@equinor/eds-core-react/next'
|
|
138
|
+
* import { save } from '@equinor/eds-icons'
|
|
139
|
+
*
|
|
140
|
+
* // Auto-sized from parent's data-font-size
|
|
141
|
+
* <div data-font-size="md">
|
|
142
|
+
* <Icon data={warning} /> Error message
|
|
143
|
+
* </div>
|
|
144
|
+
*
|
|
145
|
+
* // Explicit size for standalone usage
|
|
146
|
+
* <Icon data={save} size="lg" />
|
|
147
|
+
*
|
|
148
|
+
* // Semantic icon with accessible name
|
|
149
|
+
* <Icon data={save} title="Save document" />
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
125
152
|
const Icon = /*#__PURE__*/react.forwardRef(function Icon({
|
|
126
153
|
data,
|
|
127
154
|
title,
|
|
@@ -140,7 +167,7 @@ const Icon = /*#__PURE__*/react.forwardRef(function Icon({
|
|
|
140
167
|
height = '24',
|
|
141
168
|
width = '24'
|
|
142
169
|
} = data;
|
|
143
|
-
const classes = ['icon', className].filter(Boolean).join(' ');
|
|
170
|
+
const classes = ['eds-icon', className].filter(Boolean).join(' ');
|
|
144
171
|
|
|
145
172
|
// Accessibility: decorative icons are hidden, semantic icons have role="img"
|
|
146
173
|
const accessibilityProps = title ? {
|
|
@@ -582,7 +609,7 @@ const Input = /*#__PURE__*/react.forwardRef(function Input({
|
|
|
582
609
|
})]
|
|
583
610
|
}), /*#__PURE__*/jsxRuntime.jsx(Component, {
|
|
584
611
|
ref: ref,
|
|
585
|
-
type: type,
|
|
612
|
+
type: Component === 'textarea' ? undefined : type,
|
|
586
613
|
disabled: disabled,
|
|
587
614
|
readOnly: readOnly,
|
|
588
615
|
className: ['eds-input', className].filter(Boolean).join(' '),
|
|
@@ -682,7 +709,7 @@ const TooltipArrow = styled__default.default.svg.withConfig({
|
|
|
682
709
|
displayName: "Tooltip__TooltipArrow",
|
|
683
710
|
componentId: "sc-m2im2p-2"
|
|
684
711
|
})(["width:", ";height:", ";position:absolute;fill:", ";"], tooltip.entities.arrow.width, tooltip.entities.arrow.height, tooltip.background);
|
|
685
|
-
const Tooltip = /*#__PURE__*/react.forwardRef(function Tooltip({
|
|
712
|
+
const Tooltip$1 = /*#__PURE__*/react.forwardRef(function Tooltip({
|
|
686
713
|
title,
|
|
687
714
|
placement = 'bottom',
|
|
688
715
|
children,
|
|
@@ -835,7 +862,7 @@ const TextField = /*#__PURE__*/react.forwardRef(function TextField({
|
|
|
835
862
|
htmlFor: inputId,
|
|
836
863
|
indicator: indicator,
|
|
837
864
|
children: label
|
|
838
|
-
}), labelInfo && /*#__PURE__*/jsxRuntime.jsx(Tooltip, {
|
|
865
|
+
}), labelInfo && /*#__PURE__*/jsxRuntime.jsx(Tooltip$1, {
|
|
839
866
|
title: labelInfo,
|
|
840
867
|
placement: "top",
|
|
841
868
|
children: /*#__PURE__*/jsxRuntime.jsx(Button, {
|
|
@@ -873,12 +900,424 @@ const TextField = /*#__PURE__*/react.forwardRef(function TextField({
|
|
|
873
900
|
});
|
|
874
901
|
});
|
|
875
902
|
|
|
903
|
+
const TextArea = /*#__PURE__*/react.forwardRef(function TextArea({
|
|
904
|
+
label,
|
|
905
|
+
labelInfo,
|
|
906
|
+
indicator,
|
|
907
|
+
description,
|
|
908
|
+
helperMessage,
|
|
909
|
+
id: providedId,
|
|
910
|
+
invalid,
|
|
911
|
+
disabled,
|
|
912
|
+
maxRows,
|
|
913
|
+
showCharacterCount,
|
|
914
|
+
...textareaProps
|
|
915
|
+
}, ref) {
|
|
916
|
+
const {
|
|
917
|
+
inputId,
|
|
918
|
+
descriptionId,
|
|
919
|
+
helperMessageId,
|
|
920
|
+
getDescribedBy
|
|
921
|
+
} = useFieldIds(providedId);
|
|
922
|
+
const [charCount, setCharCount] = react.useState(() => String(textareaProps.value ?? textareaProps.defaultValue ?? '').length);
|
|
923
|
+
react.useEffect(() => {
|
|
924
|
+
if (textareaProps.value !== undefined) {
|
|
925
|
+
setCharCount(String(textareaProps.value).length);
|
|
926
|
+
}
|
|
927
|
+
}, [textareaProps.value]);
|
|
928
|
+
const {
|
|
929
|
+
maxLength,
|
|
930
|
+
onChange: onChangeProp,
|
|
931
|
+
...restTextareaProps
|
|
932
|
+
} = textareaProps;
|
|
933
|
+
const handleChange = e => {
|
|
934
|
+
setCharCount(e.target.value.length);
|
|
935
|
+
onChangeProp?.(e);
|
|
936
|
+
};
|
|
937
|
+
const internalRef = react.useRef(null);
|
|
938
|
+
const [maxPixelHeight, setMaxPixelHeight] = react.useState(undefined);
|
|
939
|
+
|
|
940
|
+
// Auto-grow is always on. When maxRows is set, compute a pixel cap after
|
|
941
|
+
// mount using the element's actual rendered line-height and padding
|
|
942
|
+
// (density-aware). Until the cap is computed (or if maxRows is not set),
|
|
943
|
+
// pass Infinity so the textarea grows without bound.
|
|
944
|
+
const autoResizeHeight = maxRows !== undefined && maxPixelHeight !== undefined ? maxPixelHeight : Infinity;
|
|
945
|
+
const autoResizeRef = edsUtils.useAutoResize(autoResizeHeight);
|
|
946
|
+
react.useEffect(() => {
|
|
947
|
+
if (!maxRows || !internalRef.current) return;
|
|
948
|
+
const el = internalRef.current;
|
|
949
|
+
const updateMaxHeight = () => {
|
|
950
|
+
const style = window.getComputedStyle(el);
|
|
951
|
+
const lineHeight = parseFloat(style.lineHeight);
|
|
952
|
+
const paddingBlockStart = parseFloat(style.paddingBlockStart);
|
|
953
|
+
const paddingBlockEnd = parseFloat(style.paddingBlockEnd);
|
|
954
|
+
setMaxPixelHeight(lineHeight * maxRows + paddingBlockStart + paddingBlockEnd);
|
|
955
|
+
};
|
|
956
|
+
const observer = new ResizeObserver(updateMaxHeight);
|
|
957
|
+
observer.observe(el);
|
|
958
|
+
updateMaxHeight();
|
|
959
|
+
return () => observer.disconnect();
|
|
960
|
+
}, [maxRows]);
|
|
961
|
+
const combinedRef = react.useMemo(() => edsUtils.mergeRefs(ref, autoResizeRef, internalRef), [ref, autoResizeRef, internalRef]);
|
|
962
|
+
const showHelperRow = helperMessage || showCharacterCount;
|
|
963
|
+
return /*#__PURE__*/jsxRuntime.jsxs(Field, {
|
|
964
|
+
className: "eds-text-area",
|
|
965
|
+
disabled: disabled,
|
|
966
|
+
children: [label && /*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
967
|
+
className: "label-row",
|
|
968
|
+
children: [/*#__PURE__*/jsxRuntime.jsx(Field.Label, {
|
|
969
|
+
htmlFor: inputId,
|
|
970
|
+
indicator: indicator,
|
|
971
|
+
children: label
|
|
972
|
+
}), labelInfo && /*#__PURE__*/jsxRuntime.jsx(Tooltip$1, {
|
|
973
|
+
title: labelInfo,
|
|
974
|
+
placement: "top",
|
|
975
|
+
children: /*#__PURE__*/jsxRuntime.jsx(Button, {
|
|
976
|
+
variant: "ghost",
|
|
977
|
+
icon: true,
|
|
978
|
+
round: true,
|
|
979
|
+
size: "small",
|
|
980
|
+
tone: "neutral",
|
|
981
|
+
"aria-label": "More information",
|
|
982
|
+
children: /*#__PURE__*/jsxRuntime.jsx(Icon, {
|
|
983
|
+
data: edsIcons.info_circle,
|
|
984
|
+
size: "xs"
|
|
985
|
+
})
|
|
986
|
+
})
|
|
987
|
+
})]
|
|
988
|
+
}), description && /*#__PURE__*/jsxRuntime.jsx(Field.Description, {
|
|
989
|
+
id: descriptionId,
|
|
990
|
+
children: description
|
|
991
|
+
}), /*#__PURE__*/jsxRuntime.jsx(Input, {
|
|
992
|
+
ref: combinedRef,
|
|
993
|
+
as: "textarea",
|
|
994
|
+
id: inputId,
|
|
995
|
+
disabled: disabled,
|
|
996
|
+
invalid: invalid,
|
|
997
|
+
maxLength: maxLength,
|
|
998
|
+
onChange: handleChange,
|
|
999
|
+
"aria-describedby": getDescribedBy({
|
|
1000
|
+
hasDescription: !!description,
|
|
1001
|
+
hasHelperMessage: !!helperMessage
|
|
1002
|
+
}),
|
|
1003
|
+
...restTextareaProps
|
|
1004
|
+
}), showHelperRow && /*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
1005
|
+
className: "helper-row",
|
|
1006
|
+
children: [helperMessage && /*#__PURE__*/jsxRuntime.jsx(Field.HelperMessage, {
|
|
1007
|
+
id: helperMessageId,
|
|
1008
|
+
role: invalid ? 'alert' : undefined,
|
|
1009
|
+
children: helperMessage
|
|
1010
|
+
}), showCharacterCount && /*#__PURE__*/jsxRuntime.jsx("span", {
|
|
1011
|
+
className: "char-count",
|
|
1012
|
+
"data-font-family": "ui",
|
|
1013
|
+
"data-font-size": "xs",
|
|
1014
|
+
"aria-live": maxLength !== undefined && charCount >= maxLength * 0.8 ? 'polite' : 'off',
|
|
1015
|
+
children: maxLength !== undefined ? `${charCount} / ${maxLength}` : charCount
|
|
1016
|
+
})]
|
|
1017
|
+
})]
|
|
1018
|
+
});
|
|
1019
|
+
});
|
|
1020
|
+
TextArea.displayName = 'TextArea';
|
|
1021
|
+
|
|
1022
|
+
const Search = /*#__PURE__*/react.forwardRef(function Search({
|
|
1023
|
+
label,
|
|
1024
|
+
description,
|
|
1025
|
+
helperMessage,
|
|
1026
|
+
id: providedId,
|
|
1027
|
+
invalid,
|
|
1028
|
+
disabled,
|
|
1029
|
+
readOnly,
|
|
1030
|
+
value,
|
|
1031
|
+
defaultValue,
|
|
1032
|
+
onChange,
|
|
1033
|
+
onClear,
|
|
1034
|
+
clearLabel = 'Clear search',
|
|
1035
|
+
...inputProps
|
|
1036
|
+
}, forwardedRef) {
|
|
1037
|
+
const {
|
|
1038
|
+
inputId,
|
|
1039
|
+
labelId,
|
|
1040
|
+
descriptionId,
|
|
1041
|
+
helperMessageId,
|
|
1042
|
+
getDescribedBy
|
|
1043
|
+
} = useFieldIds(providedId);
|
|
1044
|
+
const isControlled = value !== undefined;
|
|
1045
|
+
const [internalHasValue, setInternalHasValue] = react.useState(() => Boolean(defaultValue));
|
|
1046
|
+
const hasValue = isControlled ? Boolean(value) : internalHasValue;
|
|
1047
|
+
const inputRef = react.useRef(null);
|
|
1048
|
+
const mergedRef = react.useCallback(node => {
|
|
1049
|
+
inputRef.current = node;
|
|
1050
|
+
if (typeof forwardedRef === 'function') {
|
|
1051
|
+
forwardedRef(node);
|
|
1052
|
+
} else if (forwardedRef) {
|
|
1053
|
+
forwardedRef.current = node;
|
|
1054
|
+
}
|
|
1055
|
+
}, [forwardedRef]);
|
|
1056
|
+
const handleChange = e => {
|
|
1057
|
+
if (!isControlled) {
|
|
1058
|
+
setInternalHasValue(Boolean(e.target.value));
|
|
1059
|
+
}
|
|
1060
|
+
onChange?.(e);
|
|
1061
|
+
};
|
|
1062
|
+
const handleClear = () => {
|
|
1063
|
+
if (!isControlled && inputRef.current) {
|
|
1064
|
+
// Direct DOM mutation: bypasses React's synthetic onChange, which is
|
|
1065
|
+
// intentional — onClear is the designated callback for clear actions.
|
|
1066
|
+
inputRef.current.value = '';
|
|
1067
|
+
setInternalHasValue(false);
|
|
1068
|
+
}
|
|
1069
|
+
onClear?.();
|
|
1070
|
+
inputRef.current?.focus();
|
|
1071
|
+
};
|
|
1072
|
+
const showClear = hasValue && !disabled && !readOnly;
|
|
1073
|
+
// Accent only in interactive states — grey in error, readonly, disabled
|
|
1074
|
+
const iconTone = disabled || readOnly || invalid ? 'neutral' : 'accent';
|
|
1075
|
+
return /*#__PURE__*/jsxRuntime.jsx("search", {
|
|
1076
|
+
className: "eds-search",
|
|
1077
|
+
"aria-labelledby": label ? labelId : undefined,
|
|
1078
|
+
children: /*#__PURE__*/jsxRuntime.jsxs(Field, {
|
|
1079
|
+
disabled: disabled,
|
|
1080
|
+
children: [label && /*#__PURE__*/jsxRuntime.jsx(Field.Label, {
|
|
1081
|
+
id: labelId,
|
|
1082
|
+
htmlFor: inputId,
|
|
1083
|
+
children: label
|
|
1084
|
+
}), description && /*#__PURE__*/jsxRuntime.jsx(Field.Description, {
|
|
1085
|
+
id: descriptionId,
|
|
1086
|
+
children: description
|
|
1087
|
+
}), /*#__PURE__*/jsxRuntime.jsx(Input, {
|
|
1088
|
+
ref: mergedRef,
|
|
1089
|
+
id: inputId,
|
|
1090
|
+
type: "search",
|
|
1091
|
+
disabled: disabled,
|
|
1092
|
+
readOnly: readOnly,
|
|
1093
|
+
invalid: invalid,
|
|
1094
|
+
value: value,
|
|
1095
|
+
defaultValue: defaultValue,
|
|
1096
|
+
onChange: handleChange,
|
|
1097
|
+
"aria-describedby": getDescribedBy({
|
|
1098
|
+
hasDescription: !!description,
|
|
1099
|
+
hasHelperMessage: !!helperMessage
|
|
1100
|
+
}),
|
|
1101
|
+
hideErrorIcon: true,
|
|
1102
|
+
startAdornment: /*#__PURE__*/jsxRuntime.jsx(Icon, {
|
|
1103
|
+
data: edsIcons.search,
|
|
1104
|
+
className: "search-icon",
|
|
1105
|
+
"data-color-appearance": iconTone
|
|
1106
|
+
}),
|
|
1107
|
+
endAdornment: showClear ? /*#__PURE__*/jsxRuntime.jsx(Button, {
|
|
1108
|
+
variant: "ghost",
|
|
1109
|
+
icon: true,
|
|
1110
|
+
round: true,
|
|
1111
|
+
size: "small",
|
|
1112
|
+
tone: invalid ? 'neutral' : 'accent',
|
|
1113
|
+
onClick: handleClear,
|
|
1114
|
+
"aria-label": clearLabel,
|
|
1115
|
+
children: /*#__PURE__*/jsxRuntime.jsx(Icon, {
|
|
1116
|
+
data: edsIcons.close
|
|
1117
|
+
})
|
|
1118
|
+
}) : undefined,
|
|
1119
|
+
...inputProps
|
|
1120
|
+
}), helperMessage && /*#__PURE__*/jsxRuntime.jsx(Field.HelperMessage, {
|
|
1121
|
+
id: helperMessageId,
|
|
1122
|
+
role: invalid ? 'alert' : undefined,
|
|
1123
|
+
children: helperMessage
|
|
1124
|
+
})]
|
|
1125
|
+
})
|
|
1126
|
+
});
|
|
1127
|
+
});
|
|
1128
|
+
Search.displayName = 'Search';
|
|
1129
|
+
|
|
1130
|
+
const Link = /*#__PURE__*/react.forwardRef(function Link({
|
|
1131
|
+
variant = 'inline',
|
|
1132
|
+
className,
|
|
1133
|
+
children,
|
|
1134
|
+
...rest
|
|
1135
|
+
}, ref) {
|
|
1136
|
+
const classes = ['eds-link', className].filter(Boolean).join(' ');
|
|
1137
|
+
return /*#__PURE__*/jsxRuntime.jsx("a", {
|
|
1138
|
+
ref: ref,
|
|
1139
|
+
className: classes,
|
|
1140
|
+
"data-variant": variant,
|
|
1141
|
+
"data-font-family": variant === 'standalone' ? 'ui' : undefined,
|
|
1142
|
+
"data-font-size": variant === 'standalone' ? 'md' : undefined,
|
|
1143
|
+
"data-line-height": variant === 'standalone' ? 'squished' : undefined,
|
|
1144
|
+
...rest,
|
|
1145
|
+
children: children
|
|
1146
|
+
});
|
|
1147
|
+
});
|
|
1148
|
+
Link.displayName = 'Link';
|
|
1149
|
+
|
|
1150
|
+
const Tooltip = /*#__PURE__*/react.forwardRef(function Tooltip({
|
|
1151
|
+
title,
|
|
1152
|
+
placement = 'top',
|
|
1153
|
+
disabled,
|
|
1154
|
+
children,
|
|
1155
|
+
className,
|
|
1156
|
+
onMouseEnter: onMouseEnterProp,
|
|
1157
|
+
onMouseLeave: onMouseLeaveProp,
|
|
1158
|
+
...rest
|
|
1159
|
+
}, ref) {
|
|
1160
|
+
const uid = react.useId();
|
|
1161
|
+
const tooltipId = `eds-tooltip-${uid.replace(/:/g, '')}`;
|
|
1162
|
+
const anchorName = `--${tooltipId}`;
|
|
1163
|
+
const tooltipRef = react.useRef(null);
|
|
1164
|
+
const hideTimer = react.useRef(null);
|
|
1165
|
+
const active = Boolean(title) && !disabled;
|
|
1166
|
+
const show = () => {
|
|
1167
|
+
if (hideTimer.current) clearTimeout(hideTimer.current);
|
|
1168
|
+
if (!tooltipRef.current?.matches(':popover-open')) {
|
|
1169
|
+
tooltipRef.current?.showPopover();
|
|
1170
|
+
}
|
|
1171
|
+
};
|
|
1172
|
+
|
|
1173
|
+
// Short delay so mouse can travel from trigger to tooltip (WCAG 1.4.13 — hoverable)
|
|
1174
|
+
const hide = () => {
|
|
1175
|
+
hideTimer.current = setTimeout(() => {
|
|
1176
|
+
if (tooltipRef.current?.matches(':popover-open')) {
|
|
1177
|
+
tooltipRef.current.hidePopover();
|
|
1178
|
+
}
|
|
1179
|
+
}, 100);
|
|
1180
|
+
};
|
|
1181
|
+
|
|
1182
|
+
// Merge forwarded ref with internal ref
|
|
1183
|
+
const setRef = node => {
|
|
1184
|
+
tooltipRef.current = node;
|
|
1185
|
+
if (typeof ref === 'function') ref(node);else if (ref) ref.current = node;
|
|
1186
|
+
};
|
|
1187
|
+
if (!active) return children;
|
|
1188
|
+
return /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
1189
|
+
className: "eds-tooltip-anchor",
|
|
1190
|
+
style: {
|
|
1191
|
+
'--tooltip-anchor-name': anchorName
|
|
1192
|
+
},
|
|
1193
|
+
onMouseEnter: show,
|
|
1194
|
+
onMouseLeave: hide,
|
|
1195
|
+
onFocus: show,
|
|
1196
|
+
onBlur: hide,
|
|
1197
|
+
children: [/*#__PURE__*/react.cloneElement(children, {
|
|
1198
|
+
'aria-describedby': tooltipId
|
|
1199
|
+
}), /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
1200
|
+
ref: setRef,
|
|
1201
|
+
id: tooltipId,
|
|
1202
|
+
role: "tooltip"
|
|
1203
|
+
// hint: top-layer + Escape/light-dismiss. Safari falls back to manual (no Escape).
|
|
1204
|
+
,
|
|
1205
|
+
popover: "hint",
|
|
1206
|
+
className: ['eds-tooltip', className].filter(Boolean).join(' '),
|
|
1207
|
+
"data-placement": placement,
|
|
1208
|
+
"data-space-proportions": "squished",
|
|
1209
|
+
...rest,
|
|
1210
|
+
onMouseEnter: e => {
|
|
1211
|
+
if (hideTimer.current) clearTimeout(hideTimer.current);
|
|
1212
|
+
onMouseEnterProp?.(e);
|
|
1213
|
+
},
|
|
1214
|
+
onMouseLeave: e => {
|
|
1215
|
+
hide();
|
|
1216
|
+
onMouseLeaveProp?.(e);
|
|
1217
|
+
},
|
|
1218
|
+
children: /*#__PURE__*/jsxRuntime.jsx("span", {
|
|
1219
|
+
className: "label",
|
|
1220
|
+
"data-font-family": "ui",
|
|
1221
|
+
"data-font-size": "sm",
|
|
1222
|
+
"data-baseline": "center",
|
|
1223
|
+
children: title
|
|
1224
|
+
})
|
|
1225
|
+
})]
|
|
1226
|
+
});
|
|
1227
|
+
});
|
|
1228
|
+
Tooltip.displayName = 'Tooltip';
|
|
1229
|
+
|
|
1230
|
+
const BannerIcon = /*#__PURE__*/react.forwardRef(function BannerIcon({
|
|
1231
|
+
className,
|
|
1232
|
+
children,
|
|
1233
|
+
...rest
|
|
1234
|
+
}, ref) {
|
|
1235
|
+
return /*#__PURE__*/jsxRuntime.jsx("span", {
|
|
1236
|
+
ref: ref,
|
|
1237
|
+
className: ['eds-banner__icon', className].filter(Boolean).join(' '),
|
|
1238
|
+
...rest,
|
|
1239
|
+
children: children
|
|
1240
|
+
});
|
|
1241
|
+
});
|
|
1242
|
+
const BannerMessage = /*#__PURE__*/react.forwardRef(function BannerMessage({
|
|
1243
|
+
className,
|
|
1244
|
+
children,
|
|
1245
|
+
...rest
|
|
1246
|
+
}, ref) {
|
|
1247
|
+
return /*#__PURE__*/jsxRuntime.jsx(TypographyNext, {
|
|
1248
|
+
ref: ref,
|
|
1249
|
+
as: "p",
|
|
1250
|
+
family: "ui",
|
|
1251
|
+
size: "md",
|
|
1252
|
+
baseline: "center",
|
|
1253
|
+
lineHeight: "default",
|
|
1254
|
+
tracking: "normal",
|
|
1255
|
+
className: ['eds-banner__message', className].filter(Boolean).join(' '),
|
|
1256
|
+
...rest,
|
|
1257
|
+
children: children
|
|
1258
|
+
});
|
|
1259
|
+
});
|
|
1260
|
+
const BannerActions = /*#__PURE__*/react.forwardRef(function BannerActions({
|
|
1261
|
+
placement = 'left',
|
|
1262
|
+
className,
|
|
1263
|
+
children,
|
|
1264
|
+
...rest
|
|
1265
|
+
}, ref) {
|
|
1266
|
+
return /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
1267
|
+
ref: ref,
|
|
1268
|
+
className: ['eds-banner__actions', className].filter(Boolean).join(' '),
|
|
1269
|
+
"data-placement": placement,
|
|
1270
|
+
...rest,
|
|
1271
|
+
children: children
|
|
1272
|
+
});
|
|
1273
|
+
});
|
|
1274
|
+
const BannerComponent = /*#__PURE__*/react.forwardRef(function Banner({
|
|
1275
|
+
tone = 'info',
|
|
1276
|
+
role = 'status',
|
|
1277
|
+
onDismiss,
|
|
1278
|
+
className,
|
|
1279
|
+
children,
|
|
1280
|
+
...rest
|
|
1281
|
+
}, ref) {
|
|
1282
|
+
return /*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
1283
|
+
ref: ref,
|
|
1284
|
+
className: ['eds-banner', className].filter(Boolean).join(' '),
|
|
1285
|
+
"data-color-appearance": tone,
|
|
1286
|
+
role: role,
|
|
1287
|
+
...rest,
|
|
1288
|
+
children: [children, onDismiss && /*#__PURE__*/jsxRuntime.jsx(Button, {
|
|
1289
|
+
variant: "ghost",
|
|
1290
|
+
icon: true,
|
|
1291
|
+
size: "small",
|
|
1292
|
+
className: "eds-banner__dismiss",
|
|
1293
|
+
"aria-label": "Dismiss",
|
|
1294
|
+
onClick: onDismiss,
|
|
1295
|
+
children: /*#__PURE__*/jsxRuntime.jsx(Icon, {
|
|
1296
|
+
data: edsIcons.close
|
|
1297
|
+
})
|
|
1298
|
+
})]
|
|
1299
|
+
});
|
|
1300
|
+
});
|
|
1301
|
+
BannerIcon.displayName = 'Banner.Icon';
|
|
1302
|
+
BannerMessage.displayName = 'Banner.Message';
|
|
1303
|
+
BannerActions.displayName = 'Banner.Actions';
|
|
1304
|
+
BannerComponent.displayName = 'Banner';
|
|
1305
|
+
const Banner = BannerComponent;
|
|
1306
|
+
Banner.Icon = BannerIcon;
|
|
1307
|
+
Banner.Message = BannerMessage;
|
|
1308
|
+
Banner.Actions = BannerActions;
|
|
1309
|
+
|
|
1310
|
+
exports.Banner = Banner;
|
|
876
1311
|
exports.Button = Button;
|
|
877
1312
|
exports.Checkbox = Checkbox;
|
|
878
1313
|
exports.Field = Field;
|
|
879
1314
|
exports.Icon = Icon;
|
|
880
1315
|
exports.Input = Input;
|
|
1316
|
+
exports.Link = Link;
|
|
881
1317
|
exports.Radio = Radio;
|
|
1318
|
+
exports.Search = Search;
|
|
882
1319
|
exports.Switch = Switch;
|
|
1320
|
+
exports.TextArea = TextArea;
|
|
883
1321
|
exports.TextField = TextField;
|
|
1322
|
+
exports.Tooltip = Tooltip;
|
|
884
1323
|
exports.useFieldIds = useFieldIds;
|
|
@@ -94,7 +94,7 @@ export declare const AutocompleteContext: import("react").Context<{
|
|
|
94
94
|
optionLabel?: (option: unknown) => string;
|
|
95
95
|
} & {
|
|
96
96
|
ref?: React.Ref<HTMLInputElement>;
|
|
97
|
-
}, "disabled" | "className" | "style" | "meta" | "label" | "ref" | "multiple" | "variant" | "placeholder" | "readOnly" | "options" | "helperText" | "helperIcon" | "loading" | "optionDisabled" | "totalOptions" | "initialSelectedOptions" | "noOptionsText" | "hideClearButton" | "selectedOptions" | "selectionDisplay" | "onOptionsChange" | "onInputChange" | "onAddNewOption" | "allowSelectAll" | "optionComponent" | "optionsFilter" | "autoWidth" | "clearSearchOnChange" | "multiline" | "dropdownHeight" | "itemToKey" | "itemCompare" | "
|
|
97
|
+
}, "disabled" | "className" | "id" | "style" | "meta" | "label" | "ref" | "multiple" | "variant" | "placeholder" | "readOnly" | "options" | "onClear" | "helperText" | "helperIcon" | "loading" | "optionDisabled" | "totalOptions" | "initialSelectedOptions" | "noOptionsText" | "hideClearButton" | "selectedOptions" | "selectionDisplay" | "onOptionsChange" | "onInputChange" | "onAddNewOption" | "allowSelectAll" | "optionComponent" | "optionsFilter" | "autoWidth" | "clearSearchOnChange" | "multiline" | "dropdownHeight" | "itemToKey" | "itemCompare" | "optionLabel">;
|
|
98
98
|
highlightedIndex: number;
|
|
99
99
|
selectedItem: unknown;
|
|
100
100
|
isOpen: boolean;
|
|
@@ -208,7 +208,7 @@ export declare const useAutocompleteContext: () => {
|
|
|
208
208
|
optionLabel?: (option: unknown) => string;
|
|
209
209
|
} & {
|
|
210
210
|
ref?: React.Ref<HTMLInputElement>;
|
|
211
|
-
}, "disabled" | "className" | "style" | "meta" | "label" | "ref" | "multiple" | "variant" | "placeholder" | "readOnly" | "options" | "helperText" | "helperIcon" | "loading" | "optionDisabled" | "totalOptions" | "initialSelectedOptions" | "noOptionsText" | "hideClearButton" | "selectedOptions" | "selectionDisplay" | "onOptionsChange" | "onInputChange" | "onAddNewOption" | "allowSelectAll" | "optionComponent" | "optionsFilter" | "autoWidth" | "clearSearchOnChange" | "multiline" | "dropdownHeight" | "itemToKey" | "itemCompare" | "
|
|
211
|
+
}, "disabled" | "className" | "id" | "style" | "meta" | "label" | "ref" | "multiple" | "variant" | "placeholder" | "readOnly" | "options" | "onClear" | "helperText" | "helperIcon" | "loading" | "optionDisabled" | "totalOptions" | "initialSelectedOptions" | "noOptionsText" | "hideClearButton" | "selectedOptions" | "selectionDisplay" | "onOptionsChange" | "onInputChange" | "onAddNewOption" | "allowSelectAll" | "optionComponent" | "optionsFilter" | "autoWidth" | "clearSearchOnChange" | "multiline" | "dropdownHeight" | "itemToKey" | "itemCompare" | "optionLabel">;
|
|
212
212
|
highlightedIndex: number;
|
|
213
213
|
selectedItem: unknown;
|
|
214
214
|
isOpen: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { DOMAttributes } from 'react';
|
|
2
2
|
import { AutocompleteProps } from './Autocomplete';
|
|
3
3
|
import { AutocompleteToken } from './Autocomplete.tokens';
|
|
4
|
-
export declare const useAutocomplete: <T>({ options, totalOptions, label, meta, className, style, disabled, readOnly, loading, hideClearButton, onOptionsChange, onAddNewOption, onInputChange, selectedOptions: _selectedOptions, selectionDisplay, multiple, itemToKey: _itemToKey, itemCompare: _itemCompare, allowSelectAll, initialSelectedOptions: _initialSelectedOptions, optionDisabled, optionsFilter, autoWidth, placeholder, optionLabel, clearSearchOnChange, multiline, dropdownHeight, optionComponent, helperText, helperIcon, noOptionsText, variant, onClear, ref, ...other }: AutocompleteProps<T> & {
|
|
4
|
+
export declare const useAutocomplete: <T>({ options, totalOptions, label, meta, className, style, disabled, readOnly, loading, hideClearButton, onOptionsChange, onAddNewOption, onInputChange, selectedOptions: _selectedOptions, selectionDisplay, multiple, itemToKey: _itemToKey, itemCompare: _itemCompare, allowSelectAll, initialSelectedOptions: _initialSelectedOptions, optionDisabled, optionsFilter, autoWidth, placeholder, optionLabel, clearSearchOnChange, multiline, dropdownHeight, optionComponent, helperText, helperIcon, noOptionsText, variant, onClear, ref, id, ...other }: AutocompleteProps<T> & {
|
|
5
5
|
ref?: React.Ref<HTMLInputElement>;
|
|
6
6
|
}) => {
|
|
7
7
|
getDropdownProps: <Options>(options?: import("downshift").UseMultipleSelectionGetDropdownPropsOptions & Options, extraOptions?: import("downshift").GetPropsCommonOptions) => Omit<import("downshift").Overwrite<import("downshift").UseMultipleSelectionGetDropdownReturnValue, Options>, "preventKeyAction">;
|
|
@@ -103,7 +103,7 @@ export declare const useAutocomplete: <T>({ options, totalOptions, label, meta,
|
|
|
103
103
|
optionLabel?: (option: T) => string;
|
|
104
104
|
}) & {
|
|
105
105
|
ref?: React.Ref<HTMLInputElement>;
|
|
106
|
-
}, "disabled" | "className" | "style" | "meta" | "label" | "ref" | "multiple" | "variant" | "placeholder" | "readOnly" | "options" | "helperText" | "helperIcon" | "loading" | "optionDisabled" | "totalOptions" | "initialSelectedOptions" | "noOptionsText" | "hideClearButton" | "selectedOptions" | "selectionDisplay" | "onOptionsChange" | "onInputChange" | "onAddNewOption" | "allowSelectAll" | "optionComponent" | "optionsFilter" | "autoWidth" | "clearSearchOnChange" | "multiline" | "dropdownHeight" | "itemToKey" | "itemCompare" | "
|
|
106
|
+
}, "disabled" | "className" | "id" | "style" | "meta" | "label" | "ref" | "multiple" | "variant" | "placeholder" | "readOnly" | "options" | "onClear" | "helperText" | "helperIcon" | "loading" | "optionDisabled" | "totalOptions" | "initialSelectedOptions" | "noOptionsText" | "hideClearButton" | "selectedOptions" | "selectionDisplay" | "onOptionsChange" | "onInputChange" | "onAddNewOption" | "allowSelectAll" | "optionComponent" | "optionsFilter" | "autoWidth" | "clearSearchOnChange" | "multiline" | "dropdownHeight" | "itemToKey" | "itemCompare" | "optionLabel">;
|
|
107
107
|
highlightedIndex: number;
|
|
108
108
|
selectedItem: T;
|
|
109
109
|
isOpen: boolean;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
declare const BannerIcon: import("react").ForwardRefExoticComponent<{
|
|
2
|
+
children: import("react").ReactNode;
|
|
3
|
+
} & import("react").HTMLAttributes<HTMLSpanElement> & import("react").RefAttributes<HTMLSpanElement>>;
|
|
4
|
+
declare const BannerMessage: import("react").ForwardRefExoticComponent<{
|
|
5
|
+
children: import("react").ReactNode;
|
|
6
|
+
} & import("react").HTMLAttributes<HTMLParagraphElement> & import("react").RefAttributes<HTMLParagraphElement>>;
|
|
7
|
+
declare const BannerActions: import("react").ForwardRefExoticComponent<{
|
|
8
|
+
placement?: import("./Banner.types").BannerActionsPlacement;
|
|
9
|
+
children: import("react").ReactNode;
|
|
10
|
+
} & import("react").HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
|
|
11
|
+
declare const BannerComponent: import("react").ForwardRefExoticComponent<{
|
|
12
|
+
tone?: import("./Banner.types").BannerTone;
|
|
13
|
+
role?: import("react").HTMLAttributes<HTMLDivElement>["role"];
|
|
14
|
+
onDismiss?: () => void;
|
|
15
|
+
children: import("react").ReactNode;
|
|
16
|
+
} & import("react").HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
|
|
17
|
+
type CompoundBanner = typeof BannerComponent & {
|
|
18
|
+
Icon: typeof BannerIcon;
|
|
19
|
+
Message: typeof BannerMessage;
|
|
20
|
+
Actions: typeof BannerActions;
|
|
21
|
+
};
|
|
22
|
+
export declare const Banner: CompoundBanner;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|