import TrimText from '../TrimText/TrimText' import { c } from '../../translations/LibraryTranslationService' export const getTextWidth = (text: string) => { const canvas = document.createElement('canvas') const context = canvas.getContext('2d') if (context) { context.font = '12px "Wix Madefor Display", sans-serif' return context.measureText(text).width + 16 // For padding on tag (8px left + 8px right) } return 0 } export const getPlaceholder = (placeholder?: string) => ( ) // Shared layout defaults/utilities used by ExposedFilter variants export const DEFAULT_CONTAINER_WIDTH_MOBILE = 240 export const DEFAULT_CONTAINER_WIDTH_DESKTOP = 300 export const DEFAULT_HORIZONTAL_PADDING = 16 + 16 export const DEFAULT_CLEAR_BUTTON_WIDTH = 38 export const DEFAULT_RIGHT_PADDING = 8 export const DEFAULT_MORE_INDICATOR_RESERVED_WIDTH = 40 // This function is used to get the maximum width of the filter container. export function getMaxFilterContainerWidth(isMobile: boolean): number { return ( (isMobile ? DEFAULT_CONTAINER_WIDTH_MOBILE : DEFAULT_CONTAINER_WIDTH_DESKTOP) - DEFAULT_HORIZONTAL_PADDING ) } // Return type for the calculateSelectedTagsLayout function export interface SelectedTagsLayoutResult { selectedTags: ItemType[] hasMore: boolean truncateTagIndex: number truncatedTagWidth: number } // Refactored to a common function as it will also be used for modal-based and MultiSelect based filter options in ExposedFilterGroup. // This function is used to calculate the layout of selected tags. export interface CalculateSelectedTagsLayoutOptions { containerMaxWidth: number clearButtonWidth?: number rightPadding?: number moreIndicatorReservedWidth?: number getItemLabel: (item: ItemType) => string } export function calculateSelectedTagsLayout( selectedOptions: ItemType[], labelText: string, { containerMaxWidth, clearButtonWidth = DEFAULT_CLEAR_BUTTON_WIDTH, rightPadding = DEFAULT_RIGHT_PADDING, moreIndicatorReservedWidth = DEFAULT_MORE_INDICATOR_RESERVED_WIDTH, getItemLabel, }: CalculateSelectedTagsLayoutOptions, ): SelectedTagsLayoutResult { const labelWidth = getTextWidth(labelText) const currentAvailableWidth = containerMaxWidth - labelWidth - clearButtonWidth - rightPadding let totalWidth = 0 const updatedTags: ItemType[] = [] let truncateLastTagIndex = -1 let remainingWidthForTruncatedTag = 0 for (let i = 0; i < selectedOptions.length; i++) { const option = selectedOptions[i] const tagWidth = getTextWidth(getItemLabel(option)) const remainingTags = selectedOptions.length - i - 1 const reservedWidth = remainingTags > 0 ? moreIndicatorReservedWidth : 0 const gap = updatedTags.length > 1 ? 4 : 0 if (totalWidth + tagWidth + gap <= currentAvailableWidth - reservedWidth) { totalWidth += tagWidth + gap updatedTags.push(option) } else { const remainingSpace = currentAvailableWidth - totalWidth - gap - moreIndicatorReservedWidth if (remainingSpace >= 20) { updatedTags.push(option) truncateLastTagIndex = updatedTags.length - 1 remainingWidthForTruncatedTag = remainingSpace } break } } return { selectedTags: updatedTags, hasMore: updatedTags.length < selectedOptions.length, truncateTagIndex: truncateLastTagIndex, truncatedTagWidth: remainingWidthForTruncatedTag, } }