import React, { KeyboardEvent, ReactNode } from 'react'; import intl from 'react-intl-universal'; import { isUndefined } from 'lodash'; import { Overlay, InputGroup, Tag, MenuItem, Spinner, Intent, OverlayProps, Button, } from '@blueprintjs/core'; import { QueryList, ItemRenderer } from '@blueprintjs/select'; import { x } from '@xstyled/emotion'; import { css } from '@emotion/css'; import { Icon, If, FormattedMessage as T } from '@/components'; import { Select } from '@blueprintjs-formik/select'; import { UniversalSearchProvider, useUniversalSearchContext, } from './UniversalSearchProvider'; import { filterItemsByResourceType } from './utils'; import { RESOURCES_TYPES } from '@/constants/resourcesTypes'; // Resource type from RESOURCES_TYPES constant type ResourceType = string; // Search type option item interface SearchTypeOption { key: ResourceType; label: string; } // Universal search item interface UniversalSearchItem { id: number | string; _type: ResourceType; text: string; subText?: string; label?: string; [key: string]: any; } // CSS styles for complex selectors const overlayStyles = css` .bp4-overlay-appear, .bp4-overlay-enter { filter: blur(20px); opacity: 0.2; } .bp4-overlay-appear-active, .bp4-overlay-enter-active { filter: blur(0); opacity: 1; transition: filter 0.2s cubic-bezier(0.4, 1, 0.75, 0.9), opacity 0.2s cubic-bezier(0.4, 1, 0.75, 0.9); } .bp4-overlay-exit { filter: blur(0); opacity: 1; } .bp4-overlay-exit-active { filter: blur(20px); opacity: 0.2; transition: filter 0.2s cubic-bezier(0.4, 1, 0.75, 0.9), opacity 0.2s cubic-bezier(0.4, 1, 0.75, 0.9); } `; const containerStyles = css` position: fixed; filter: blur(0); opacity: 1; background-color: var(--color-universal-search-background); border-radius: 3px; box-shadow: 0 0 0 1px rgba(16, 22, 26, 0.1), 0 4px 8px rgba(16, 22, 26, 0.2), 0 18px 46px 6px rgba(16, 22, 26, 0.2); left: calc(50% - 250px); top: 20vh; width: 500px; z-index: 20; .bp4-input-group { .bp4-icon { margin: 16px; color: var(--color-universal-search-icon); svg { stroke: currentColor; fill: none; fill-rule: evenodd; stroke-linecap: round; stroke-linejoin: round; stroke-width: 2; --text-opacity: 1; } } } .bp4-input-group .bp4-input { border: 0; box-shadow: 0 0 0 0; height: 50px; line-height: 50px; font-size: 20px; } .bp4-input-group.bp4-large .bp4-input:not(:first-child) { padding-left: 50px !important; } .bp4-input-group.bp4-large .bp4-input:not(:last-child) { padding-right: 130px !important; } .bp4-menu { border-top: 1px solid var(--color-universal-search-menu-border); max-height: calc(60vh - 20px); overflow: auto; .bp4-menu-item { .bp4-text-muted { font-size: 12px; .bp4-icon { color: var(--bp4-gray-600); } } &.bp4-intent-primary { &.bp4-active { background-color: var(--bp4-blue-100); color: var(--bp4-dark-gray-800); .bp4-menu-item-label { color: var(--bp4-gray-600); } } } &-label { flex-direction: row; text-align: right; } } } .bp4-input-action { height: 100%; display: flex; flex-direction: row; align-items: center; } `; const inputRightElementsStyles = css` display: flex; margin: 10px; .bp4-spinner { margin-right: 6px; } `; const footerStyles = css` padding: 12px 12px; border-top: 1px solid var(--color-universal-search-footer-divider); `; const actionBaseStyles = css` &:not(:first-of-type) { margin-left: 14px; } .bp4-tag { background: var(--color-universal-search-tag-background); color: var(--color-universal-search-tag-text); } `; const actionArrowsStyles = css` &:not(:first-of-type) { margin-left: 14px; } .bp4-tag { background: var(--color-universal-search-tag-background); color: var(--color-universal-search-tag-text); padding: 0; text-align: center; line-height: 16px; margin-left: 4px; svg { fill: var(--color-universal-search-tag-text); height: 100%; display: block; width: 100%; padding: 2px; } } `; // UniversalSearchInputRightElements props interface UniversalSearchInputRightElementsProps { /** Callback when search type changes */ onSearchTypeChange?: (option: SearchTypeOption) => void; } /** * Universal search input action. */ function UniversalSearchInputRightElements({ onSearchTypeChange, }: UniversalSearchInputRightElementsProps) { const { isLoading, searchType, searchTypeOptions } = useUniversalSearchContext(); // Find the currently selected item object. const selectedItem = searchTypeOptions.find( (item) => item.key === searchType, ); // Handle search type option change. const handleSearchTypeChange = (option: SearchTypeOption) => { onSearchTypeChange?.(option); }; // Item renderer for the select dropdown. const itemRenderer: ItemRenderer = ( item, { handleClick }, ) => { return ; }; return ( items={searchTypeOptions} itemRenderer={itemRenderer} onItemSelect={handleSearchTypeChange} selectedValue={selectedItem?.key} valueAccessor={'key'} labelAccessor={'label'} filterable={false} popoverProps={{ minimal: true, captureDismiss: true, }} input={({ activeItem }) => (