@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.
Files changed (49) hide show
  1. package/build/index.css +389 -39
  2. package/build/index.min.css +1 -1
  3. package/dist/eds-core-react.cjs +29 -23
  4. package/dist/esm/components/Autocomplete/AutocompleteContext.js +2 -2
  5. package/dist/esm/components/Autocomplete/MultipleInput.js +2 -2
  6. package/dist/esm/components/Autocomplete/OptionList.js +6 -4
  7. package/dist/esm/components/Autocomplete/useAutocomplete.js +4 -0
  8. package/dist/esm/components/Datepicker/calendars/CalendarGrid.js +4 -8
  9. package/dist/esm/components/Datepicker/calendars/CalendarHeader.js +6 -6
  10. package/dist/esm/components/Datepicker/fields/DateSegment.js +4 -1
  11. package/dist/esm/components/InputWrapper/InputWrapper.js +1 -1
  12. package/dist/esm/components/Popover/Popover.js +4 -4
  13. package/dist/esm/components/Textarea/Textarea.js +1 -1
  14. package/dist/esm-next/components/next/Banner/Banner.js +88 -0
  15. package/dist/esm-next/components/next/Button/Button.js +1 -0
  16. package/dist/esm-next/components/next/Icon/Icon.js +27 -1
  17. package/dist/esm-next/components/next/Input/Input.js +1 -1
  18. package/dist/esm-next/components/next/Link/Link.js +24 -0
  19. package/dist/esm-next/components/next/Search/Search.js +118 -0
  20. package/dist/esm-next/components/next/TextArea/TextArea.js +131 -0
  21. package/dist/esm-next/components/next/Tooltip/Tooltip.js +84 -0
  22. package/dist/esm-next/index.next.js +5 -0
  23. package/dist/index.next.cjs +445 -6
  24. package/dist/types/components/Autocomplete/AutocompleteContext.d.ts +2 -2
  25. package/dist/types/components/Autocomplete/useAutocomplete.d.ts +2 -2
  26. package/dist/types/components/next/Banner/Banner.d.ts +23 -0
  27. package/dist/types/components/next/Banner/Banner.figma.d.ts +1 -0
  28. package/dist/types/components/next/Banner/Banner.types.d.ts +33 -0
  29. package/dist/types/components/next/Banner/index.d.ts +2 -0
  30. package/dist/types/components/next/Icon/Icon.d.ts +0 -1
  31. package/dist/types/components/next/Input/Input.types.d.ts +4 -1
  32. package/dist/types/components/next/Link/Link.d.ts +4 -0
  33. package/dist/types/components/next/Link/Link.figma.d.ts +1 -0
  34. package/dist/types/components/next/Link/Link.types.d.ts +11 -0
  35. package/dist/types/components/next/Link/index.d.ts +2 -0
  36. package/dist/types/components/next/Search/Search.d.ts +9 -0
  37. package/dist/types/components/next/Search/Search.figma.d.ts +1 -0
  38. package/dist/types/components/next/Search/Search.types.d.ts +16 -0
  39. package/dist/types/components/next/Search/index.d.ts +2 -0
  40. package/dist/types/components/next/TextArea/TextArea.d.ts +11 -0
  41. package/dist/types/components/next/TextArea/TextArea.figma.d.ts +1 -0
  42. package/dist/types/components/next/TextArea/TextArea.types.d.ts +21 -0
  43. package/dist/types/components/next/TextArea/index.d.ts +2 -0
  44. package/dist/types/components/next/Tooltip/Tooltip.d.ts +7 -0
  45. package/dist/types/components/next/Tooltip/Tooltip.figma.d.ts +1 -0
  46. package/dist/types/components/next/Tooltip/Tooltip.types.d.ts +17 -0
  47. package/dist/types/components/next/Tooltip/index.d.ts +2 -0
  48. package/dist/types/components/next/index.d.ts +10 -0
  49. 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';
@@ -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" | "onClear" | "optionLabel">;
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" | "onClear" | "optionLabel">;
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" | "onClear" | "optionLabel">;
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 {};