{"version":3,"file":"BadgeCell.mjs","sources":["../../../../src/lib/nextGenComponents/components/BadgeCell/BadgeCell.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nimport Badge, { getBadgeColor } from '@/components/Badge'\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'\nimport { cn } from '@/lib/utils'\n\nexport type BadgeItem = {\n  key: string\n  value?: string\n}\n\nexport type BadgeCellProps = {\n  badges: BadgeItem[]\n  delimiter?: string\n  maxVisible?: number\n  className?: string\n}\n\nconst badgeColor = getBadgeColor()\nconst OVERFLOW_BADGE_WIDTH = 36\nconst BADGE_GAP = 4\n\nconst formatLabel = (badge: BadgeItem, delimiter: string) => {\n  if (!badge.value) return badge.key\n  return `${badge.key}${delimiter}${badge.value}`\n}\n\nconst BadgeCell = ({ badges, delimiter = ':', maxVisible, className }: BadgeCellProps) => {\n  const containerRef = useRef<HTMLDivElement>(null)\n  const measureRef = useRef<HTMLDivElement>(null)\n  const [visibleCount, setVisibleCount] = useState(badges.length)\n\n  const calculateVisibleCount = useCallback(() => {\n    const container = containerRef.current\n    const measure = measureRef.current\n    if (!container || !measure) return\n\n    const containerWidth = container.offsetWidth\n\n    if (maxVisible !== undefined) {\n      setVisibleCount(Math.min(maxVisible, badges.length))\n      return\n    }\n\n    const badgeElements = measure.children\n    let totalWidth = 0\n    let count = 0\n\n    for (let i = 0; i < badgeElements.length; i++) {\n      const badgeWidth = (badgeElements[i] as HTMLElement).offsetWidth + BADGE_GAP\n      const needsOverflow = i < badges.length - 1\n      const availableWidth = needsOverflow\n        ? containerWidth - OVERFLOW_BADGE_WIDTH - BADGE_GAP\n        : containerWidth\n\n      if (totalWidth + badgeWidth <= availableWidth) {\n        totalWidth += badgeWidth\n        count++\n      } else {\n        break\n      }\n    }\n\n    setVisibleCount(Math.max(count, 0))\n  }, [badges.length, maxVisible])\n\n  const throttledCalculate = useMemo(() => {\n    let lastCall = 0\n    let timeoutId: ReturnType<typeof setTimeout> | null = null\n\n    const throttled = () => {\n      const now = Date.now()\n      const remaining = 150 - (now - lastCall)\n\n      if (remaining <= 0) {\n        lastCall = now\n        calculateVisibleCount()\n      } else if (!timeoutId) {\n        timeoutId = setTimeout(() => {\n          lastCall = Date.now()\n          timeoutId = null\n          calculateVisibleCount()\n        }, remaining)\n      }\n    }\n\n    throttled.cancel = () => {\n      if (timeoutId) {\n        clearTimeout(timeoutId)\n        timeoutId = null\n      }\n    }\n\n    return throttled\n  }, [calculateVisibleCount])\n\n  useEffect(() => {\n    calculateVisibleCount()\n\n    const observer = new ResizeObserver(throttledCalculate)\n    if (containerRef.current) {\n      observer.observe(containerRef.current)\n    }\n\n    return () => {\n      observer.disconnect()\n      throttledCalculate.cancel()\n    }\n  }, [calculateVisibleCount, throttledCalculate])\n\n  if (badges.length === 0) {\n    return null\n  }\n\n  const visibleBadges = badges.slice(0, visibleCount)\n  const hiddenBadges = badges.slice(visibleCount)\n  const hiddenCount = hiddenBadges.length\n\n  return (\n    <div\n      ref={containerRef}\n      data-testid=\"badge-cell\"\n      className={cn('relative flex items-center gap-1 min-w-0 overflow-hidden', className)}\n    >\n      <div\n        ref={measureRef}\n        aria-hidden\n        className=\"absolute top-0 left-0 flex items-center gap-1 invisible pointer-events-none whitespace-nowrap\"\n      >\n        {badges.map((badge, index) => (\n          <Badge key={`measure-${badge.key}-${index}`} label={formatLabel(badge, delimiter)} />\n        ))}\n      </div>\n\n      {visibleBadges.map((badge, index) => (\n        <Badge key={`${badge.key}-${index}`} label={formatLabel(badge, delimiter)} />\n      ))}\n\n      {hiddenCount > 0 && (\n        <Popover>\n          <PopoverTrigger asChild>\n            <button\n              type=\"button\"\n              data-testid=\"badge-cell-overflow\"\n              className={cn(\n                'inline-flex items-center justify-center rounded px-2 py-0.5 text-xs font-medium cursor-pointer whitespace-nowrap border-0',\n                badgeColor.bg,\n                badgeColor.text\n              )}\n            >\n              +{hiddenCount}\n            </button>\n          </PopoverTrigger>\n          <PopoverContent\n            side=\"top\"\n            align=\"start\"\n            className=\"w-auto max-h-[200px] overflow-y-auto p-2 bg-white text-igz-primary border border-igz-gray-light\"\n          >\n            <div className=\"flex flex-col gap-1.5\">\n              {hiddenBadges.map((badge, index) => (\n                <span\n                  key={`hidden-${badge.key}-${index}`}\n                  className={cn(\n                    'inline-flex rounded px-2 py-0.5 text-xs font-medium whitespace-nowrap',\n                    badgeColor.bg,\n                    badgeColor.text\n                  )}\n                >\n                  {formatLabel(badge, delimiter)}\n                </span>\n              ))}\n            </div>\n          </PopoverContent>\n        </Popover>\n      )}\n    </div>\n  )\n}\n\nexport default BadgeCell\n"],"names":["badgeColor","getBadgeColor","OVERFLOW_BADGE_WIDTH","BADGE_GAP","formatLabel","badge","delimiter","BadgeCell","badges","maxVisible","className","containerRef","useRef","measureRef","visibleCount","setVisibleCount","useState","calculateVisibleCount","useCallback","container","measure","containerWidth","badgeElements","totalWidth","count","i","badgeWidth","availableWidth","throttledCalculate","useMemo","lastCall","timeoutId","throttled","now","remaining","useEffect","observer","visibleBadges","hiddenBadges","hiddenCount","jsxs","cn","jsx","index","Badge","Popover","PopoverTrigger","PopoverContent"],"mappings":"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"}