@orchestrator-ui/orchestrator-ui-components 2.2.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orchestrator-ui/orchestrator-ui-components",
3
- "version": "2.2.0",
3
+ "version": "2.4.0",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Library of UI Components used to display the workflow orchestrator frontend",
6
6
  "author": {
@@ -276,23 +276,6 @@ function SubscriptionFieldDefinition({
276
276
  }
277
277
  }
278
278
 
279
- // Untagged ports that are unavailable because they are already in use are part still part of the graphql result
280
- // we know an untagged port is unavailable when the port is untagged but it's has an inUseBySubscription since untagged
281
- // ports can only be used once. This is a hard condition to capture in a graphQL filter, solving it in the backend would
282
- // be better but for now we do this extra check in the frontend until we refactor the forms part more thoroughly.
283
- // https://github.com/workfloworchestrator/orchestrator-ui-library/issues/1250
284
- if (
285
- getPortMode(subscription.productBlockInstances) ===
286
- PortMode.UNTAGGED
287
- ) {
288
- if (
289
- subscription.inUseBySubscriptions.pageInfo.totalItems &&
290
- subscription.inUseBySubscriptions.pageInfo.totalItems > 0
291
- ) {
292
- return false;
293
- }
294
- }
295
-
296
279
  return true;
297
280
  });
298
281
 
@@ -1,16 +1,39 @@
1
1
  import React, { FC } from 'react';
2
2
 
3
- import { useWithOrchestratorTheme } from '@/hooks';
3
+ import { EuiCopy } from '@elastic/eui';
4
4
 
5
- import { getFirstUuidPart } from '../../../utils';
6
- import { getStyles } from './styles';
5
+ import { useOrchestratorTheme, useWithOrchestratorTheme } from '@/hooks';
6
+ import { WfoClipboardCopy } from '@/icons/WfoClipboardCopy';
7
+ import { getFirstUuidPart } from '@/utils';
8
+
9
+ import { COPY_ICON_CLASS, getStyles } from './styles';
7
10
 
8
11
  export type WfoFirstUUIDPartProps = {
9
12
  UUID: string;
10
13
  };
11
14
 
12
15
  export const WfoFirstPartUUID: FC<WfoFirstUUIDPartProps> = ({ UUID }) => {
13
- const { uuidFieldStyle } = useWithOrchestratorTheme(getStyles);
16
+ const { uuidFieldStyle, clickable } = useWithOrchestratorTheme(getStyles);
17
+ const { theme } = useOrchestratorTheme();
14
18
 
15
- return <span css={uuidFieldStyle}>{getFirstUuidPart(UUID)}</span>;
19
+ return (
20
+ <span css={uuidFieldStyle} title={UUID}>
21
+ {getFirstUuidPart(UUID)}
22
+ <EuiCopy textToCopy={UUID}>
23
+ {(copy) => (
24
+ <div
25
+ className={COPY_ICON_CLASS}
26
+ onClick={copy}
27
+ css={clickable}
28
+ >
29
+ <WfoClipboardCopy
30
+ width={16}
31
+ height={16}
32
+ color={theme.colors.mediumShade}
33
+ />
34
+ </div>
35
+ )}
36
+ </EuiCopy>
37
+ </span>
38
+ );
16
39
  };
@@ -2,12 +2,28 @@ import { css } from '@emotion/react';
2
2
 
3
3
  import { WfoTheme } from '@/hooks';
4
4
 
5
+ export const COPY_ICON_CLASS = 'copyIcon';
6
+
5
7
  export const getStyles = ({ theme }: WfoTheme) => {
6
8
  const uuidFieldStyle = css({
7
9
  fontWeight: theme.font.weight.medium,
10
+ display: 'flex',
11
+ gap: theme.size.xs,
12
+ [`&:focus-visible .${COPY_ICON_CLASS}`]: {
13
+ visibility: 'visible',
14
+ },
15
+ [`&:hover .${COPY_ICON_CLASS}`]: {
16
+ visibility: 'visible',
17
+ },
18
+ });
19
+
20
+ const clickable = css({
21
+ cursor: 'pointer',
22
+ visibility: 'hidden',
8
23
  });
9
24
 
10
25
  return {
26
+ clickable,
11
27
  uuidFieldStyle,
12
28
  };
13
29
  };
@@ -10,6 +10,9 @@ export type WfoSortButtonsProps = {
10
10
  onChangeSortOrder: (updatedSortOrder: SortOrder) => void;
11
11
  };
12
12
 
13
+ /**
14
+ * @deprecated This component is not used anymore and will be removed in the next major version.
15
+ */
13
16
  export const WfoSortButtons: FC<WfoSortButtonsProps> = ({
14
17
  sortOrder,
15
18
  onChangeSortOrder,
@@ -1,11 +1,13 @@
1
1
  import React, { FC } from 'react';
2
2
 
3
3
  import { useOrchestratorTheme } from '@/hooks';
4
- import { WfoArrowNarrowDown, WfoArrowNarrowUp } from '@/icons';
4
+ import { WfoArrowNarrowDown, WfoArrowNarrowUp, WfoArrowsUpDown } from '@/icons';
5
5
  import { SortOrder } from '@/types';
6
6
 
7
+ import { SORTABLE_ICON_CLASS } from './styles';
8
+
7
9
  export type WfoSortDirectionIconProps = {
8
- sortDirection: SortOrder;
10
+ sortDirection?: SortOrder;
9
11
  };
10
12
 
11
13
  export const WfoSortDirectionIcon: FC<WfoSortDirectionIconProps> = ({
@@ -13,6 +15,16 @@ export const WfoSortDirectionIcon: FC<WfoSortDirectionIconProps> = ({
13
15
  }) => {
14
16
  const { theme } = useOrchestratorTheme();
15
17
 
18
+ if (!sortDirection) {
19
+ return (
20
+ <WfoArrowsUpDown
21
+ className={SORTABLE_ICON_CLASS}
22
+ css={{ visibility: 'hidden' }}
23
+ color={theme.colors.subduedText}
24
+ />
25
+ );
26
+ }
27
+
16
28
  return sortDirection === SortOrder.ASC ? (
17
29
  <WfoArrowNarrowUp
18
30
  color={theme.colors.subduedText}
@@ -10,12 +10,16 @@ import {
10
10
  useGeneratedHtmlId,
11
11
  } from '@elastic/eui';
12
12
 
13
- import { WfoSortButtons } from '@/components';
13
+ import { getUpdatedSortOrder } from '@/components/WfoTable/WfoTable/utils';
14
14
  import { useWithOrchestratorTheme } from '@/hooks';
15
15
  import { SortOrder } from '@/types';
16
16
 
17
17
  import { WfoSortDirectionIcon } from './WfoSortDirectionIcon';
18
- import { getWfoBasicTableStyles } from './styles';
18
+ import {
19
+ HEADER_CELL_SORT_BUTTON_CLASS,
20
+ HEADER_CELL_TITLE_BUTTON_CLASS,
21
+ getWfoBasicTableStyles,
22
+ } from './styles';
19
23
 
20
24
  export type WfoTableHeaderCellProps = {
21
25
  fieldName: string;
@@ -33,17 +37,18 @@ export const WfoTableHeaderCell: FC<WfoTableHeaderCellProps> = ({
33
37
  onSearch,
34
38
  }) => {
35
39
  const {
36
- headerCellContentStyle,
40
+ headerCellStyle,
41
+ getHeaderCellContentStyle,
37
42
  headerCellPopoverHeaderStyle,
38
43
  headerCellPopoverHeaderTitleStyle,
39
44
  headerCellPopoverContentStyle,
40
- getHeaderCellButtonStyle,
45
+ getTitleButtonStyle,
46
+ sortButtonStyle,
41
47
  } = useWithOrchestratorTheme(getWfoBasicTableStyles);
42
48
  const t = useTranslations('common');
43
49
 
44
50
  const isSortable = !!onSetSortOrder;
45
51
  const isFilterable = !!onSearch;
46
- const shouldShowPopover = isSortable || isFilterable;
47
52
 
48
53
  const smallContextMenuPopoverId = useGeneratedHtmlId({
49
54
  prefix: 'smallContextMenuPopover',
@@ -53,24 +58,14 @@ export const WfoTableHeaderCell: FC<WfoTableHeaderCellProps> = ({
53
58
  const handleButtonClick = () => setPopover(!isPopoverOpen);
54
59
  const closePopover = () => setPopover(false);
55
60
 
56
- const handleChangeSortOrder = (updatedSortOrder: SortOrder) => {
57
- onSetSortOrder?.(updatedSortOrder);
58
- closePopover();
59
- };
60
-
61
61
  const handleSearch = (searchText: string) => {
62
62
  onSearch?.(searchText);
63
63
  closePopover();
64
64
  };
65
65
 
66
66
  const WfoHeaderCellContentButton = () => (
67
- <button onClick={handleButtonClick} disabled={!shouldShowPopover}>
68
- <div css={getHeaderCellButtonStyle(shouldShowPopover)}>
69
- <div css={headerCellContentStyle}>{children}</div>
70
- {sortOrder && (
71
- <WfoSortDirectionIcon sortDirection={sortOrder} />
72
- )}
73
- </div>
67
+ <button onClick={handleButtonClick} disabled={!isFilterable}>
68
+ <div css={getHeaderCellContentStyle(isFilterable)}>{children}</div>
74
69
  </button>
75
70
  );
76
71
 
@@ -79,12 +74,6 @@ export const WfoTableHeaderCell: FC<WfoTableHeaderCellProps> = ({
79
74
  <EuiText size="xs" css={headerCellPopoverHeaderTitleStyle}>
80
75
  {children}
81
76
  </EuiText>
82
- {isSortable && (
83
- <WfoSortButtons
84
- sortOrder={sortOrder}
85
- onChangeSortOrder={handleChangeSortOrder}
86
- />
87
- )}
88
77
  </div>
89
78
  );
90
79
 
@@ -100,22 +89,34 @@ export const WfoTableHeaderCell: FC<WfoTableHeaderCellProps> = ({
100
89
  );
101
90
 
102
91
  return (
103
- <EuiPopover
104
- initialFocus={`.euiPanel .euiFieldSearch.${fieldName}`}
105
- id={smallContextMenuPopoverId}
106
- button={<WfoHeaderCellContentButton />}
107
- isOpen={isPopoverOpen}
108
- closePopover={closePopover}
109
- panelPaddingSize="none"
110
- anchorPosition="downLeft"
111
- >
112
- <WfoPopoverHeader />
113
- {isFilterable && (
114
- <>
115
- <EuiHorizontalRule margin="none" />
116
- <WfoPopoverContent />
117
- </>
92
+ <div css={headerCellStyle}>
93
+ <EuiPopover
94
+ className={HEADER_CELL_TITLE_BUTTON_CLASS}
95
+ css={getTitleButtonStyle(sortOrder)}
96
+ initialFocus={`.euiPanel .euiFieldSearch.${fieldName}`}
97
+ id={smallContextMenuPopoverId}
98
+ button={<WfoHeaderCellContentButton />}
99
+ isOpen={isPopoverOpen}
100
+ closePopover={closePopover}
101
+ panelPaddingSize="none"
102
+ anchorPosition="downLeft"
103
+ >
104
+ <WfoPopoverHeader />
105
+ <EuiHorizontalRule margin="none" />
106
+ <WfoPopoverContent />
107
+ </EuiPopover>
108
+
109
+ {isSortable && (
110
+ <button
111
+ className={HEADER_CELL_SORT_BUTTON_CLASS}
112
+ css={sortButtonStyle}
113
+ onClick={() =>
114
+ onSetSortOrder(getUpdatedSortOrder(sortOrder))
115
+ }
116
+ >
117
+ <WfoSortDirectionIcon sortDirection={sortOrder} />
118
+ </button>
118
119
  )}
119
- </EuiPopover>
120
+ </div>
120
121
  );
121
122
  };
@@ -1,6 +1,11 @@
1
1
  import { css } from '@emotion/react';
2
2
 
3
3
  import { WfoTheme } from '@/hooks';
4
+ import { SortOrder } from '@/types';
5
+
6
+ export const HEADER_CELL_TITLE_BUTTON_CLASS = 'headerCellTitleButton';
7
+ export const HEADER_CELL_SORT_BUTTON_CLASS = 'headerCellSortButton';
8
+ export const SORTABLE_ICON_CLASS = 'sortableIcon';
4
9
 
5
10
  export const getWfoBasicTableStyles = ({ theme }: WfoTheme) => {
6
11
  const radius = theme.border.radius.medium;
@@ -72,10 +77,23 @@ export const getWfoBasicTableStyles = ({ theme }: WfoTheme) => {
72
77
  },
73
78
  ]);
74
79
 
75
- const headerCellContentStyle = css({
76
- fontWeight: theme.font.weight.semiBold,
80
+ const headerCellStyle = css({
81
+ display: 'flex',
82
+ justifyContent: 'flex-start',
83
+ alignItems: 'center',
84
+
85
+ [`.${HEADER_CELL_TITLE_BUTTON_CLASS}:has(+ .${HEADER_CELL_SORT_BUTTON_CLASS}:focus-visible)`]:
86
+ {
87
+ overflow: 'hidden',
88
+ },
77
89
  });
78
90
 
91
+ const getHeaderCellContentStyle = (isSortable: boolean) =>
92
+ css({
93
+ cursor: isSortable ? 'pointer' : 'not-allowed',
94
+ fontWeight: theme.font.weight.semiBold,
95
+ });
96
+
79
97
  const headerCellPopoverHeaderStyle = css({
80
98
  margin: theme.size.m,
81
99
  display: 'flex',
@@ -91,20 +109,30 @@ export const getWfoBasicTableStyles = ({ theme }: WfoTheme) => {
91
109
  margin: theme.size.m,
92
110
  });
93
111
 
94
- const getHeaderCellButtonStyle = (isSortable: boolean) =>
112
+ const getTitleButtonStyle = (sortOrder?: SortOrder) =>
95
113
  css({
96
- display: 'flex',
97
- alignItems: 'center',
98
- cursor: isSortable ? 'pointer' : 'not-allowed',
114
+ flex: '0 1 auto',
115
+ overflow: sortOrder === undefined ? 'visible' : 'hidden',
99
116
  });
100
117
 
118
+ const sortButtonStyle = css({
119
+ display: 'flex',
120
+ flex: '0 0 auto',
121
+ alignItems: 'center',
122
+ [`&:focus-visible .${SORTABLE_ICON_CLASS}`]: {
123
+ visibility: 'visible',
124
+ },
125
+ });
126
+
101
127
  return {
102
128
  basicTableStyle,
103
- headerCellContentStyle,
129
+ headerCellStyle,
130
+ getHeaderCellContentStyle,
104
131
  headerCellPopoverHeaderStyle,
105
132
  headerCellPopoverHeaderTitleStyle,
106
133
  headerCellPopoverContentStyle,
107
- getHeaderCellButtonStyle,
134
+ getTitleButtonStyle,
135
+ sortButtonStyle,
108
136
  getStatusColumnStyle,
109
137
  dropDownTableStyle,
110
138
  expandableTableStyle,
@@ -28,7 +28,7 @@ export const WfoTableHeaderRow = <T extends object>({
28
28
  onUpdateDataSearch,
29
29
  className,
30
30
  }: WfoTableHeaderRowProps<T>) => {
31
- const { cellStyle, rowStyle, setWidth } =
31
+ const { cellStyle, headerCellStyle, rowStyle, setWidth } =
32
32
  useWithOrchestratorTheme(getWfoTableStyles);
33
33
 
34
34
  const sortedVisibleColumns = getSortedVisibleColumns(
@@ -55,6 +55,10 @@ export const WfoTableHeaderRow = <T extends object>({
55
55
  cellStyle,
56
56
  !columnConfig.disableDefaultCellStyle,
57
57
  ),
58
+ ...toOptionalArrayEntry(
59
+ headerCellStyle,
60
+ !!columnConfig.isSortable,
61
+ ),
58
62
  setWidth(columnConfig.width),
59
63
  ]}
60
64
  >
@@ -2,9 +2,14 @@ import { CSSProperties } from 'react';
2
2
 
3
3
  import { css, keyframes } from '@emotion/react';
4
4
 
5
- import { TABLE_ROW_HEIGHT } from '@/components/WfoTable';
6
5
  import { WfoTheme } from '@/hooks';
7
6
 
7
+ import {
8
+ HEADER_CELL_TITLE_BUTTON_CLASS,
9
+ SORTABLE_ICON_CLASS,
10
+ } from './WfoTableHeaderCell/styles';
11
+ import { TABLE_ROW_HEIGHT } from './constants';
12
+
8
13
  export const getWfoTableStyles = ({ theme }: WfoTheme) => {
9
14
  const radius = theme.border.radius.medium;
10
15
 
@@ -77,6 +82,17 @@ export const getWfoTableStyles = ({ theme }: WfoTheme) => {
77
82
  backgroundColor: theme.colors.lightestShade,
78
83
  });
79
84
 
85
+ const headerCellStyle = css({
86
+ [`&:hover`]: {
87
+ [`.${SORTABLE_ICON_CLASS}`]: {
88
+ visibility: 'visible',
89
+ },
90
+ [`.${HEADER_CELL_TITLE_BUTTON_CLASS}`]: {
91
+ overflow: 'hidden',
92
+ },
93
+ },
94
+ });
95
+
80
96
  const cellStyle = css({
81
97
  paddingLeft: theme.size.m,
82
98
  paddingRight: theme.size.m,
@@ -109,6 +125,7 @@ export const getWfoTableStyles = ({ theme }: WfoTheme) => {
109
125
  rowStyle,
110
126
  dataRowStyle,
111
127
  expandedRowStyle,
128
+ headerCellStyle,
112
129
  cellStyle,
113
130
  emptyTableMessageStyle,
114
131
  clickableStyle,
@@ -2,8 +2,12 @@ import {
2
2
  ColumnType,
3
3
  WfoTableColumnConfig,
4
4
  } from '@/components/WfoTable/WfoTable/WfoTable';
5
+ import { SortOrder } from '@/types';
5
6
 
6
- import { mapSortableAndFilterableValuesToTableColumnConfig } from './utils';
7
+ import {
8
+ getUpdatedSortOrder,
9
+ mapSortableAndFilterableValuesToTableColumnConfig,
10
+ } from './utils';
7
11
 
8
12
  type TestObject = {
9
13
  name: string;
@@ -21,59 +25,83 @@ const tableColumnConfig: WfoTableColumnConfig<TestObject> = {
21
25
  },
22
26
  };
23
27
 
24
- describe('mapSortableAndFilterableValuesToTableColumnConfig', () => {
25
- it('sets the sortable and filterable properties for the columnConfig object to true when the colum name is specified in the list', () => {
26
- // Given
27
- const sortableFieldNames = ['name', 'age', 'nonExistingFieldName'];
28
- const filterableFieldNames = ['name', 'age', 'nonExistingFieldName'];
28
+ describe('utils', () => {
29
+ describe('getUpdatedSortOrder()', () => {
30
+ it('returns SortOrder.DESC if the currentSortOrder is SortOrder.ASC', () => {
31
+ const currentSortOrder = SortOrder.ASC;
32
+ const result = getUpdatedSortOrder(currentSortOrder);
33
+ expect(result).toBe(SortOrder.DESC);
34
+ });
35
+ it('returns SortOrder.ASC if the currentSortOrder is SortOrder.DESC', () => {
36
+ const currentSortOrder = SortOrder.DESC;
37
+ const result = getUpdatedSortOrder(currentSortOrder);
38
+ expect(result).toBe(SortOrder.ASC);
39
+ });
40
+ it('returns SortOrder.ASC if the currentSortOrder is undefined', () => {
41
+ const currentSortOrder = undefined;
42
+ const result = getUpdatedSortOrder(currentSortOrder);
43
+ expect(result).toBe(SortOrder.ASC);
44
+ });
45
+ });
46
+
47
+ describe('mapSortableAndFilterableValuesToTableColumnConfig()', () => {
48
+ it('sets the sortable and filterable properties for the columnConfig object to true when the colum name is specified in the list', () => {
49
+ // Given
50
+ const sortableFieldNames = ['name', 'age', 'nonExistingFieldName'];
51
+ const filterableFieldNames = [
52
+ 'name',
53
+ 'age',
54
+ 'nonExistingFieldName',
55
+ ];
29
56
 
30
- // When
31
- const result =
32
- mapSortableAndFilterableValuesToTableColumnConfig<TestObject>(
33
- tableColumnConfig,
34
- sortableFieldNames,
35
- filterableFieldNames,
36
- );
57
+ // When
58
+ const result =
59
+ mapSortableAndFilterableValuesToTableColumnConfig<TestObject>(
60
+ tableColumnConfig,
61
+ sortableFieldNames,
62
+ filterableFieldNames,
63
+ );
37
64
 
38
- // Then
39
- if (
40
- result.name?.columnType === ColumnType.DATA &&
41
- result.age?.columnType === ColumnType.DATA
42
- ) {
43
- expect(result.name.isSortable).toEqual(true);
44
- expect(result.name.isFilterable).toEqual(true);
45
- expect(result.age.isSortable).toEqual(true);
46
- expect(result.age.isFilterable).toEqual(true);
47
- } else {
48
- // Preventing silently skipping above expects
49
- throw Error('Some of the fields are not data fields');
50
- }
51
- });
52
- it('sets the sortable and filterable properties for the columnConfig object to false when the colum name is not specified in the list', () => {
53
- // Given
54
- const sortableFieldNames = ['nonExistingFieldName'];
55
- const filterableFieldNames: string[] = [];
65
+ // Then
66
+ if (
67
+ result.name?.columnType === ColumnType.DATA &&
68
+ result.age?.columnType === ColumnType.DATA
69
+ ) {
70
+ expect(result.name.isSortable).toEqual(true);
71
+ expect(result.name.isFilterable).toEqual(true);
72
+ expect(result.age.isSortable).toEqual(true);
73
+ expect(result.age.isFilterable).toEqual(true);
74
+ } else {
75
+ // Preventing silently skipping above expects
76
+ throw Error('Some of the fields are not data fields');
77
+ }
78
+ });
79
+ it('sets the sortable and filterable properties for the columnConfig object to false when the colum name is not specified in the list', () => {
80
+ // Given
81
+ const sortableFieldNames = ['nonExistingFieldName'];
82
+ const filterableFieldNames: string[] = [];
56
83
 
57
- // When
58
- const result =
59
- mapSortableAndFilterableValuesToTableColumnConfig<TestObject>(
60
- tableColumnConfig,
61
- sortableFieldNames,
62
- filterableFieldNames,
63
- );
84
+ // When
85
+ const result =
86
+ mapSortableAndFilterableValuesToTableColumnConfig<TestObject>(
87
+ tableColumnConfig,
88
+ sortableFieldNames,
89
+ filterableFieldNames,
90
+ );
64
91
 
65
- // Then
66
- if (
67
- result.name?.columnType === ColumnType.DATA &&
68
- result.age?.columnType === ColumnType.DATA
69
- ) {
70
- expect(result.name.isSortable).toEqual(false);
71
- expect(result.name.isFilterable).toEqual(false);
72
- expect(result.age.isSortable).toEqual(false);
73
- expect(result.age.isFilterable).toEqual(false);
74
- } else {
75
- // Preventing silently skipping above expects
76
- throw Error('Some of the fields are not data fields');
77
- }
92
+ // Then
93
+ if (
94
+ result.name?.columnType === ColumnType.DATA &&
95
+ result.age?.columnType === ColumnType.DATA
96
+ ) {
97
+ expect(result.name.isSortable).toEqual(false);
98
+ expect(result.name.isFilterable).toEqual(false);
99
+ expect(result.age.isSortable).toEqual(false);
100
+ expect(result.age.isFilterable).toEqual(false);
101
+ } else {
102
+ // Preventing silently skipping above expects
103
+ throw Error('Some of the fields are not data fields');
104
+ }
105
+ });
78
106
  });
79
107
  });
@@ -1,4 +1,5 @@
1
1
  import { TableColumnKeys } from '@/components';
2
+ import { SortOrder } from '@/types';
2
3
  import { toObjectWithSortedKeys } from '@/utils';
3
4
 
4
5
  import {
@@ -33,6 +34,9 @@ export const getSortedVisibleColumns = <T extends object>(
33
34
  );
34
35
  };
35
36
 
37
+ export const getUpdatedSortOrder = (currentSortOrder?: SortOrder) =>
38
+ currentSortOrder === SortOrder.ASC ? SortOrder.DESC : SortOrder.ASC;
39
+
36
40
  /**
37
41
  * Maps from WfoTableColumnConfig to WfoTableColumnConfig.
38
42
  * A generic type must be provided to prevent type errors
@@ -1 +1 @@
1
- export const ORCHESTRATOR_UI_LIBRARY_VERSION = '2.2.0';
1
+ export const ORCHESTRATOR_UI_LIBRARY_VERSION = '2.4.0';
@@ -0,0 +1,27 @@
1
+ import React, { FC } from 'react';
2
+
3
+ import { WfoIconProps } from '@/icons/WfoIconProps';
4
+
5
+ import { withWfoHeroIconsWrapper } from './WfoHeroIconsWrapper';
6
+
7
+ const WfoArrowsUpDownSvg: FC<WfoIconProps> = ({
8
+ width = 20,
9
+ height = 20,
10
+ color = '#000000',
11
+ }) => (
12
+ <svg
13
+ width={width}
14
+ height={height}
15
+ viewBox="0 0 24 24"
16
+ fill={color}
17
+ xmlns="http://www.w3.org/2000/svg"
18
+ >
19
+ <path
20
+ fillRule="evenodd"
21
+ d="M6.97 2.47a.75.75 0 0 1 1.06 0l4.5 4.5a.75.75 0 0 1-1.06 1.06L8.25 4.81V16.5a.75.75 0 0 1-1.5 0V4.81L3.53 8.03a.75.75 0 0 1-1.06-1.06l4.5-4.5Zm9.53 4.28a.75.75 0 0 1 .75.75v11.69l3.22-3.22a.75.75 0 1 1 1.06 1.06l-4.5 4.5a.75.75 0 0 1-1.06 0l-4.5-4.5a.75.75 0 1 1 1.06-1.06l3.22 3.22V7.5a.75.75 0 0 1 .75-.75Z"
22
+ clipRule="evenodd"
23
+ />
24
+ </svg>
25
+ );
26
+
27
+ export const WfoArrowsUpDown = withWfoHeroIconsWrapper(WfoArrowsUpDownSvg);
@@ -0,0 +1,43 @@
1
+ import React, { FC, ReactElement } from 'react';
2
+
3
+ import { useOrchestratorTheme } from '@/hooks';
4
+ import { WfoIconProps } from '@/icons';
5
+
6
+ export type WfoHeroIconsWrapperProps = {
7
+ children: ReactElement;
8
+ className?: string;
9
+ };
10
+
11
+ export const WfoHeroIconsWrapper: FC<WfoHeroIconsWrapperProps> = ({
12
+ children,
13
+ className,
14
+ }) => {
15
+ const { theme } = useOrchestratorTheme();
16
+
17
+ return (
18
+ <div
19
+ className={className}
20
+ css={{
21
+ marginLeft: theme.size.xs,
22
+ marginRight: theme.size.xs,
23
+ display: 'flex',
24
+ alignItems: 'center',
25
+ }}
26
+ >
27
+ {children}
28
+ </div>
29
+ );
30
+ };
31
+
32
+ export const withWfoHeroIconsWrapper = (Icon: FC<WfoIconProps>) => {
33
+ const wfoHeroIconsWrapperWithIcon = ({
34
+ className,
35
+ ...iconProps
36
+ }: WfoIconProps & Omit<WfoHeroIconsWrapperProps, 'children'>) => (
37
+ <WfoHeroIconsWrapper className={className}>
38
+ <Icon {...iconProps} />
39
+ </WfoHeroIconsWrapper>
40
+ );
41
+ wfoHeroIconsWrapperWithIcon.displayName = 'WfoHeroIconsWrapper';
42
+ return wfoHeroIconsWrapperWithIcon;
43
+ };
@@ -0,0 +1,2 @@
1
+ export * from './WfoArrowsUpDown';
2
+ export * from './WfoHeroIconsWrapper';