@equinor/eds-core-react 2.3.5 → 2.3.6-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 (46) hide show
  1. package/build/index.css +186 -304
  2. package/build/index.min.css +1 -5
  3. package/dist/eds-core-react.cjs +233 -47
  4. package/dist/esm/components/Autocomplete/AddNewOption.js +1 -1
  5. package/dist/esm/components/Autocomplete/Autocomplete.js +1 -1
  6. package/dist/esm/components/Autocomplete/AutocompleteContext.js +2 -2
  7. package/dist/esm/components/Autocomplete/Option.js +11 -2
  8. package/dist/esm/components/Autocomplete/OptionList.js +6 -4
  9. package/dist/esm/components/Autocomplete/SelectAllOption.js +1 -1
  10. package/dist/esm/components/Autocomplete/useAutocomplete.js +13 -2
  11. package/dist/esm/components/Banner/Banner.tokens.js +2 -10
  12. package/dist/esm/components/Chip/Chip.js +1 -1
  13. package/dist/esm/components/Chip/Chip.tokens.js +0 -2
  14. package/dist/esm/components/Datepicker/DatePicker.js +4 -1
  15. package/dist/esm/components/Datepicker/DateRangePicker.js +4 -1
  16. package/dist/esm/components/Datepicker/calendars/CalendarGrid.js +4 -8
  17. package/dist/esm/components/Datepicker/calendars/CalendarHeader.js +6 -6
  18. package/dist/esm/components/Datepicker/fields/DateFieldSegments.js +11 -2
  19. package/dist/esm/components/Datepicker/fields/DateSegment.js +4 -1
  20. package/dist/esm/components/Datepicker/utils/get-calendar-date.js +1 -1
  21. package/dist/esm/components/Datepicker/utils/getLocalizedValidationErrors.js +164 -0
  22. package/dist/esm/components/EdsProvider/eds.context.js +1 -1
  23. package/dist/esm/components/Menu/Menu.context.js +1 -1
  24. package/dist/esm/components/Popover/Popover.js +4 -4
  25. package/dist/esm/components/SideBar/SideBar.context.js +1 -1
  26. package/dist/esm/components/Table/DataCell/DataCell.js +1 -1
  27. package/dist/esm/components/Table/FooterCell/FooterCell.js +1 -1
  28. package/dist/esm/components/Table/HeaderCell/HeaderCell.js +1 -1
  29. package/dist/esm/components/Typography/Typography.js +1 -1
  30. package/dist/esm/index.js +64 -64
  31. package/dist/esm-next/components/next/Button/Button.js +4 -5
  32. package/dist/esm-next/components/next/Icon/Icon.js +27 -1
  33. package/dist/esm-next/components/next/Input/Input.js +6 -11
  34. package/dist/esm-next/components/next/TextField/TextField.js +8 -2
  35. package/dist/esm-next/index.next.js +4 -4
  36. package/dist/index.next.cjs +44 -19
  37. package/dist/types/components/Autocomplete/Autocomplete.d.ts +1 -1
  38. package/dist/types/components/Autocomplete/AutocompleteContext.d.ts +2 -2
  39. package/dist/types/components/Autocomplete/useAutocomplete.d.ts +3 -2
  40. package/dist/types/components/Datepicker/DateRangePicker.d.ts +1 -1
  41. package/dist/types/components/Datepicker/utils/getLocalizedValidationErrors.d.ts +9 -0
  42. package/dist/types/components/SideBar/SideBarButton/index.d.ts +1 -1
  43. package/dist/types/components/next/Icon/Icon.d.ts +0 -1
  44. package/dist/types/components/next/Input/Input.types.d.ts +6 -4
  45. package/dist/types/components/next/TextField/TextField.d.ts +1 -0
  46. package/package.json +44 -37
@@ -13,6 +13,7 @@ import { tokens } from '@equinor/eds-tokens';
13
13
  import { Icon } from '../Icon/index.js';
14
14
  import { getCalendarDate } from './utils/get-calendar-date.js';
15
15
  import { useGetLocale } from './utils/useGetLocale.js';
16
+ import { getLocalizedValidationErrors } from './utils/getLocalizedValidationErrors.js';
16
17
  import { jsx } from 'react/jsx-runtime';
17
18
 
18
19
  const DateRangePicker = /*#__PURE__*/forwardRef(({
@@ -96,8 +97,10 @@ const DateRangePicker = /*#__PURE__*/forwardRef(({
96
97
  buttonProps,
97
98
  calendarProps
98
99
  } = useDateRangePicker(dateRangePickerStateProps, state, ref);
100
+ const localizedErrors = state.displayValidation.isInvalid ? getLocalizedValidationErrors(state.displayValidation.validationDetails, locale, _minValue, _maxValue, timezone) : [];
101
+ const errorMessages = localizedErrors.length > 0 ? localizedErrors : state.displayValidation.validationErrors;
99
102
  const helperProps = state.displayValidation.isInvalid ? {
100
- text: state.displayValidation.validationErrors.join('\n'),
103
+ text: errorMessages.join('\n'),
101
104
  color: tokens.colors.interactive.warning__text.rgba,
102
105
  icon: /*#__PURE__*/jsx(Icon, {
103
106
  size: 16,
@@ -1,5 +1,4 @@
1
- import { useLocale, useCalendarGrid } from 'react-aria';
2
- import { getWeeksInMonth } from '@internationalized/date';
1
+ import { useCalendarGrid } from 'react-aria';
3
2
  import { CalendarCell } from './CalendarCell.js';
4
3
  import { YearGrid } from './YearGrid.js';
5
4
  import { jsx, jsxs } from 'react/jsx-runtime';
@@ -17,9 +16,6 @@ function CalendarGrid({
17
16
  setYearPickerPage,
18
17
  ...props
19
18
  }) {
20
- const {
21
- locale
22
- } = useLocale();
23
19
  const {
24
20
  gridProps,
25
21
  headerProps,
@@ -29,9 +25,9 @@ function CalendarGrid({
29
25
  weekdayStyle: 'long'
30
26
  }, state);
31
27
 
32
- // Get the number of weeks in the month so that we can render the proper number of rows.
33
- const howManyWeeksInMonth = getWeeksInMonth(state.visibleRange.start, locale);
34
- const weeksInMonthArray = [...new Array(howManyWeeksInMonth).keys()];
28
+ // Always render 6 rows (the maximum weeks in any month) so the calendar
29
+ // height stays consistent when navigating between months.
30
+ const weeksInMonthArray = [...new Array(6).keys()];
35
31
  return showYearPicker ? /*#__PURE__*/jsx(YearGrid, {
36
32
  year: state.focusedDate.year,
37
33
  setFocusedYear: year => {
@@ -21,7 +21,7 @@ function TodayPicker({
21
21
  onClick: () => onClick(new CalendarDate(today.getFullYear(), today.getMonth() + 1, today.getDate())),
22
22
  variant: 'ghost',
23
23
  style: {
24
- marginLeft: 16
24
+ marginLeft: 4
25
25
  },
26
26
  children: "Today"
27
27
  });
@@ -30,6 +30,10 @@ const HeaderActions = styled.div.withConfig({
30
30
  displayName: "CalendarHeader__HeaderActions",
31
31
  componentId: "sc-kuy15-1"
32
32
  })(["display:flex;align-items:center;width:100%;"]);
33
+ const TitleButton = styled(Button).withConfig({
34
+ displayName: "CalendarHeader__TitleButton",
35
+ componentId: "sc-kuy15-2"
36
+ })(["min-width:13.1rem;white-space:nowrap;font-size:", ";text-transform:capitalize;& > span{display:flex;justify-content:space-between;align-items:center;width:100%;}"], tokens.typography.heading.h5.fontSize);
33
37
 
34
38
  /**
35
39
  * The default header for the calendar components if no custom header is provided
@@ -61,15 +65,11 @@ function CalendarHeader({
61
65
  style: {
62
66
  flex: '1 1 auto'
63
67
  }
64
- }), /*#__PURE__*/jsxs(Button, {
68
+ }), /*#__PURE__*/jsxs(TitleButton, {
65
69
  onClick: () => setShowYearPicker(!showYearPicker),
66
70
  "data-testid": 'heading',
67
71
  "aria-live": 'polite',
68
72
  variant: 'ghost',
69
- style: {
70
- fontSize: tokens.typography.heading.h5.fontSize,
71
- textTransform: 'capitalize'
72
- },
73
73
  children: [title, /*#__PURE__*/jsx(Icon, {
74
74
  data: showYearPicker ? chevron_up : chevron_down
75
75
  })]
@@ -1,20 +1,29 @@
1
1
  import { useDateFieldState } from '@react-stately/datepicker';
2
2
  import { useDateField } from 'react-aria';
3
- import { createCalendar } from '@internationalized/date';
3
+ import { CalendarDate, createCalendar } from '@internationalized/date';
4
4
  import { DateSegment } from './DateSegment.js';
5
5
  import { forwardRef } from 'react';
6
6
  import { jsx } from 'react/jsx-runtime';
7
7
 
8
8
  // In some cases we need to use the index as key
9
9
  /* eslint-disable react/no-array-index-key */
10
+ // Use January 1st as placeholder when no value is set.
11
+ // This ensures the day segment allows values up to 31,
12
+ // preventing eager auto-advance when typing "3" (which
13
+ // would otherwise auto-complete to "03" in months with
14
+ // fewer than 30 days, like February).
15
+ const DEFAULT_PLACEHOLDER = new CalendarDate(new Date().getFullYear(), 1, 1);
16
+
10
17
  /**
11
18
  * A field that wraps segments for inputting a date / date-time
12
19
  */
13
20
  const DateFieldSegments = /*#__PURE__*/forwardRef((props, ref) => {
21
+ const placeholderValue = props.placeholderValue ?? DEFAULT_PLACEHOLDER;
14
22
  const state = useDateFieldState({
15
23
  ...props,
16
24
  locale: props.locale,
17
- createCalendar
25
+ createCalendar,
26
+ placeholderValue
18
27
  });
19
28
  const {
20
29
  fieldProps
@@ -30,7 +30,10 @@ function DateSegment({
30
30
  formatOptions,
31
31
  timezone
32
32
  } = useDatePickerContext();
33
- const formatter = useDateFormatter(formatOptions);
33
+ const formatter = useDateFormatter({
34
+ ...formatOptions,
35
+ timeZone: timezone
36
+ });
34
37
  const parts = state.value ? formatter.formatToParts(state.value.toDate(timezone)) : [];
35
38
  const part = parts.find(p => p.type === segment.type);
36
39
  const value = segment.isPlaceholder || segment.type === 'literal' ? segment.text : part?.value ?? segment.text;
@@ -1,4 +1,4 @@
1
- import { toCalendarDateTime, toCalendarDate, fromDate } from '@internationalized/date';
1
+ import { toCalendarDateTime, fromDate, toCalendarDate } from '@internationalized/date';
2
2
 
3
3
  const getCalendarDate = (value, timezone, showTimeInput = false) => {
4
4
  if (!value) return null;
@@ -0,0 +1,164 @@
1
+ import { DateFormatter } from '@internationalized/date';
2
+
3
+ /**
4
+ * Validation message translations matching @react-stately/datepicker's built-in messages.
5
+ * Sourced from @react-stately/datepicker's intlStrings bundle.
6
+ * Unsupported locales fall back to English.
7
+ */
8
+ const allTranslations = {
9
+ 'en-US': {
10
+ rangeUnderflow: args => `Value must be ${args.minValue} or later.`,
11
+ rangeOverflow: args => `Value must be ${args.maxValue} or earlier.`,
12
+ unavailableDate: 'Selected date unavailable.'
13
+ },
14
+ 'nb-NO': {
15
+ rangeUnderflow: args => `Verdien m\u00e5 v\u00e6re ${args.minValue} eller senere.`,
16
+ rangeOverflow: args => `Verdien m\u00e5 v\u00e6re ${args.maxValue} eller tidligere.`,
17
+ unavailableDate: 'Valgt dato utilgjengelig.'
18
+ },
19
+ 'da-DK': {
20
+ rangeUnderflow: args => `V\u00e6rdien skal v\u00e6re ${args.minValue} eller senere.`,
21
+ rangeOverflow: args => `V\u00e6rdien skal v\u00e6re ${args.maxValue} eller tidligere.`,
22
+ unavailableDate: 'Den valgte dato er ikke tilg\u00e6ngelig.'
23
+ },
24
+ 'sv-SE': {
25
+ rangeUnderflow: args => `V\u00e4rdet m\u00e5ste vara ${args.minValue} eller senare.`,
26
+ rangeOverflow: args => `V\u00e4rdet m\u00e5ste vara ${args.maxValue} eller tidigare.`,
27
+ unavailableDate: 'Valt datum \u00e4r inte tillg\u00e4ngligt.'
28
+ },
29
+ 'de-DE': {
30
+ rangeUnderflow: args => `Der Wert muss ${args.minValue} oder sp\u00e4ter sein.`,
31
+ rangeOverflow: args => `Der Wert muss ${args.maxValue} oder fr\u00fcher sein.`,
32
+ unavailableDate: 'Das ausgew\u00e4hlte Datum ist nicht verf\u00fcgbar.'
33
+ },
34
+ 'fr-FR': {
35
+ rangeUnderflow: args => `La valeur doit \u00eatre ${args.minValue} ou ult\u00e9rieure.`,
36
+ rangeOverflow: args => `La valeur doit \u00eatre ${args.maxValue} ou ant\u00e9rieure.`,
37
+ unavailableDate: 'Date s\u00e9lectionn\u00e9e non disponible.'
38
+ },
39
+ 'es-ES': {
40
+ rangeUnderflow: args => `El valor debe ser ${args.minValue} o posterior.`,
41
+ rangeOverflow: args => `El valor debe ser ${args.maxValue} o anterior.`,
42
+ unavailableDate: 'Fecha seleccionada no disponible.'
43
+ },
44
+ 'pt-BR': {
45
+ rangeUnderflow: args => `O valor deve ser ${args.minValue} ou posterior.`,
46
+ rangeOverflow: args => `O valor deve ser ${args.maxValue} ou anterior.`,
47
+ unavailableDate: 'Data selecionada indispon\u00edvel.'
48
+ },
49
+ 'pt-PT': {
50
+ rangeUnderflow: args => `O valor tem de ser ${args.minValue} ou posterior.`,
51
+ rangeOverflow: args => `O valor tem de ser ${args.maxValue} ou anterior.`,
52
+ unavailableDate: 'Data selecionada indispon\u00edvel.'
53
+ },
54
+ 'pl-PL': {
55
+ rangeUnderflow: args => `Warto\u015b\u0107 musi wynosi\u0107 ${args.minValue} lub p\u00f3\u017aniej.`,
56
+ rangeOverflow: args => `Warto\u015b\u0107 musi wynosi\u0107 ${args.maxValue} lub wcze\u015bniej.`,
57
+ unavailableDate: 'Wybrana data jest niedost\u0119pna.'
58
+ },
59
+ 'nl-NL': {
60
+ rangeUnderflow: args => `Waarde moet ${args.minValue} of later zijn.`,
61
+ rangeOverflow: args => `Waarde moet ${args.maxValue} of eerder zijn.`,
62
+ unavailableDate: 'Geselecteerde datum niet beschikbaar.'
63
+ },
64
+ 'it-IT': {
65
+ rangeUnderflow: args => `Il valore deve essere ${args.minValue} o successivo.`,
66
+ rangeOverflow: args => `Il valore deve essere ${args.maxValue} o precedente.`,
67
+ unavailableDate: 'Data selezionata non disponibile.'
68
+ },
69
+ 'ja-JP': {
70
+ rangeUnderflow: args => `\u5024\u306f${args.minValue}\u4ee5\u964d\u3067\u3042\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002`,
71
+ rangeOverflow: args => `\u5024\u306f${args.maxValue}\u4ee5\u524d\u3067\u3042\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002`,
72
+ unavailableDate: '\u9078\u629e\u3057\u305f\u65e5\u4ed8\u306f\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002'
73
+ },
74
+ 'ko-KR': {
75
+ rangeUnderflow: args => `\uac12\uc740 ${args.minValue} \uc774\ud6c4\uc5ec\uc57c \ud569\ub2c8\ub2e4.`,
76
+ rangeOverflow: args => `\uac12\uc740 ${args.maxValue} \uc774\uc804\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4.`,
77
+ unavailableDate: '\uc120\ud0dd\ud55c \ub0a0\uc9dc\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.'
78
+ },
79
+ 'zh-CN': {
80
+ rangeUnderflow: args => `\u503c\u5fc5\u987b\u4e3a ${args.minValue} \u6216\u66f4\u665a\u3002`,
81
+ rangeOverflow: args => `\u503c\u5fc5\u987b\u4e3a ${args.maxValue} \u6216\u66f4\u65e9\u3002`,
82
+ unavailableDate: '\u6240\u9009\u65e5\u671f\u4e0d\u53ef\u7528\u3002'
83
+ },
84
+ 'zh-TW': {
85
+ rangeUnderflow: args => `\u503c\u5fc5\u9808\u70ba ${args.minValue} \u6216\u66f4\u665a\u3002`,
86
+ rangeOverflow: args => `\u503c\u5fc5\u9808\u70ba ${args.maxValue} \u6216\u66f4\u65e9\u3002`,
87
+ unavailableDate: '\u6240\u9078\u65e5\u671f\u4e0d\u53ef\u7528\u3002'
88
+ },
89
+ 'ru-RU': {
90
+ rangeUnderflow: args => `\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c ${args.minValue} \u0438\u043b\u0438 \u043f\u043e\u0437\u0436\u0435.`,
91
+ rangeOverflow: args => `\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c ${args.maxValue} \u0438\u043b\u0438 \u0440\u0430\u043d\u044c\u0448\u0435.`,
92
+ unavailableDate: '\u0412\u044b\u0431\u0440\u0430\u043d\u043d\u0430\u044f \u0434\u0430\u0442\u0430 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430.'
93
+ },
94
+ 'uk-UA': {
95
+ rangeUnderflow: args => `\u0417\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043c\u0430\u0454 \u0431\u0443\u0442\u0438 ${args.minValue} \u0430\u0431\u043e \u043f\u0456\u0437\u043d\u0456\u0448\u0435.`,
96
+ rangeOverflow: args => `\u0417\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043c\u0430\u0454 \u0431\u0443\u0442\u0438 ${args.maxValue} \u0430\u0431\u043e \u0440\u0430\u043d\u0456\u0448\u0435.`,
97
+ unavailableDate: '\u0412\u0438\u0431\u0440\u0430\u043d\u0430 \u0434\u0430\u0442\u0430 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430.'
98
+ },
99
+ 'ar-AE': {
100
+ rangeUnderflow: args => `\u064a\u062c\u0628 \u0623\u0646 \u062a\u0643\u0648\u0646 \u0627\u0644\u0642\u064a\u0645\u0629 ${args.minValue} \u0623\u0648 \u0623\u062d\u062f\u062b.`,
101
+ rangeOverflow: args => `\u064a\u062c\u0628 \u0623\u0646 \u062a\u0643\u0648\u0646 \u0627\u0644\u0642\u064a\u0645\u0629 ${args.maxValue} \u0623\u0648 \u0623\u0642\u062f\u0645.`,
102
+ unavailableDate: '\u0627\u0644\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u0645\u062d\u062f\u062f \u063a\u064a\u0631 \u0645\u062a\u0627\u062d.'
103
+ },
104
+ 'fi-FI': {
105
+ rangeUnderflow: args => `Arvon on oltava ${args.minValue} tai my\u00f6hempi.`,
106
+ rangeOverflow: args => `Arvon on oltava ${args.maxValue} tai aikaisempi.`,
107
+ unavailableDate: 'Valittu p\u00e4iv\u00e4m\u00e4\u00e4r\u00e4 ei ole k\u00e4ytett\u00e4viss\u00e4.'
108
+ }
109
+ };
110
+ const englishFallback = allTranslations['en-US'];
111
+
112
+ /**
113
+ * Find the best matching locale from available translations.
114
+ * Tries exact match first (e.g. "nb-NO"), then language prefix match (e.g. "nb" → "nb-NO").
115
+ */
116
+ function findLocaleMessages(locale) {
117
+ if (allTranslations[locale]) return allTranslations[locale];
118
+ const language = Intl.Locale ? new Intl.Locale(locale).language : locale.split('-')[0];
119
+
120
+ // First match wins: e.g. "pt" → "pt-BR", "zh" → "zh-CN"
121
+ for (const key of Object.keys(allTranslations)) {
122
+ const keyLang = key.split('-')[0];
123
+ if (keyLang === language) return allTranslations[key];
124
+ }
125
+ return englishFallback;
126
+ }
127
+ function formatMessage(msg, args) {
128
+ return typeof msg === 'function' ? msg(args) : msg;
129
+ }
130
+
131
+ /**
132
+ * Generates validation error messages using the provided locale instead of
133
+ * navigator.language (which is what react-stately uses internally).
134
+ *
135
+ * This fixes the issue where validation messages appear in the browser's
136
+ * language rather than the locale configured via I18nProvider.
137
+ */
138
+ function getLocalizedValidationErrors(validationDetails, locale, minValue, maxValue, timezone) {
139
+ const msgs = findLocaleMessages(locale);
140
+ const dateFormatter = new DateFormatter(locale, {
141
+ year: 'numeric',
142
+ month: 'numeric',
143
+ day: 'numeric'
144
+ });
145
+ const timeZone = timezone ?? dateFormatter.resolvedOptions().timeZone;
146
+ const errors = [];
147
+ if (validationDetails.rangeUnderflow && minValue && msgs.rangeUnderflow) {
148
+ errors.push(formatMessage(msgs.rangeUnderflow, {
149
+ minValue: dateFormatter.format(minValue.toDate(timeZone))
150
+ }));
151
+ }
152
+ if (validationDetails.rangeOverflow && maxValue && msgs.rangeOverflow) {
153
+ errors.push(formatMessage(msgs.rangeOverflow, {
154
+ maxValue: dateFormatter.format(maxValue.toDate(timeZone))
155
+ }));
156
+ }
157
+ // react-stately maps isDateUnavailable to badInput (not customError)
158
+ if (validationDetails.badInput && msgs.unavailableDate) {
159
+ errors.push(formatMessage(msgs.unavailableDate, {}));
160
+ }
161
+ return errors;
162
+ }
163
+
164
+ export { getLocalizedValidationErrors };
@@ -1,4 +1,4 @@
1
- import { useContext, useState, useEffect, createContext } from 'react';
1
+ import { useState, useEffect, useContext, createContext } from 'react';
2
2
  import { jsx } from 'react/jsx-runtime';
3
3
 
4
4
  const initalState = {
@@ -1,4 +1,4 @@
1
- import { useContext, useState, createContext } from 'react';
1
+ import { useState, useContext, createContext } from 'react';
2
2
  import { jsx } from 'react/jsx-runtime';
3
3
 
4
4
  const initalState = {
@@ -99,12 +99,12 @@ const Popover = /*#__PURE__*/forwardRef(function Popover({
99
99
  } = useInteractions([useDismiss(context)]);
100
100
  useEffect(() => {
101
101
  if (!elements.floating) return;
102
- if (open) {
103
- if (elements.floating.isConnected) {
102
+ if (elements.floating.hasAttribute('popover')) {
103
+ if (open) {
104
104
  elements.floating.showPopover();
105
+ } else {
106
+ elements.floating.hidePopover();
105
107
  }
106
- } else {
107
- elements.floating.hidePopover();
108
108
  }
109
109
  }, [open, elements.floating]);
110
110
  useEffect(() => {
@@ -1,4 +1,4 @@
1
- import { useContext, createContext, useState, useCallback } from 'react';
1
+ import { useContext, useState, useCallback, createContext } from 'react';
2
2
  import { jsx } from 'react/jsx-runtime';
3
3
 
4
4
  const initalState = {
@@ -20,7 +20,7 @@ const StyledTableCell = styled.td.withConfig({
20
20
  align
21
21
  } = theme;
22
22
  const backgroundColor = color === 'error' ? theme.validation.error?.background : '';
23
- const base = css(["min-height:", ";height:", ";background:", ";vertical-align:", ";box-sizing:border-box;", " ", " ", ""], height, height, backgroundColor, align.vertical, spacingsTemplate(spacings), typographyTemplate(typography), bordersTemplate(border));
23
+ const base = css(["min-height:", ";height:", ";background:", ";vertical-align:", ";box-sizing:border-box;", " ", " ", " a{font-size:inherit;font-weight:inherit;}"], height, height, backgroundColor, align.vertical, spacingsTemplate(spacings), typographyTemplate(typography), bordersTemplate(border));
24
24
  return base;
25
25
  });
26
26
  const TableDataCell = /*#__PURE__*/forwardRef(function TableDataCell({
@@ -19,7 +19,7 @@ const StyledTableCell = styled.th.withConfig({
19
19
  typography,
20
20
  spacings
21
21
  } = theme;
22
- return css(["min-height:", ";height:", ";background:", ";box-sizing:border-box;", " ", " ", " ", ""], height, height, background, spacingsTemplate(spacings), typographyTemplate(typography), bordersTemplate(theme.border), $sticky ? css(["position:sticky;bottom:0;z-index:2;"]) : '');
22
+ return css(["min-height:", ";height:", ";background:", ";box-sizing:border-box;", " ", " ", " a{font-size:inherit;font-weight:inherit;}", ""], height, height, background, spacingsTemplate(spacings), typographyTemplate(typography), bordersTemplate(theme.border), $sticky ? css(["position:sticky;bottom:0;z-index:2;"]) : '');
23
23
  });
24
24
  const CellInner = styled.div.withConfig({
25
25
  displayName: "FooterCell__CellInner",
@@ -34,7 +34,7 @@ const StyledTableCell = styled.th.withConfig({
34
34
  // Firefox specific workaround (bug in v142.0) - see issue #3910
35
35
  // Hardcoded padding values compensate for Firefox's incorrect table cell height calculation
36
36
  const firefoxFix = isFirefox() ? css(["vertical-align:top;height:auto;min-height:", ";> div{padding:", " 0;}"], height, $density === 'compact' ? '7px' : '13px') : css([""]);
37
- return css(["min-height:", ";height:", ";background:", ";box-sizing:border-box;", " ", " ", " ", " ", " ", " ", ""], height, height, background, spacingsTemplate(spacings), typographyTemplate(typography), bordersTemplate(theme.border), sortStylingHover, sortStylingActive, firefoxFix, $sticky ? css(["position:sticky;top:0;z-index:1;"]) : '');
37
+ return css(["min-height:", ";height:", ";background:", ";box-sizing:border-box;", " ", " ", " ", " ", " ", " a{font-size:inherit;font-weight:inherit;}", ""], height, height, background, spacingsTemplate(spacings), typographyTemplate(typography), bordersTemplate(theme.border), sortStylingHover, sortStylingActive, firefoxFix, $sticky ? css(["position:sticky;top:0;z-index:1;"]) : '');
38
38
  });
39
39
  const CellInner = styled.div.withConfig({
40
40
  displayName: "HeaderCell__CellInner",
@@ -1,7 +1,7 @@
1
1
  import { forwardRef } from 'react';
2
2
  import styled, { css } from 'styled-components';
3
3
  import { typographyTemplate, outlineTemplate } from '@equinor/eds-utils';
4
- import { quickVariants, typography, colors, link } from './Typography.tokens.js';
4
+ import { quickVariants, typography, link, colors } from './Typography.tokens.js';
5
5
  import { jsx } from 'react/jsx-runtime';
6
6
 
7
7
  const getElementType = (variant, link) => {
package/dist/esm/index.js CHANGED
@@ -16,85 +16,85 @@ export { Progress } from './components/Progress/index.js';
16
16
  export { Breadcrumbs } from './components/Breadcrumbs/index.js';
17
17
  export { Menu } from './components/Menu/index.js';
18
18
  export { SideBar } from './components/SideBar/index.js';
19
- export { ButtonGroup } from './components/Button/ButtonGroup/ButtonGroup.js';
20
- export { ToggleButton } from './components/Button/ToggleButton/ToggleButton.js';
21
- export { TypographyNext } from './components/Typography/Typography.new.js';
22
- export { Heading } from './components/Typography/Heading.js';
23
- export { Paragraph } from './components/Typography/Paragraph.js';
24
- export { Typography } from './components/Typography/Typography.js';
25
- export { Body as TableBody } from './components/Table/Body.js';
26
- export { Cell as TableCell } from './components/Table/Cell.js';
27
- export { Head as TableHead } from './components/Table/Head/Head.js';
28
- export { Foot as TableFoot } from './components/Table/Foot/Foot.js';
29
- export { Row as TableRow } from './components/Table/Row/Row.js';
30
- export { Caption as TableCaption } from './components/Table/Caption.js';
31
- export { Divider } from './components/Divider/Divider.js';
32
- export { TextField } from './components/TextField/TextField.js';
33
- export { Textarea } from './components/Textarea/Textarea.js';
34
- export { ListItem } from './components/List/ListItem.js';
35
- export { AccordionItem } from './components/Accordion/AccordionItem.js';
36
19
  export { AccordionHeader } from './components/Accordion/AccordionHeader.js';
37
- export { AccordionHeaderTitle } from './components/Accordion/AccordionHeaderTitle.js';
38
20
  export { AccordionHeaderActions } from './components/Accordion/AccordionHeaderActions.js';
21
+ export { AccordionHeaderTitle } from './components/Accordion/AccordionHeaderTitle.js';
22
+ export { AccordionItem } from './components/Accordion/AccordionItem.js';
39
23
  export { AccordionPanel } from './components/Accordion/AccordionPanel.js';
40
- export { Tab } from './components/Tabs/Tab.js';
41
- export { TabPanels } from './components/Tabs/TabPanels.js';
42
- export { TabPanel } from './components/Tabs/TabPanel.js';
43
- export { TabList } from './components/Tabs/TabList.js';
24
+ export { AddSymbol, AllSymbol, Autocomplete, StyledButton, defaultOptionDisabled } from './components/Autocomplete/Autocomplete.js';
25
+ export { Avatar } from './components/Avatar/Avatar.js';
26
+ export { BannerActions } from './components/Banner/BannerActions.js';
27
+ export { BannerIcon } from './components/Banner/BannerIcon.js';
28
+ export { BannerMessage } from './components/Banner/BannerMessage.js';
29
+ export { Breadcrumb } from './components/Breadcrumbs/Breadcrumb.js';
30
+ export { ButtonGroup } from './components/Button/ButtonGroup/ButtonGroup.js';
44
31
  export { CardActions } from './components/Card/CardActions.js';
45
32
  export { CardContent } from './components/Card/CardContent.js';
46
33
  export { CardHeader } from './components/Card/CardHeader.js';
47
- export { CardMedia } from './components/Card/CardMedia.js';
48
34
  export { CardHeaderTitle } from './components/Card/CardHeaderTitle.js';
49
- export { Actions as TopbarActions } from './components/TopBar/Actions.js';
50
- export { Header as TopbarHeader } from './components/TopBar/Header.js';
51
- export { CustomContent as TopbarCustomContent } from './components/TopBar/CustomContent.js';
35
+ export { CardMedia } from './components/Card/CardMedia.js';
36
+ export { Checkbox } from './components/Checkbox/Checkbox.js';
37
+ export { Chip } from './components/Chip/Chip.js';
38
+ export { CircularProgress } from './components/Progress/Circular/CircularProgress.js';
39
+ export { DatePicker } from './components/Datepicker/DatePicker.js';
40
+ export { DateRangePicker } from './components/Datepicker/DateRangePicker.js';
52
41
  export { DialogActions } from './components/Dialog/DialogActions.js';
53
- export { DialogTitle } from './components/Dialog/DialogTitle.js';
54
42
  export { DialogContent } from './components/Dialog/DialogContent.js';
55
43
  export { DialogHeader } from './components/Dialog/DialogHeader.js';
56
- export { Scrim } from './components/Scrim/Scrim.js';
57
- export { LinkItem as TableOfContentsLinkItem } from './components/TableOfContents/LinkItem.js';
58
- export { SideSheet } from './components/SideSheet/SideSheet.js';
59
- export { Chip } from './components/Chip/Chip.js';
60
- export { Avatar } from './components/Avatar/Avatar.js';
61
- export { Search } from './components/Search/Search.js';
62
- export { Slider } from './components/Slider/Slider.js';
63
- export { Tooltip } from './components/Tooltip/Tooltip.js';
64
- export { SnackbarAction } from './components/Snackbar/SnackbarAction.js';
65
- export { PopoverTitle } from './components/Popover/PopoverTitle.js';
66
- export { PopoverContent } from './components/Popover/PopoverContent.js';
67
- export { PopoverHeader } from './components/Popover/PopoverHeader.js';
68
- export { PopoverActions } from './components/Popover/PopoverActions.js';
69
- export { BannerIcon } from './components/Banner/BannerIcon.js';
70
- export { BannerMessage } from './components/Banner/BannerMessage.js';
71
- export { BannerActions } from './components/Banner/BannerActions.js';
72
- export { LinearProgress } from './components/Progress/Linear/LinearProgress.js';
73
- export { CircularProgress } from './components/Progress/Circular/CircularProgress.js';
74
- export { StarProgress } from './components/Progress/Star/StarProgress.js';
44
+ export { DialogTitle } from './components/Dialog/DialogTitle.js';
45
+ export { Divider } from './components/Divider/Divider.js';
75
46
  export { DotProgress } from './components/Progress/Dots/DotProgress.js';
76
- export { Breadcrumb } from './components/Breadcrumbs/Breadcrumb.js';
47
+ export { EdsProvider, useEds } from './components/EdsProvider/eds.context.js';
48
+ export { Heading } from './components/Typography/Heading.js';
49
+ export { Input } from './components/Input/Input.js';
50
+ export { InputWrapper } from './components/InputWrapper/InputWrapper.js';
51
+ export { Label } from './components/Label/Label.js';
52
+ export { LinearProgress } from './components/Progress/Linear/LinearProgress.js';
53
+ export { ListItem } from './components/List/ListItem.js';
77
54
  export { MenuItem } from './components/Menu/MenuItem.js';
78
55
  export { MenuSection } from './components/Menu/MenuSection.js';
79
- export { Pagination } from './components/Pagination/Pagination.js';
80
56
  export { NativeSelect } from './components/Select/NativeSelect.js';
81
- export { Label } from './components/Label/Label.js';
82
- export { Input } from './components/Input/Input.js';
83
- export { Checkbox } from './components/Checkbox/Checkbox.js';
84
- export { Radio } from './components/Radio/Radio.js';
85
- export { Switch } from './components/Switch/Switch.js';
86
- export { EdsProvider, useEds } from './components/EdsProvider/eds.context.js';
57
+ export { Pagination } from './components/Pagination/Pagination.js';
87
58
  export { Paper } from './components/Paper/Paper.js';
88
- export { AddSymbol, AllSymbol, Autocomplete, StyledButton, defaultOptionDisabled } from './components/Autocomplete/Autocomplete.js';
89
- export { InputWrapper } from './components/InputWrapper/InputWrapper.js';
90
- export { useInputField } from './components/InputWrapper/useInputField.js';
91
- export { useSideBar } from './components/SideBar/SideBar.context.js';
92
- export { SidebarLink } from './components/SideBar/SidebarLink/index.js';
59
+ export { Paragraph } from './components/Typography/Paragraph.js';
60
+ export { PopoverActions } from './components/Popover/PopoverActions.js';
61
+ export { PopoverContent } from './components/Popover/PopoverContent.js';
62
+ export { PopoverHeader } from './components/Popover/PopoverHeader.js';
63
+ export { PopoverTitle } from './components/Popover/PopoverTitle.js';
64
+ export { Radio } from './components/Radio/Radio.js';
65
+ export { Scrim } from './components/Scrim/Scrim.js';
66
+ export { Search } from './components/Search/Search.js';
67
+ export { SideBarAccordion } from './components/SideBar/SideBarAccordion/index.js';
68
+ export { SideBarAccordionItem } from './components/SideBar/SideBarAccordionItem/index.js';
69
+ export { SideBarButton } from './components/SideBar/SideBarButton/index.js';
93
70
  export { SideBarContent } from './components/SideBar/SideBarContent.js';
94
71
  export { SideBarFooter } from './components/SideBar/SideBarFooter.js';
95
72
  export { SideBarToggle } from './components/SideBar/SideBarToggle.js';
96
- export { SideBarButton } from './components/SideBar/SideBarButton/index.js';
97
- export { SideBarAccordion } from './components/SideBar/SideBarAccordion/index.js';
98
- export { SideBarAccordionItem } from './components/SideBar/SideBarAccordionItem/index.js';
99
- export { DatePicker } from './components/Datepicker/DatePicker.js';
100
- export { DateRangePicker } from './components/Datepicker/DateRangePicker.js';
73
+ export { SideSheet } from './components/SideSheet/SideSheet.js';
74
+ export { SidebarLink } from './components/SideBar/SidebarLink/index.js';
75
+ export { Slider } from './components/Slider/Slider.js';
76
+ export { SnackbarAction } from './components/Snackbar/SnackbarAction.js';
77
+ export { StarProgress } from './components/Progress/Star/StarProgress.js';
78
+ export { Switch } from './components/Switch/Switch.js';
79
+ export { Tab } from './components/Tabs/Tab.js';
80
+ export { TabList } from './components/Tabs/TabList.js';
81
+ export { TabPanel } from './components/Tabs/TabPanel.js';
82
+ export { TabPanels } from './components/Tabs/TabPanels.js';
83
+ export { Body as TableBody } from './components/Table/Body.js';
84
+ export { Caption as TableCaption } from './components/Table/Caption.js';
85
+ export { Cell as TableCell } from './components/Table/Cell.js';
86
+ export { Foot as TableFoot } from './components/Table/Foot/Foot.js';
87
+ export { Head as TableHead } from './components/Table/Head/Head.js';
88
+ export { LinkItem as TableOfContentsLinkItem } from './components/TableOfContents/LinkItem.js';
89
+ export { Row as TableRow } from './components/Table/Row/Row.js';
90
+ export { TextField } from './components/TextField/TextField.js';
91
+ export { Textarea } from './components/Textarea/Textarea.js';
92
+ export { ToggleButton } from './components/Button/ToggleButton/ToggleButton.js';
93
+ export { Tooltip } from './components/Tooltip/Tooltip.js';
94
+ export { Actions as TopbarActions } from './components/TopBar/Actions.js';
95
+ export { CustomContent as TopbarCustomContent } from './components/TopBar/CustomContent.js';
96
+ export { Header as TopbarHeader } from './components/TopBar/Header.js';
97
+ export { Typography } from './components/Typography/Typography.js';
98
+ export { TypographyNext } from './components/Typography/Typography.new.js';
99
+ export { useInputField } from './components/InputWrapper/useInputField.js';
100
+ export { useSideBar } from './components/SideBar/SideBar.context.js';
@@ -32,18 +32,17 @@ const Button = /*#__PURE__*/forwardRef(function Button({
32
32
  "data-variant": variant,
33
33
  "data-selectable-space": selectableSpace,
34
34
  "data-space-proportions": "squished",
35
- "data-font-family": "ui",
36
- "data-font-size": typographySize,
37
- "data-line-height": "squished",
38
35
  "data-color-appearance": disabled ? 'neutral' : tone,
39
36
  "data-icon-only": icon || undefined,
40
37
  "data-round": icon && round ? true : undefined,
41
38
  ...rest,
42
- children: /*#__PURE__*/jsx(TypographyNext, {
39
+ children: icon ? children : /*#__PURE__*/jsx(TypographyNext, {
40
+ as: "span",
41
+ className: "eds-button__label",
43
42
  family: "ui",
44
43
  size: typographySize,
45
- baseline: "center",
46
44
  lineHeight: "squished",
45
+ baseline: "center",
47
46
  children: children
48
47
  })
49
48
  });
@@ -1,6 +1,32 @@
1
1
  import { forwardRef, useId } from 'react';
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
3
 
4
+ /**
5
+ * Icon component for EDS 2.0
6
+ *
7
+ * Features:
8
+ * - Automatic sizing from parent's data-font-size via --eds-typography-icon-size
9
+ * - Dynamic fallback sizing (1.5em) when no tokens are set
10
+ * - Explicit size prop for standalone usage
11
+ * - WCAG 2.1 AA accessible with optional title for semantic icons
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * import { Icon } from '@equinor/eds-core-react/next'
16
+ * import { save } from '@equinor/eds-icons'
17
+ *
18
+ * // Auto-sized from parent's data-font-size
19
+ * <div data-font-size="md">
20
+ * <Icon data={warning} /> Error message
21
+ * </div>
22
+ *
23
+ * // Explicit size for standalone usage
24
+ * <Icon data={save} size="lg" />
25
+ *
26
+ * // Semantic icon with accessible name
27
+ * <Icon data={save} title="Save document" />
28
+ * ```
29
+ */
4
30
  const Icon = /*#__PURE__*/forwardRef(function Icon({
5
31
  data,
6
32
  title,
@@ -19,7 +45,7 @@ const Icon = /*#__PURE__*/forwardRef(function Icon({
19
45
  height = '24',
20
46
  width = '24'
21
47
  } = data;
22
- const classes = ['icon', className].filter(Boolean).join(' ');
48
+ const classes = ['eds-icon', className].filter(Boolean).join(' ');
23
49
 
24
50
  // Accessibility: decorative icons are hidden, semantic icons have role="img"
25
51
  const accessibilityProps = title ? {