@equinor/eds-core-react 0.36.0 → 0.37.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 (67) hide show
  1. package/dist/eds-core-react.cjs +1192 -53
  2. package/dist/esm/components/Autocomplete/Autocomplete.js +1 -1
  3. package/dist/esm/components/Breadcrumbs/Breadcrumbs.js +1 -1
  4. package/dist/esm/components/Button/Button.js +1 -1
  5. package/dist/esm/components/Button/tokens/contained_icon.js +2 -2
  6. package/dist/esm/components/Button/tokens/icon.js +1 -1
  7. package/dist/esm/components/Datepicker/DatePicker.js +156 -0
  8. package/dist/esm/components/Datepicker/DateRangePicker.js +151 -0
  9. package/dist/esm/components/Datepicker/calendars/Calendar.js +83 -0
  10. package/dist/esm/components/Datepicker/calendars/CalendarCell.js +144 -0
  11. package/dist/esm/components/Datepicker/calendars/CalendarGrid.js +65 -0
  12. package/dist/esm/components/Datepicker/calendars/CalendarHeader.js +90 -0
  13. package/dist/esm/components/Datepicker/calendars/CalendarWrapper.js +8 -0
  14. package/dist/esm/components/Datepicker/calendars/RangeCalendar.js +72 -0
  15. package/dist/esm/components/Datepicker/calendars/YearGrid.js +90 -0
  16. package/dist/esm/components/Datepicker/fields/DateField.js +40 -0
  17. package/dist/esm/components/Datepicker/fields/DateFieldSegments.js +43 -0
  18. package/dist/esm/components/Datepicker/fields/DateRangeField.js +43 -0
  19. package/dist/esm/components/Datepicker/fields/DateSegment.js +47 -0
  20. package/dist/esm/components/Datepicker/fields/FieldWrapper.js +136 -0
  21. package/dist/esm/components/Datepicker/fields/Toggle.js +61 -0
  22. package/dist/esm/components/Datepicker/utils/context.js +21 -0
  23. package/dist/esm/components/Datepicker/utils/get-calendar-date.js +8 -0
  24. package/dist/esm/components/Datepicker/utils/useConvertedValidationFunctions.js +20 -0
  25. package/dist/esm/components/Label/Label.js +1 -1
  26. package/dist/esm/components/Menu/MenuItem.js +1 -1
  27. package/dist/esm/components/TextField/TextField.js +2 -1
  28. package/dist/esm/components/Textarea/Textarea.js +9 -3
  29. package/dist/esm/index.js +2 -0
  30. package/dist/esm/node_modules/.pnpm/ramda@0.29.1/node_modules/ramda/es/mergeDeepRight.js +1 -2
  31. package/dist/esm/node_modules/.pnpm/ramda@0.29.1/node_modules/ramda/es/mergeDeepWithKey.js +1 -2
  32. package/dist/esm/node_modules/.pnpm/ramda@0.29.1/node_modules/ramda/es/mergeWith.js +1 -2
  33. package/dist/esm/node_modules/.pnpm/ramda@0.29.1/node_modules/ramda/es/mergeWithKey.js +1 -2
  34. package/dist/esm/node_modules/.pnpm/ramda@0.29.1/node_modules/ramda/es/pickBy.js +1 -2
  35. package/dist/types/components/Autocomplete/Autocomplete.d.ts +2 -2
  36. package/dist/types/components/Chip/Icon.d.ts +3 -1
  37. package/dist/types/components/Datepicker/DatePicker.d.ts +23 -0
  38. package/dist/types/components/Datepicker/DatePicker.spec.d.ts +1 -0
  39. package/dist/types/components/Datepicker/DateRangePicker.d.ts +39 -0
  40. package/dist/types/components/Datepicker/DateRangePicker.spec.d.ts +1 -0
  41. package/dist/types/components/Datepicker/calendars/Calendar.d.ts +17 -0
  42. package/dist/types/components/Datepicker/calendars/CalendarCell.d.ts +9 -0
  43. package/dist/types/components/Datepicker/calendars/CalendarGrid.d.ts +10 -0
  44. package/dist/types/components/Datepicker/calendars/CalendarHeader.d.ts +12 -0
  45. package/dist/types/components/Datepicker/calendars/CalendarWrapper.d.ts +273 -0
  46. package/dist/types/components/Datepicker/calendars/RangeCalendar.d.ts +11 -0
  47. package/dist/types/components/Datepicker/calendars/YearGrid.d.ts +4 -0
  48. package/dist/types/components/Datepicker/fields/DateField.d.ts +20 -0
  49. package/dist/types/components/Datepicker/fields/DateFieldSegments.d.ts +6 -0
  50. package/dist/types/components/Datepicker/fields/DateRangeField.d.ts +12 -0
  51. package/dist/types/components/Datepicker/fields/DateSegment.d.ts +8 -0
  52. package/dist/types/components/Datepicker/fields/FieldWrapper.d.ts +31 -0
  53. package/dist/types/components/Datepicker/fields/Toggle.d.ts +15 -0
  54. package/dist/types/components/Datepicker/index.d.ts +2 -0
  55. package/dist/types/components/Datepicker/props.d.ts +105 -0
  56. package/dist/types/components/Datepicker/utils/context.d.ts +9 -0
  57. package/dist/types/components/Datepicker/utils/get-calendar-date.d.ts +1 -0
  58. package/dist/types/components/Datepicker/utils/timezone.d.ts +1 -0
  59. package/dist/types/components/Datepicker/utils/types.d.ts +6 -0
  60. package/dist/types/components/Datepicker/utils/useConvertedValidationFunctions.d.ts +8 -0
  61. package/dist/types/components/Label/Label.d.ts +2 -2
  62. package/dist/types/components/Select/NativeSelect.d.ts +3 -3
  63. package/dist/types/components/Switch/Switch.styles.d.ts +6 -7
  64. package/dist/types/components/Tabs/TabList.d.ts +2 -13
  65. package/dist/types/components/TextField/TextField.d.ts +1 -1
  66. package/dist/types/index.d.ts +1 -0
  67. package/package.json +22 -19
@@ -0,0 +1,90 @@
1
+ import styled from 'styled-components';
2
+ import { Button } from '../../Button/index.js';
3
+ import { Icon } from '../../Icon/index.js';
4
+ import { chevron_left, chevron_up, chevron_down, chevron_right } from '@equinor/eds-icons';
5
+ import { CalendarDate } from '@internationalized/date';
6
+ import { tokens } from '@equinor/eds-tokens';
7
+ import { jsx, jsxs } from 'react/jsx-runtime';
8
+
9
+ const HeaderWrapper = styled.div.withConfig({
10
+ displayName: "CalendarHeader__HeaderWrapper",
11
+ componentId: "sc-kuy15-0"
12
+ })(["display:flex;justify-content:space-between;align-items:center;text-transform:capitalize;width:100%;"]);
13
+ function TodayPicker({
14
+ onClick,
15
+ disabled
16
+ }) {
17
+ const today = new Date();
18
+ return /*#__PURE__*/jsx(Button, {
19
+ disabled: disabled,
20
+ onClick: () => onClick(new CalendarDate(today.getFullYear(), today.getMonth() + 1, today.getDate())),
21
+ variant: 'ghost',
22
+ style: {
23
+ marginLeft: 16
24
+ },
25
+ children: "Today"
26
+ });
27
+ }
28
+ const HeaderActions = styled.div.withConfig({
29
+ displayName: "CalendarHeader__HeaderActions",
30
+ componentId: "sc-kuy15-1"
31
+ })(["display:flex;align-items:center;width:100%;"]);
32
+
33
+ /**
34
+ * The default header for the calendar components if no custom header is provided
35
+ */
36
+ function CalendarHeader({
37
+ state,
38
+ title,
39
+ previousMonthDisabled,
40
+ nextMonthDisabled,
41
+ showYearPicker,
42
+ setShowYearPicker
43
+ }) {
44
+ return /*#__PURE__*/jsx(HeaderWrapper, {
45
+ children: /*#__PURE__*/jsxs(HeaderActions, {
46
+ children: [/*#__PURE__*/jsx(Button, {
47
+ variant: 'ghost_icon',
48
+ "aria-label": 'Previous month',
49
+ disabled: previousMonthDisabled || showYearPicker,
50
+ onClick: () => state.focusPreviousPage(),
51
+ children: /*#__PURE__*/jsx(Icon, {
52
+ data: chevron_left
53
+ })
54
+ }), /*#__PURE__*/jsx("span", {
55
+ style: {
56
+ flex: '1 1 auto'
57
+ }
58
+ }), /*#__PURE__*/jsxs(Button, {
59
+ onClick: () => setShowYearPicker(!showYearPicker),
60
+ "data-testid": 'heading',
61
+ "aria-live": 'polite',
62
+ variant: 'ghost',
63
+ style: {
64
+ fontSize: tokens.typography.heading.h5.fontSize,
65
+ textTransform: 'capitalize'
66
+ },
67
+ children: [title, /*#__PURE__*/jsx(Icon, {
68
+ data: showYearPicker ? chevron_up : chevron_down
69
+ })]
70
+ }), /*#__PURE__*/jsx(TodayPicker, {
71
+ disabled: showYearPicker,
72
+ onClick: v => state.setFocusedDate(v)
73
+ }), /*#__PURE__*/jsx("span", {
74
+ style: {
75
+ flex: '1 1 auto'
76
+ }
77
+ }), /*#__PURE__*/jsx(Button, {
78
+ variant: 'ghost_icon',
79
+ onClick: () => state.focusNextPage(),
80
+ disabled: nextMonthDisabled || showYearPicker,
81
+ "aria-label": 'Next month',
82
+ children: /*#__PURE__*/jsx(Icon, {
83
+ data: chevron_right
84
+ })
85
+ })]
86
+ })
87
+ });
88
+ }
89
+
90
+ export { CalendarHeader };
@@ -0,0 +1,8 @@
1
+ import styled from 'styled-components';
2
+
3
+ const CalendarWrapper = styled.div.withConfig({
4
+ displayName: "CalendarWrapper",
5
+ componentId: "sc-14hqwiu-0"
6
+ })(["display:grid;grid-gap:16px;max-height:80vh;width:max-content;max-width:560px;overflow:auto;"]);
7
+
8
+ export { CalendarWrapper };
@@ -0,0 +1,72 @@
1
+ import { useLocale, useRangeCalendar } from 'react-aria';
2
+ import { useRangeCalendarState } from '@react-stately/calendar';
3
+ import { createCalendar } from '@internationalized/date';
4
+ import { CalendarGrid } from './CalendarGrid.js';
5
+ import { forwardRef, useState } from 'react';
6
+ import { CalendarHeader } from './CalendarHeader.js';
7
+ import { Popover } from '../../Popover/index.js';
8
+ import { CalendarWrapper } from './CalendarWrapper.js';
9
+ import { jsxs, jsx } from 'react/jsx-runtime';
10
+
11
+ const RangeCalendar = /*#__PURE__*/forwardRef(({
12
+ Header,
13
+ Footer,
14
+ ...props
15
+ }, ref) => {
16
+ const [showYearPicker, setShowYearPicker] = useState(false);
17
+ const {
18
+ locale
19
+ } = useLocale();
20
+ const state = useRangeCalendarState({
21
+ ...props,
22
+ locale,
23
+ createCalendar
24
+ });
25
+ const {
26
+ calendarProps,
27
+ title
28
+ } = useRangeCalendar(props, state, ref);
29
+ return /*#__PURE__*/jsxs(CalendarWrapper, {
30
+ ...calendarProps,
31
+ ref: ref,
32
+ children: [/*#__PURE__*/jsx(Popover.Header, {
33
+ children: Header ? /*#__PURE__*/jsx(Header, {
34
+ month: state.focusedDate.month,
35
+ state: state,
36
+ setMonth: month => state.setFocusedDate(state.focusedDate.set({
37
+ month
38
+ })),
39
+ setYear: year => state.setFocusedDate(state.focusedDate.set({
40
+ year
41
+ })),
42
+ year: state.focusedDate.year
43
+ }) : /*#__PURE__*/jsx(CalendarHeader, {
44
+ state: state,
45
+ title: title,
46
+ setShowYearPicker: setShowYearPicker,
47
+ showYearPicker: showYearPicker
48
+ })
49
+ }), /*#__PURE__*/jsx(Popover.Content, {
50
+ children: /*#__PURE__*/jsx(CalendarGrid, {
51
+ state: state,
52
+ setShowYearPicker: setShowYearPicker,
53
+ showYearPicker: showYearPicker
54
+ })
55
+ }), Footer && /*#__PURE__*/jsx(Popover.Actions, {
56
+ children: /*#__PURE__*/jsx(Footer, {
57
+ month: state.focusedDate.month,
58
+ state: state,
59
+ setMonth: month => state.setFocusedDate(state.focusedDate.set({
60
+ month
61
+ })),
62
+ setYear: year => state.setFocusedDate(state.focusedDate.set({
63
+ year
64
+ })),
65
+ year: state.focusedDate.year
66
+ })
67
+ })]
68
+ });
69
+ });
70
+ RangeCalendar.displayName = 'RangeCalendar';
71
+
72
+ export { RangeCalendar };
@@ -0,0 +1,90 @@
1
+ import styled from 'styled-components';
2
+ import { tokens } from '@equinor/eds-tokens';
3
+ import { FocusScope, useFocusManager } from 'react-aria';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ // Disable no-autofocus - it's not the native autofocus attribute, but react-aria's autoFocus prop
7
+ /* eslint-disable jsx-a11y/no-autofocus */
8
+ const Grid = styled.div.withConfig({
9
+ displayName: "YearGrid__Grid",
10
+ componentId: "sc-1l9jho8-0"
11
+ })(["display:grid;grid-template-columns:repeat(6,1fr);grid-gap:8px;margin:8px;"]);
12
+ const GridColumn = styled.button.withConfig({
13
+ displayName: "YearGrid__GridColumn",
14
+ componentId: "sc-1l9jho8-1"
15
+ })(["background-color:transparent;outline:none;border:none;display:flex;justify-content:center;cursor:pointer;padding:8px;font-size:", ";font-family:", ";font-weight:", ";line-height:", ";color:", ";border-radius:999px;", ";&:hover{background-color:#f0f0f0;}&:focus{outline:2px dashed ", ";}"], tokens.typography.navigation.button.fontSize, tokens.typography.navigation.button.fontFamily, tokens.typography.navigation.button.fontWeight, tokens.typography.navigation.button.lineHeight, tokens.colors.text.static_icons__default.rgba, ({
16
+ $active
17
+ }) => $active ? `background-color: ${tokens.colors.interactive.primary__selected_highlight.rgba}` : '', tokens.colors.interactive.primary__resting.rgba);
18
+ const GridFocusManager = ({
19
+ year: selectedYear,
20
+ setFocusedYear
21
+ }) => {
22
+ const focusManager = useFocusManager();
23
+ const onKeyDown = e => {
24
+ const target = e.currentTarget;
25
+ const parent = target.parentElement;
26
+ switch (e.key) {
27
+ case 'ArrowRight':
28
+ e.preventDefault();
29
+ focusManager.focusNext({
30
+ wrap: true
31
+ });
32
+ break;
33
+ case 'ArrowLeft':
34
+ e.preventDefault();
35
+ focusManager.focusPrevious({
36
+ wrap: true
37
+ });
38
+ break;
39
+ case 'ArrowDown':
40
+ {
41
+ e.preventDefault();
42
+ const selfIndex = Array.from(parent.children).indexOf(target);
43
+ const focusElement = Array.from(parent.children).at(selfIndex + 5);
44
+ focusManager.focusNext({
45
+ from: focusElement
46
+ });
47
+ break;
48
+ }
49
+ case 'ArrowUp':
50
+ {
51
+ e.preventDefault();
52
+ const selfIndex = Array.from(parent.children).indexOf(target);
53
+ const focusElement = Array.from(parent.children).at(selfIndex - 5);
54
+ focusManager.focusPrevious({
55
+ from: focusElement
56
+ });
57
+ break;
58
+ }
59
+ }
60
+ };
61
+ const years = Array.from({
62
+ length: 36
63
+ }, (_, i) => i + (selectedYear - 30 / 2));
64
+ return years.map(year => /*#__PURE__*/jsx(GridColumn, {
65
+ $active: selectedYear === year,
66
+ onKeyDown: onKeyDown,
67
+ onClick: () => setFocusedYear(year),
68
+ "aria-label": `Set year to ${year}`,
69
+ tabIndex: 0,
70
+ children: year
71
+ }, year));
72
+ };
73
+ const YearGrid = ({
74
+ setFocusedYear,
75
+ year: selectedYear
76
+ }) => {
77
+ return /*#__PURE__*/jsx(Grid, {
78
+ children: /*#__PURE__*/jsx(FocusScope, {
79
+ contain: true,
80
+ restoreFocus: true,
81
+ autoFocus: true,
82
+ children: /*#__PURE__*/jsx(GridFocusManager, {
83
+ year: selectedYear,
84
+ setFocusedYear: setFocusedYear
85
+ })
86
+ })
87
+ });
88
+ };
89
+
90
+ export { YearGrid };
@@ -0,0 +1,40 @@
1
+ import { useDateFieldState } from '@react-stately/datepicker';
2
+ import { forwardRef, useRef } from 'react';
3
+ import { InputFieldWrapper } from './FieldWrapper.js';
4
+ import { DateFieldSegments } from './DateFieldSegments.js';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ /**
8
+ * Datefield is the input field used in {@link DatePicker} to type in a single date.
9
+ * Encapsulates styling / functionality for typing a date
10
+ */
11
+ const DateField = /*#__PURE__*/forwardRef(function ({
12
+ fieldProps,
13
+ groupProps,
14
+ variant,
15
+ dateCreateProps,
16
+ ...props
17
+ }, ref) {
18
+ const state = useDateFieldState(dateCreateProps);
19
+ const inputRef = useRef(null);
20
+ return /*#__PURE__*/jsxs(InputFieldWrapper, {
21
+ ...groupProps,
22
+ readonly: fieldProps.isReadOnly,
23
+ disabled: state.isDisabled,
24
+ color: state.isInvalid ? 'warning' : variant,
25
+ ref: ref,
26
+ className: `field ${state.isInvalid ? 'invalid' : 'valid'}`,
27
+ children: [/*#__PURE__*/jsx(DateFieldSegments, {
28
+ ...state,
29
+ ...fieldProps,
30
+ ref: inputRef
31
+ }), /*#__PURE__*/jsx("span", {
32
+ style: {
33
+ flex: '1 1 auto'
34
+ }
35
+ }), props.rightAdornments]
36
+ });
37
+ });
38
+ DateField.displayName = 'DateField';
39
+
40
+ export { DateField };
@@ -0,0 +1,43 @@
1
+ import { useDateFieldState } from '@react-stately/datepicker';
2
+ import { useLocale, useDateField } from 'react-aria';
3
+ import { createCalendar } from '@internationalized/date';
4
+ import { DateSegment } from './DateSegment.js';
5
+ import { forwardRef } from 'react';
6
+ import { jsx } from 'react/jsx-runtime';
7
+
8
+ // In some cases we need to use the index as key
9
+ /* eslint-disable react/no-array-index-key */
10
+ /**
11
+ * A field that wraps segments for inputting a date / date-time
12
+ */
13
+ const DateFieldSegments = /*#__PURE__*/forwardRef((props, ref) => {
14
+ const {
15
+ locale
16
+ } = useLocale();
17
+ const state = useDateFieldState({
18
+ ...props,
19
+ locale,
20
+ createCalendar
21
+ });
22
+ const {
23
+ fieldProps
24
+ } = useDateField({
25
+ ...props,
26
+ // Type-casting as react-aria expects string | ReactNode, but we only pass strings
27
+ 'aria-label': props.label ?? 'Date input field'
28
+ }, state, ref);
29
+ return /*#__PURE__*/jsx("div", {
30
+ ...fieldProps,
31
+ style: {
32
+ display: 'flex'
33
+ },
34
+ ref: ref,
35
+ children: state.segments.map((segment, i) => /*#__PURE__*/jsx(DateSegment, {
36
+ segment: segment,
37
+ state: state
38
+ }, i))
39
+ });
40
+ });
41
+ DateFieldSegments.displayName = 'SingleDateField';
42
+
43
+ export { DateFieldSegments };
@@ -0,0 +1,43 @@
1
+ import { forwardRef, useRef } from 'react';
2
+ import { InputFieldWrapper } from './FieldWrapper.js';
3
+ import { DateFieldSegments } from './DateFieldSegments.js';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
5
+ import { Typography } from '../../Typography/Typography.js';
6
+
7
+ /**
8
+ * DateRangeField is the input field used in {@link DateRangePicker} to type in a date range.
9
+ */
10
+ const DateRangeField = /*#__PURE__*/forwardRef(function (props, ref) {
11
+ const fromRef = useRef(null);
12
+ const toRef = useRef(null);
13
+ return /*#__PURE__*/jsxs(InputFieldWrapper, {
14
+ ref: ref,
15
+ readonly: props.startFieldProps.isReadOnly,
16
+ className: "field",
17
+ disabled: props.disabled,
18
+ color: props.variant,
19
+ ...props.groupProps,
20
+ children: [/*#__PURE__*/jsx(DateFieldSegments, {
21
+ ...props.startFieldProps,
22
+ ref: fromRef
23
+ }), /*#__PURE__*/jsx(Typography, {
24
+ as: 'span',
25
+ variant: 'text',
26
+ group: 'input',
27
+ style: {
28
+ padding: '0 4px'
29
+ },
30
+ children: "\u2014"
31
+ }), /*#__PURE__*/jsx(DateFieldSegments, {
32
+ ...props.endFieldProps,
33
+ ref: toRef
34
+ }), /*#__PURE__*/jsx("span", {
35
+ style: {
36
+ flex: '1 1 auto'
37
+ }
38
+ }), props.rightAdornments]
39
+ });
40
+ });
41
+ DateRangeField.displayName = 'DateRangeField';
42
+
43
+ export { DateRangeField };
@@ -0,0 +1,47 @@
1
+ import { useRef } from 'react';
2
+ import { useDateSegment } from 'react-aria';
3
+ import styled from 'styled-components';
4
+ import { tokens } from '@equinor/eds-tokens';
5
+ import { jsx } from 'react/jsx-runtime';
6
+
7
+ const Segment = styled.div.withConfig({
8
+ displayName: "DateSegment__Segment",
9
+ componentId: "sc-19uidpx-0"
10
+ })(["color:", ";font-family:", ";&:focus-visible{outline:2px solid ", ";background-color:", ";}", ""], tokens.typography.input.text.color, tokens.typography.input.text.fontFamily, tokens.colors.interactive.primary__resting.rgba, tokens.colors.ui.background__medium.rgba, ({
11
+ $disabled
12
+ }) => $disabled && `color: ${tokens.colors.interactive.disabled__text.rgba};`);
13
+
14
+ /**
15
+ * DateSegment is used to represent a single segment of a date in the DateField (i.e. day, month, year)
16
+ */
17
+ function DateSegment({
18
+ segment,
19
+ state
20
+ }) {
21
+ const ref = useRef(null);
22
+ const {
23
+ segmentProps
24
+ } = useDateSegment(segment, state, ref);
25
+ return /*#__PURE__*/jsx(Segment, {
26
+ ...segmentProps,
27
+ $invalid: state.isInvalid,
28
+ $disabled: state.isDisabled,
29
+ $placeholder: segment.isPlaceholder,
30
+ style: {
31
+ padding: segment.type === 'literal' ? '0 2px' : '0'
32
+ },
33
+ onKeyDown: e => {
34
+ if (e.code === 'Enter' || e.code === 'Space') {
35
+ e.stopPropagation();
36
+ e.preventDefault();
37
+ } else if (segmentProps.onKeyDown) {
38
+ segmentProps.onKeyDown(e);
39
+ }
40
+ },
41
+ ref: ref,
42
+ className: `segment ${segment.isPlaceholder ? 'placeholder' : ''}`,
43
+ children: segment.isPlaceholder || segment.type === 'literal' ? segment.text : segment.text.padStart(segment.type === 'year' ? 4 : 2, '0')
44
+ });
45
+ }
46
+
47
+ export { DateSegment };
@@ -0,0 +1,136 @@
1
+ import styled from 'styled-components';
2
+ import { tokens } from '@equinor/eds-tokens';
3
+ import { forwardRef, useEffect } from 'react';
4
+ import { Popover } from '../../Popover/index.js';
5
+ import { filterDOMProps } from '@react-aria/utils';
6
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
7
+ import { InputWrapper } from '../../InputWrapper/InputWrapper.js';
8
+ import { useEds } from '../../EdsProvider/eds.context.js';
9
+
10
+ const getVariant = variant => {
11
+ if (variant === 'error') {
12
+ return tokens.colors.interactive.danger__resting.rgba;
13
+ }
14
+ if (variant === 'success') {
15
+ return tokens.colors.interactive.success__resting.rgba;
16
+ }
17
+ if (variant === 'warning') {
18
+ return tokens.colors.interactive.warning__resting.rgba;
19
+ }
20
+ return tokens.colors.interactive.primary__resting.rgba;
21
+ };
22
+ const getVariantText = variant => {
23
+ if (variant === 'error') {
24
+ return tokens.colors.interactive.danger__text.rgba;
25
+ }
26
+ if (variant === 'success') {
27
+ return tokens.colors.interactive.success__text.rgba;
28
+ }
29
+ if (variant === 'warning') {
30
+ return tokens.colors.interactive.warning__text.rgba;
31
+ }
32
+ return tokens.typography.input.text.color;
33
+ };
34
+ const StyledInputFieldWrapper = styled.div.withConfig({
35
+ displayName: "FieldWrapper__StyledInputFieldWrapper",
36
+ componentId: "sc-1h0kqs9-0"
37
+ })(["display:flex;align-items:center;background-color:", ";height:", ";padding:0 8px;", " ", " color:", ";cursor:default;"], tokens.colors.ui.background__light.rgba, ({
38
+ $density
39
+ }) => $density === 'compact' ? '24px' : '36px', ({
40
+ $variant,
41
+ $disabled,
42
+ $readonly
43
+ }) => {
44
+ if (!$variant && !$readonly) {
45
+ return `&:focus-within:not(.invalid) {
46
+ outline: 2px solid
47
+ ${tokens.colors.interactive.primary__resting.rgba};
48
+ }
49
+
50
+ ${!$disabled && `&:not(:focus-within) {
51
+ box-shadow: inset 0 -1px 0 0 ${tokens.colors.text.static_icons__tertiary.rgba};`}
52
+ }
53
+ `;
54
+ }
55
+ return `outline: 2px solid ${getVariant($variant)};`;
56
+ }, ({
57
+ $readonly
58
+ }) => {
59
+ return $readonly && `background-color: ${tokens.colors.ui.background__default.rgba};
60
+ outline: none;`;
61
+ }, p => getVariantText(p.$variant));
62
+ /**
63
+ * Applies styles around the date input fields (density, color etc.)
64
+ */
65
+ const InputFieldWrapper = /*#__PURE__*/forwardRef(({
66
+ children,
67
+ color,
68
+ disabled,
69
+ readonly,
70
+ ...props
71
+ }, ref) => {
72
+ const {
73
+ density
74
+ } = useEds();
75
+ // As the props returned are designed for react-aria, some of them are not valid DOM props (i.e. onPress).
76
+ // The filterDOMProps-method strips out the invalid props, but it also removes event listeners due to casing
77
+ const filteredProps = filterDOMProps(props);
78
+ // filterDOMProps also strips event handlers
79
+ const eventHandlers = Object.keys(props).filter(k => k.startsWith('on')).reduce((a, b) => ({
80
+ ...a,
81
+ [b]: props[b]
82
+ }), {});
83
+ return /*#__PURE__*/jsx(StyledInputFieldWrapper, {
84
+ ref: ref,
85
+ $density: density,
86
+ $variant: color,
87
+ $disabled: disabled ?? false,
88
+ $readonly: readonly ?? false,
89
+ ...filteredProps,
90
+ ...eventHandlers,
91
+ children: children
92
+ });
93
+ });
94
+ const FieldWrapper = /*#__PURE__*/forwardRef(({
95
+ children,
96
+ pickerRef,
97
+ calendar,
98
+ isOpen,
99
+ setIsOpen,
100
+ label,
101
+ readonly,
102
+ ...props
103
+ }, ref) => {
104
+ useEffect(() => {
105
+ if (isOpen === false) {
106
+ // Focus the first segment in the input field
107
+ const segment = ref.current?.querySelector('.segment');
108
+ segment?.focus();
109
+ }
110
+ }, [ref, isOpen, pickerRef]);
111
+ return /*#__PURE__*/jsxs(Fragment, {
112
+ children: [/*#__PURE__*/jsx(InputWrapper, {
113
+ readOnly: readonly,
114
+ label: label,
115
+ onKeyDownCapture: event => {
116
+ const isIconTarget = event.target instanceof SVGSVGElement;
117
+ if (!isIconTarget && (event.code === 'Space' || event.code === 'Enter')) {
118
+ setIsOpen(true);
119
+ }
120
+ },
121
+ ...props,
122
+ children: children
123
+ }), /*#__PURE__*/jsx(Popover, {
124
+ open: isOpen ?? false,
125
+ onClose: () => setIsOpen(false),
126
+ anchorEl: ref.current,
127
+ placement: 'bottom-start',
128
+ withinPortal: true,
129
+ children: calendar
130
+ })]
131
+ });
132
+ });
133
+ InputFieldWrapper.displayName = 'InputFieldWrapper';
134
+ FieldWrapper.displayName = 'FieldWrapper';
135
+
136
+ export { FieldWrapper, InputFieldWrapper };
@@ -0,0 +1,61 @@
1
+ import { Icon } from '../../Icon/index.js';
2
+ import { close } from '@equinor/eds-icons';
3
+ import { Button } from '../../Button/Button.js';
4
+ import styled from 'styled-components';
5
+ import { filterDOMProps } from '@react-aria/utils';
6
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
7
+
8
+ const StyledButton = styled(Button).withConfig({
9
+ displayName: "Toggle__StyledButton",
10
+ componentId: "sc-1bwqcj7-0"
11
+ })(["height:24px;width:24px;"]);
12
+
13
+ /**
14
+ * Toggle component encapsulates the reset and open calendar buttons
15
+ */
16
+ const Toggle = ({
17
+ reset,
18
+ setOpen,
19
+ open,
20
+ icon,
21
+ disabled,
22
+ buttonProps,
23
+ valueString,
24
+ readonly
25
+ }) => {
26
+ return readonly || disabled ? null : /*#__PURE__*/jsxs(Fragment, {
27
+ children: [/*#__PURE__*/jsx(StyledButton, {
28
+ disabled: disabled,
29
+ variant: 'ghost_icon',
30
+ "aria-label": 'Reset',
31
+ onClick: () => {
32
+ reset();
33
+ },
34
+ onKeyDown: e => {
35
+ if (e.code === 'Enter' || e.code === 'Space') {
36
+ e.preventDefault();
37
+ e.stopPropagation();
38
+ reset();
39
+ }
40
+ },
41
+ children: /*#__PURE__*/jsx(Icon, {
42
+ data: close
43
+ })
44
+ }), /*#__PURE__*/jsx(StyledButton, {
45
+ ...filterDOMProps(buttonProps),
46
+ disabled: disabled,
47
+ "aria-label": valueString ? `Change date, ${valueString}` : `Change date`,
48
+ variant: 'ghost_icon',
49
+ onClick: e => {
50
+ e.preventDefault();
51
+ e.stopPropagation();
52
+ setOpen(!open);
53
+ },
54
+ children: /*#__PURE__*/jsx(Icon, {
55
+ data: icon
56
+ })
57
+ })]
58
+ });
59
+ };
60
+
61
+ export { Toggle };
@@ -0,0 +1,21 @@
1
+ import { createContext } from 'react';
2
+ import { jsx } from 'react/jsx-runtime';
3
+
4
+ const intl = new Intl.DateTimeFormat();
5
+ const defaultTimezone = intl.resolvedOptions().timeZone;
6
+ const DatePickerContext = /*#__PURE__*/createContext({
7
+ timezone: defaultTimezone
8
+ });
9
+ const DatePickerProvider = ({
10
+ timezone,
11
+ children
12
+ }) => {
13
+ return /*#__PURE__*/jsx(DatePickerContext.Provider, {
14
+ value: {
15
+ timezone: timezone ?? defaultTimezone
16
+ },
17
+ children: children
18
+ });
19
+ };
20
+
21
+ export { DatePickerProvider, defaultTimezone };
@@ -0,0 +1,8 @@
1
+ import { toCalendarDateTime, fromDate, toCalendarDate } from '@internationalized/date';
2
+
3
+ const getCalendarDate = (value, timezone, showTimeInput = false) => {
4
+ if (!value) return null;
5
+ return showTimeInput ? toCalendarDateTime(fromDate(value, timezone)) : toCalendarDate(fromDate(value, timezone));
6
+ };
7
+
8
+ export { getCalendarDate };
@@ -0,0 +1,20 @@
1
+ import { toCalendarDate, fromDate } from '@internationalized/date';
2
+ import { defaultTimezone } from './context.js';
3
+
4
+ const useConvertedValidationFunctions = (minValue, maxValue, isDateUnavailable, timezone) => {
5
+ const tz = timezone ?? defaultTimezone;
6
+ const _minValue = minValue ? toCalendarDate(fromDate(minValue, tz)) : undefined;
7
+ const _maxValue = maxValue ? toCalendarDate(fromDate(maxValue, tz)) : undefined;
8
+ const _minTimeValue = minValue ? fromDate(minValue, tz) : undefined;
9
+ const _maxTimeValue = maxValue ? fromDate(maxValue, tz) : undefined;
10
+ const _isDateUnavailable = value => isDateUnavailable ? isDateUnavailable(value.toDate(tz)) : false;
11
+ return {
12
+ _minValue,
13
+ _maxValue,
14
+ _isDateUnavailable,
15
+ _minTimeValue,
16
+ _maxTimeValue
17
+ };
18
+ };
19
+
20
+ export { useConvertedValidationFunctions };