@orchestrator-ui/orchestrator-ui-components 5.9.0 → 6.1.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 (61) hide show
  1. package/.turbo/turbo-build.log +8 -8
  2. package/.turbo/turbo-lint.log +10 -1
  3. package/.turbo/turbo-test.log +10 -10
  4. package/CHANGELOG.md +12 -0
  5. package/__mocks__/@copilotkit/react-core.js +9 -0
  6. package/__mocks__/@copilotkit/react-ui.js +11 -0
  7. package/dist/index.d.ts +1432 -2
  8. package/dist/index.js +3006 -28
  9. package/dist/index.js.map +1 -1
  10. package/package.json +5 -1
  11. package/src/components/WfoAgent/FilterDisplay/FilterDisplay.tsx +182 -0
  12. package/src/components/WfoAgent/FilterDisplay/index.ts +1 -0
  13. package/src/components/WfoAgent/FilterDisplay/styles.ts +62 -0
  14. package/src/components/WfoAgent/WfoAgent/WfoAgent.tsx +100 -0
  15. package/src/components/WfoAgent/WfoAgent/index.ts +1 -0
  16. package/src/components/WfoAgent/index.ts +2 -0
  17. package/src/components/WfoSearchPage/WfoConditionRow/WfoConditionRow.tsx +388 -0
  18. package/src/components/WfoSearchPage/WfoConditionRow/WfoFieldSelector.tsx +43 -0
  19. package/src/components/WfoSearchPage/WfoConditionRow/WfoOperatorSelector.tsx +100 -0
  20. package/src/components/WfoSearchPage/WfoConditionRow/WfoPathChips.tsx +193 -0
  21. package/src/components/WfoSearchPage/WfoConditionRow/WfoPathSelector.tsx +54 -0
  22. package/src/components/WfoSearchPage/WfoConditionRow/WfoRenderFunctions.tsx +107 -0
  23. package/src/components/WfoSearchPage/WfoConditionRow/WfoSelectedPathDisplay.tsx +75 -0
  24. package/src/components/WfoSearchPage/WfoConditionRow/index.ts +11 -0
  25. package/src/components/WfoSearchPage/WfoConditionRow/types.ts +84 -0
  26. package/src/components/WfoSearchPage/WfoConditionRow/utils.ts +63 -0
  27. package/src/components/WfoSearchPage/WfoFilterGroup/WfoFilterGroup.tsx +238 -0
  28. package/src/components/WfoSearchPage/WfoFilterGroup/index.ts +1 -0
  29. package/src/components/WfoSearchPage/WfoSearch/WfoSearch.tsx +453 -0
  30. package/src/components/WfoSearchPage/WfoSearch/index.ts +1 -0
  31. package/src/components/WfoSearchPage/WfoSearchResults/WfoHighlightedText.tsx +63 -0
  32. package/src/components/WfoSearchPage/WfoSearchResults/WfoPathBreadcrumb.tsx +80 -0
  33. package/src/components/WfoSearchPage/WfoSearchResults/WfoSearchEmptyState.tsx +24 -0
  34. package/src/components/WfoSearchPage/WfoSearchResults/WfoSearchLoadingState.tsx +24 -0
  35. package/src/components/WfoSearchPage/WfoSearchResults/WfoSearchMetadataHeader.tsx +24 -0
  36. package/src/components/WfoSearchPage/WfoSearchResults/WfoSearchPaginationInfo.tsx +107 -0
  37. package/src/components/WfoSearchPage/WfoSearchResults/WfoSearchResultItem.tsx +157 -0
  38. package/src/components/WfoSearchPage/WfoSearchResults/WfoSearchResults.tsx +65 -0
  39. package/src/components/WfoSearchPage/WfoSearchResults/WfoSubscriptionDetailModal.tsx +55 -0
  40. package/src/components/WfoSearchPage/WfoSearchResults/index.ts +10 -0
  41. package/src/components/WfoSearchPage/WfoValueControl/WfoValueControl.tsx +247 -0
  42. package/src/components/WfoSearchPage/WfoValueControl/index.ts +1 -0
  43. package/src/components/WfoSearchPage/constants.ts +17 -0
  44. package/src/components/WfoSearchPage/index.ts +6 -0
  45. package/src/components/WfoSearchPage/utils.ts +271 -0
  46. package/src/components/index.ts +2 -0
  47. package/src/configuration/version.ts +1 -1
  48. package/src/hooks/useDebounce.ts +21 -0
  49. package/src/hooks/usePathAutoComplete.ts +133 -0
  50. package/src/hooks/useSearch.ts +83 -0
  51. package/src/hooks/useSearchPagination.ts +148 -0
  52. package/src/hooks/useUrlParams.ts +120 -0
  53. package/src/icons/WfoPencil.tsx +23 -4
  54. package/src/messages/en-GB.json +79 -1
  55. package/src/messages/nl-NL.json +2 -1
  56. package/src/rtk/endpoints/index.ts +1 -0
  57. package/src/rtk/endpoints/search.ts +90 -0
  58. package/src/types/index.ts +1 -0
  59. package/src/types/search.ts +215 -0
  60. package/src/utils/optionalArray.spec.ts +27 -0
  61. package/src/utils/optionalArray.ts +5 -0
@@ -0,0 +1,63 @@
1
+ import React, { FC, useMemo } from 'react';
2
+
3
+ import { css } from '@emotion/react';
4
+
5
+ import { useOrchestratorTheme } from '@/hooks';
6
+
7
+ interface WfoHighlightedTextProps {
8
+ text: string;
9
+ highlight_indices: [number, number][];
10
+ }
11
+
12
+ export const WfoHighlightedText: FC<WfoHighlightedTextProps> = ({
13
+ text,
14
+ highlight_indices,
15
+ }) => {
16
+ const { theme } = useOrchestratorTheme();
17
+
18
+ const highlightStyles = css`
19
+ background-color: ${theme.colors.warning};
20
+ color: ${theme.colors.plainDark};
21
+ padding: 0 ${theme.size.xs};
22
+ font-family: ${theme.font.family};
23
+ font-weight: ${theme.font.weight.bold};
24
+ border-radius: ${theme.size.xs};
25
+ `;
26
+
27
+ const highlightedParts = useMemo(() => {
28
+ if (!highlight_indices || highlight_indices.length === 0) {
29
+ return text;
30
+ }
31
+
32
+ const sorted = [...highlight_indices].sort((a, b) => a[0] - b[0]);
33
+ const parts: React.ReactNode[] = [];
34
+ let lastIndex = 0;
35
+
36
+ sorted.forEach(([start, end], idx) => {
37
+ // Plain text
38
+ if (start > lastIndex) {
39
+ parts.push(
40
+ <span key={`plain-${idx}`}>
41
+ {text.slice(lastIndex, start)}
42
+ </span>,
43
+ );
44
+ }
45
+ // Highlighted text
46
+ parts.push(
47
+ <span key={`hl-${idx}`} css={highlightStyles}>
48
+ {text.slice(start, end)}
49
+ </span>,
50
+ );
51
+ lastIndex = end;
52
+ });
53
+
54
+ // Remaining plain text
55
+ if (lastIndex < text.length) {
56
+ parts.push(<span key="plain-last">{text.slice(lastIndex)}</span>);
57
+ }
58
+
59
+ return parts;
60
+ }, [text, highlight_indices, highlightStyles]);
61
+
62
+ return <>{highlightedParts}</>;
63
+ };
@@ -0,0 +1,80 @@
1
+ import React, { FC, Fragment } from 'react';
2
+
3
+ import { EuiFlexGroup, EuiFlexItem, EuiIcon } from '@elastic/eui';
4
+
5
+ import { WfoBadge } from '@/components/WfoBadges';
6
+ import { useOrchestratorTheme } from '@/hooks';
7
+
8
+ interface WfoPathBreadcrumbProps {
9
+ path: string;
10
+ size?: 's' | 'm';
11
+ maxSegments?: number;
12
+ showArrows?: boolean;
13
+ color?: string;
14
+ stripFirstSegment?: boolean;
15
+ }
16
+
17
+ export const WfoPathBreadcrumb: FC<WfoPathBreadcrumbProps> = ({
18
+ path,
19
+ size = 'm',
20
+ maxSegments,
21
+ showArrows = true,
22
+ color,
23
+ stripFirstSegment = false,
24
+ }) => {
25
+ const { theme } = useOrchestratorTheme();
26
+
27
+ if (!path) {
28
+ return null;
29
+ }
30
+
31
+ let segments = path.split('.').filter((segment) => !/^\d+$/.test(segment));
32
+
33
+ // Strip the first segment (the entity type)
34
+ if (stripFirstSegment && segments.length > 1) {
35
+ segments = segments.slice(1);
36
+ }
37
+
38
+ const displaySegments =
39
+ maxSegments && segments.length > maxSegments
40
+ ? [
41
+ ...segments.slice(0, maxSegments - 1),
42
+ '...',
43
+ segments[segments.length - 1],
44
+ ]
45
+ : segments;
46
+
47
+ const badgeColor = color || theme.colors.primary;
48
+
49
+ return (
50
+ <EuiFlexGroup
51
+ gutterSize={size}
52
+ alignItems="center"
53
+ wrap={false}
54
+ responsive={false}
55
+ >
56
+ {displaySegments.map((segment, index) => (
57
+ <Fragment key={index}>
58
+ <EuiFlexItem grow={false}>
59
+ <WfoBadge
60
+ color={badgeColor}
61
+ textColor={theme.colors.ghost}
62
+ size={size}
63
+ >
64
+ {segment}
65
+ </WfoBadge>
66
+ </EuiFlexItem>
67
+ {showArrows && index < displaySegments.length - 1 && (
68
+ <EuiFlexItem grow={false}>
69
+ <EuiIcon
70
+ type="arrowRight"
71
+ size={size}
72
+ color={theme.colors.link}
73
+ />
74
+ </EuiFlexItem>
75
+ )}
76
+ </Fragment>
77
+ ))}
78
+ </EuiFlexGroup>
79
+ );
80
+ };
@@ -0,0 +1,24 @@
1
+ import React, { FC } from 'react';
2
+
3
+ import { useTranslations } from 'next-intl';
4
+
5
+ import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiText } from '@elastic/eui';
6
+
7
+ import { useOrchestratorTheme } from '@/hooks';
8
+
9
+ export const WfoSearchEmptyState: FC = () => {
10
+ const t = useTranslations('search.page');
11
+ const { theme } = useOrchestratorTheme();
12
+
13
+ return (
14
+ <EuiPanel paddingSize="l" color="transparent" hasShadow={false}>
15
+ <EuiFlexGroup justifyContent="center" alignItems="center">
16
+ <EuiFlexItem grow={false}>
17
+ <EuiText size="m" color={theme.colors.textSubdued}>
18
+ {t('noResultsFound')}
19
+ </EuiText>
20
+ </EuiFlexItem>
21
+ </EuiFlexGroup>
22
+ </EuiPanel>
23
+ );
24
+ };
@@ -0,0 +1,24 @@
1
+ import React, { FC } from 'react';
2
+
3
+ import { useTranslations } from 'next-intl';
4
+
5
+ import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiText } from '@elastic/eui';
6
+
7
+ import { useOrchestratorTheme } from '@/hooks';
8
+
9
+ export const WfoSearchLoadingState: FC = () => {
10
+ const t = useTranslations('search.page');
11
+ const { theme } = useOrchestratorTheme();
12
+
13
+ return (
14
+ <EuiPanel paddingSize="l" color="transparent" hasShadow={false}>
15
+ <EuiFlexGroup justifyContent="center" alignItems="center">
16
+ <EuiFlexItem grow={false}>
17
+ <EuiText size="m" color={theme.colors.textSubdued}>
18
+ {t('loadingSearchResults')}
19
+ </EuiText>
20
+ </EuiFlexItem>
21
+ </EuiFlexGroup>
22
+ </EuiPanel>
23
+ );
24
+ };
@@ -0,0 +1,24 @@
1
+ import React, { FC } from 'react';
2
+
3
+ import { WfoBadge, WfoToolTip } from '@/components';
4
+
5
+ interface WfoSearchMetadataHeaderProps {
6
+ search_metadata: {
7
+ search_type: string | null;
8
+ description: string | null;
9
+ };
10
+ }
11
+
12
+ export const WfoSearchMetadataHeader: FC<WfoSearchMetadataHeaderProps> = ({
13
+ search_metadata,
14
+ }) => {
15
+ if (!search_metadata.search_type) return null;
16
+
17
+ return (
18
+ <WfoToolTip tooltipContent={search_metadata.description || ''}>
19
+ <WfoBadge color="hollow" iconType="search" textColor="default">
20
+ {search_metadata.search_type}
21
+ </WfoBadge>
22
+ </WfoToolTip>
23
+ );
24
+ };
@@ -0,0 +1,107 @@
1
+ import React, { FC } from 'react';
2
+
3
+ import { useTranslations } from 'next-intl';
4
+
5
+ import {
6
+ EuiButtonIcon,
7
+ EuiFlexGroup,
8
+ EuiFlexItem,
9
+ EuiText,
10
+ } from '@elastic/eui';
11
+
12
+ import { WfoBadge } from '@/components/WfoBadges';
13
+ import { useOrchestratorTheme } from '@/hooks';
14
+
15
+ interface WfoSearchPaginationInfoProps {
16
+ has_next_page: boolean;
17
+ next_page_cursor: number | null;
18
+ onNextPage?: (nextPageCursor: number) => void;
19
+ onPrevPage?: () => void;
20
+ isLoading?: boolean;
21
+ currentPage?: number;
22
+ hasPrevPage?: boolean;
23
+ resultCount?: number;
24
+ }
25
+
26
+ export const WfoSearchPaginationInfo: FC<WfoSearchPaginationInfoProps> = ({
27
+ has_next_page,
28
+ next_page_cursor,
29
+ onNextPage,
30
+ onPrevPage,
31
+ isLoading = false,
32
+ currentPage = 1,
33
+ hasPrevPage = false,
34
+ resultCount,
35
+ }) => {
36
+ const t = useTranslations('search.page');
37
+ const { theme } = useOrchestratorTheme();
38
+
39
+ const handleNextPage = () => {
40
+ if (!isLoading && next_page_cursor && onNextPage)
41
+ onNextPage(next_page_cursor);
42
+ };
43
+
44
+ const handlePrevPage = () => {
45
+ if (!isLoading && onPrevPage) onPrevPage();
46
+ };
47
+
48
+ if (!has_next_page && !hasPrevPage) return null;
49
+
50
+ return (
51
+ <EuiFlexGroup
52
+ justifyContent="flexEnd"
53
+ alignItems="center"
54
+ gutterSize="xs"
55
+ responsive={false}
56
+ style={{
57
+ whiteSpace: 'nowrap',
58
+ padding: 0,
59
+ background: 'transparent',
60
+ border: 'none',
61
+ }}
62
+ role="navigation"
63
+ aria-label={t('searchResultsPagination')}
64
+ >
65
+ <EuiFlexItem grow={false}>
66
+ <EuiButtonIcon
67
+ iconType="arrowLeft"
68
+ aria-label={t('previousPage')}
69
+ onClick={handlePrevPage}
70
+ disabled={!hasPrevPage || isLoading}
71
+ color="text"
72
+ size="s"
73
+ />
74
+ </EuiFlexItem>
75
+
76
+ <EuiFlexItem grow={false}>
77
+ <EuiText size="xs" color={theme.colors.textSubdued}>
78
+ {t('page')} {currentPage}
79
+ </EuiText>
80
+ </EuiFlexItem>
81
+
82
+ <EuiFlexItem grow={false}>
83
+ <EuiButtonIcon
84
+ iconType="arrowRight"
85
+ aria-label={t('nextPage')}
86
+ onClick={handleNextPage}
87
+ disabled={!has_next_page || isLoading}
88
+ color="text"
89
+ size="s"
90
+ isLoading={isLoading}
91
+ />
92
+ </EuiFlexItem>
93
+
94
+ {resultCount && resultCount > 0 && (
95
+ <EuiFlexItem grow={false}>
96
+ <WfoBadge
97
+ className="wfoPagination__badge"
98
+ color="hollow"
99
+ textColor="default"
100
+ >
101
+ {t('resultsOnPage', { resultCount })}
102
+ </WfoBadge>
103
+ </EuiFlexItem>
104
+ )}
105
+ </EuiFlexGroup>
106
+ );
107
+ };
@@ -0,0 +1,157 @@
1
+ import React, { FC, MouseEvent, useEffect, useRef } from 'react';
2
+
3
+ import { useTranslations } from 'next-intl';
4
+
5
+ import {
6
+ EuiButtonIcon,
7
+ EuiFlexGroup,
8
+ EuiFlexItem,
9
+ EuiPanel,
10
+ EuiSpacer,
11
+ EuiText,
12
+ } from '@elastic/eui';
13
+
14
+ import { WfoBadge } from '@/components/WfoBadges';
15
+ import { useOrchestratorTheme } from '@/hooks';
16
+ import { AnySearchResult } from '@/types';
17
+
18
+ import { getDescription, getDetailUrl } from '../utils';
19
+ import { WfoHighlightedText } from './WfoHighlightedText';
20
+ import { WfoPathBreadcrumb } from './WfoPathBreadcrumb';
21
+
22
+ interface WfoSearchResultItemProps {
23
+ result: AnySearchResult;
24
+ index: number;
25
+ isSelected?: boolean;
26
+ onSelect?: () => void;
27
+ onPositionChange?: (index: number, element: HTMLElement | null) => void;
28
+ }
29
+
30
+ export const WfoSearchResultItem: FC<WfoSearchResultItemProps> = ({
31
+ result,
32
+ isSelected = false,
33
+ onSelect,
34
+ onPositionChange,
35
+ index,
36
+ }) => {
37
+ const t = useTranslations('search.page');
38
+ const matchingField = result.matching_field;
39
+ const { theme } = useOrchestratorTheme();
40
+ const baseUrl = `${window.location.protocol}//${window.location.host}`;
41
+ const detailUrl = getDetailUrl(result, baseUrl);
42
+ const itemRef = useRef<HTMLDivElement>(null);
43
+
44
+ useEffect(() => {
45
+ if (isSelected && onPositionChange && itemRef.current) {
46
+ onPositionChange(index, itemRef.current);
47
+ }
48
+ }, [isSelected, index, onPositionChange]);
49
+
50
+ return (
51
+ <EuiFlexItem>
52
+ <EuiPanel
53
+ panelRef={itemRef}
54
+ color={isSelected ? 'primary' : 'transparent'}
55
+ paddingSize="m"
56
+ data-record-index={index}
57
+ onClick={() => {
58
+ onSelect?.();
59
+ }}
60
+ style={
61
+ isSelected
62
+ ? {
63
+ borderTop: theme.border.thick,
64
+ borderBottom: theme.border.thick,
65
+ borderLeft: 'none',
66
+ borderRight: 'none',
67
+ borderColor: theme.colors.primary,
68
+ }
69
+ : undefined
70
+ }
71
+ >
72
+ <EuiFlexGroup alignItems="flexStart" gutterSize="m">
73
+ <EuiFlexItem>
74
+ <EuiFlexGroup direction="column" gutterSize="xs">
75
+ <EuiFlexItem>
76
+ <EuiText
77
+ size="m"
78
+ style={{
79
+ fontWeight: theme.font.weight.semiBold,
80
+ }}
81
+ >
82
+ {getDescription(result)}
83
+ </EuiText>
84
+ </EuiFlexItem>
85
+ {matchingField && (
86
+ <>
87
+ {matchingField.path && (
88
+ <EuiFlexItem>
89
+ <WfoPathBreadcrumb
90
+ path={matchingField.path}
91
+ size="s"
92
+ maxSegments={4}
93
+ color={theme.colors.primary}
94
+ />
95
+ </EuiFlexItem>
96
+ )}
97
+ <EuiFlexItem>
98
+ <EuiText
99
+ style={{
100
+ backgroundColor: 'transparent',
101
+ borderRadius:
102
+ theme.border.radius.medium,
103
+ fontSize: theme.size.base,
104
+ }}
105
+ >
106
+ <WfoHighlightedText
107
+ text={matchingField.text}
108
+ highlight_indices={
109
+ matchingField.highlight_indices
110
+ }
111
+ />
112
+ </EuiText>
113
+ </EuiFlexItem>
114
+
115
+ <EuiSpacer size="xs" />
116
+ </>
117
+ )}
118
+ </EuiFlexGroup>
119
+ </EuiFlexItem>
120
+
121
+ <EuiFlexItem grow={false}>
122
+ <EuiFlexGroup
123
+ direction="column"
124
+ alignItems="flexEnd"
125
+ gutterSize="xs"
126
+ >
127
+ <EuiFlexItem>
128
+ <WfoBadge
129
+ color={theme.colors.primary}
130
+ textColor={theme.colors.ghost}
131
+ >
132
+ {'score' in result && result.score
133
+ ? result.score.toFixed(4)
134
+ : 'N/A'}
135
+ </WfoBadge>
136
+ </EuiFlexItem>
137
+ <EuiFlexItem>
138
+ <EuiButtonIcon
139
+ iconType="popout"
140
+ aria-label={t('viewDetails')}
141
+ onClick={(
142
+ e: MouseEvent<HTMLButtonElement>,
143
+ ) => {
144
+ e.stopPropagation();
145
+ window.open(detailUrl, '_blank');
146
+ }}
147
+ color="text"
148
+ size="m"
149
+ />
150
+ </EuiFlexItem>
151
+ </EuiFlexGroup>
152
+ </EuiFlexItem>
153
+ </EuiFlexGroup>
154
+ </EuiPanel>
155
+ </EuiFlexItem>
156
+ );
157
+ };
@@ -0,0 +1,65 @@
1
+ import React, { useState } from 'react';
2
+
3
+ import { EuiFlexGroup, EuiPanel } from '@elastic/eui';
4
+
5
+ import { AnySearchResult } from '@/types';
6
+
7
+ import { WfoSearchEmptyState } from './WfoSearchEmptyState';
8
+ import { WfoSearchLoadingState } from './WfoSearchLoadingState';
9
+ import { WfoSearchResultItem } from './WfoSearchResultItem';
10
+ import { WfoSubscriptionDetailModal } from './WfoSubscriptionDetailModal';
11
+
12
+ interface WfoSearchResultsProps {
13
+ results: AnySearchResult[];
14
+ loading: boolean;
15
+ selectedRecordIndex?: number;
16
+ onRecordSelect?: (index: number) => void;
17
+ }
18
+
19
+ export const WfoSearchResults = ({
20
+ results,
21
+ loading,
22
+ selectedRecordIndex = 0,
23
+ onRecordSelect,
24
+ }: WfoSearchResultsProps) => {
25
+ const [modalData, setModalData] = useState<{
26
+ subscription: unknown;
27
+ matchingField?: unknown;
28
+ } | null>(null);
29
+
30
+ const handleCloseModal = () => {
31
+ setModalData(null);
32
+ };
33
+
34
+ if (loading) {
35
+ return <WfoSearchLoadingState />;
36
+ }
37
+
38
+ if (!results || results.length === 0) {
39
+ return <WfoSearchEmptyState />;
40
+ }
41
+
42
+ return (
43
+ <>
44
+ <EuiPanel paddingSize="m" hasShadow={false}>
45
+ <EuiFlexGroup direction="column" gutterSize="s">
46
+ {results.map((result, idx) => (
47
+ <WfoSearchResultItem
48
+ key={idx}
49
+ result={result}
50
+ index={idx}
51
+ isSelected={idx === selectedRecordIndex}
52
+ onSelect={() => onRecordSelect?.(idx)}
53
+ />
54
+ ))}
55
+ </EuiFlexGroup>
56
+ </EuiPanel>
57
+ <WfoSubscriptionDetailModal
58
+ isVisible={!!modalData}
59
+ onClose={handleCloseModal}
60
+ subscriptionData={modalData?.subscription}
61
+ matchingField={modalData?.matchingField}
62
+ />
63
+ </>
64
+ );
65
+ };
@@ -0,0 +1,55 @@
1
+ import React, { FC } from 'react';
2
+
3
+ import { useTranslations } from 'next-intl';
4
+
5
+ import {
6
+ EuiButton,
7
+ EuiModal,
8
+ EuiModalBody,
9
+ EuiModalFooter,
10
+ EuiModalHeader,
11
+ EuiModalHeaderTitle,
12
+ } from '@elastic/eui';
13
+
14
+ import { WfoSubscription } from '@/components';
15
+ import { TreeProvider } from '@/contexts';
16
+
17
+ interface WfoSubscriptionDetailModalProps {
18
+ isVisible: boolean;
19
+ onClose: () => void;
20
+ subscriptionData: unknown | null;
21
+ matchingField?: unknown;
22
+ }
23
+
24
+ export const WfoSubscriptionDetailModal: FC<
25
+ WfoSubscriptionDetailModalProps
26
+ > = ({ isVisible, onClose, subscriptionData }) => {
27
+ const t = useTranslations('search.page');
28
+ if (!isVisible || !subscriptionData) return null;
29
+
30
+ const subscriptionId =
31
+ subscriptionData &&
32
+ (subscriptionData as { subscription_id: string }).subscription_id;
33
+
34
+ return (
35
+ <EuiModal onClose={onClose} maxWidth={800}>
36
+ <EuiModalHeader>
37
+ <EuiModalHeaderTitle>
38
+ {t('subscriptionDetails')}
39
+ </EuiModalHeaderTitle>
40
+ </EuiModalHeader>
41
+
42
+ <EuiModalBody>
43
+ <TreeProvider>
44
+ <WfoSubscription subscriptionId={subscriptionId} />
45
+ </TreeProvider>
46
+ </EuiModalBody>
47
+
48
+ <EuiModalFooter>
49
+ <EuiButton onClick={onClose} fill>
50
+ {t('closeButton')}
51
+ </EuiButton>
52
+ </EuiModalFooter>
53
+ </EuiModal>
54
+ );
55
+ };
@@ -0,0 +1,10 @@
1
+ export * from './WfoSearchResults';
2
+
3
+ export * from './WfoSearchResultItem';
4
+ export * from './WfoSearchEmptyState';
5
+ export * from './WfoSearchLoadingState';
6
+ export * from './WfoSearchMetadataHeader';
7
+ export * from './WfoSearchPaginationInfo';
8
+ export * from './WfoHighlightedText';
9
+ export * from './WfoPathBreadcrumb';
10
+ export * from './WfoSubscriptionDetailModal';