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,
}
}