{"version":3,"file":"index.cjs","sources":["../../../../src/components/TextTruncate/TextTruncate.tsx"],"sourcesContent":["import {\n  ComponentProps,\n  ComponentPropsWithRef,\n  CSSProperties,\n  ElementType,\n  HTMLAttributes,\n  ReactNode,\n  forwardRef,\n  useEffect,\n  useId,\n  useMemo,\n  useRef,\n  useState,\n} from 'react';\nimport { cn, cva } from '@/lib/cva';\nimport { mergeRefs } from '@/utils/mergeRefs';\nimport { useIsTruncated } from '@/hooks/useIsTruncated';\nimport { Tooltip } from '@/components/Tooltip';\nimport { TextTruncateProps } from './TextTruncate.types';\nimport styles from './TextTruncate.module.css';\n\nconst NO_BREAK_SPACE = '\\u00a0';\n\nconst INTERACTIVE_ELEMENT = [\n  'a[href]',\n  'button',\n  'summary',\n  '[role=\"button\"]',\n  '[role=\"link\"]',\n  '[role=\"tab\"]',\n  '[role=\"option\"]',\n  '[role=\"menuitem\"]',\n  '[role=\"menuitemcheckbox\"]',\n  '[role=\"menuitemradio\"]',\n  '[role=\"checkbox\"]',\n  '[role=\"radio\"]',\n  '[role=\"switch\"]',\n  '[role=\"treeitem\"]',\n  '[cui-select-item]',\n].join(', ');\n\nconst textTruncateVariants = cva(styles['text-truncate'], {\n  variants: {\n    middle: { true: styles['text-truncate_pos-middle'] },\n    split: { true: styles['text-truncate_split'] },\n  },\n});\n\nconst splitMiddle = (text: string, trailingChars: number): [string, string] => {\n  const chars = Array.from(text);\n  const endLength = Number.isFinite(trailingChars) ? Math.floor(trailingChars) : 0;\n  if (endLength <= 0 || endLength > chars.length - endLength) {\n    return [text, ''];\n  }\n  const start = chars.slice(0, -endLength).join('');\n  const end = chars.slice(-endLength).join('');\n  return [start.replace(/\\s+$/, NO_BREAK_SPACE), end.replace(/^\\s+/, NO_BREAK_SPACE)];\n};\n\ntype TextTruncatePolymorphicComponent = <T extends ElementType = 'span'>(\n  props: Omit<ComponentProps<T>, keyof TextTruncateProps<T>> & TextTruncateProps<T>\n) => ReactNode;\n\nconst TextTruncateComponent = <T extends ElementType = 'span'>(\n  {\n    component,\n    ellipsisPosition,\n    trailingChars = 8,\n    maxWidth,\n    showTooltip = true,\n    tooltipContent,\n    tooltipProps,\n    className,\n    style,\n    children,\n    ...props\n  }: Omit<ComponentProps<T>, keyof TextTruncateProps<T>> & TextTruncateProps<T>,\n  ref: ComponentPropsWithRef<T>['ref']\n) => {\n  const Component = component ?? 'span';\n  const middleText =\n    ellipsisPosition === 'middle' && typeof children === 'string' ? children : null;\n  const isMiddle = middleText !== null;\n\n  const { ref: measureRef, isTruncated } = useIsTruncated({ enabled: showTooltip });\n  const [isTooltipOpen, setIsTooltipOpen] = useState(false);\n  const [rootElement, setRootElement] = useState<HTMLElement | null>(null);\n  const hasWarnedRef = useRef(false);\n  const generatedId = useId();\n  const {\n    id,\n    'aria-label': ariaLabel,\n    'aria-labelledby': ariaLabelledBy,\n  } = props as Pick<HTMLAttributes<HTMLElement>, 'id' | 'aria-label' | 'aria-labelledby'>;\n\n  useEffect(() => {\n    if (!isTruncated) {\n      setIsTooltipOpen(false);\n    }\n  }, [isTruncated]);\n\n  const rootRef = useMemo(\n    () =>\n      !showTooltip\n        ? ref\n        : isMiddle\n          ? mergeRefs([ref, setRootElement])\n          : mergeRefs([ref, setRootElement, measureRef]),\n    [showTooltip, isMiddle, ref, measureRef]\n  );\n\n  const isInsideControl = useMemo(\n    () => rootElement?.parentElement?.closest(INTERACTIVE_ELEMENT) != null,\n    [rootElement]\n  );\n\n  useEffect(() => {\n    if (\n      hasWarnedRef.current ||\n      tooltipContent !== undefined ||\n      !rootElement?.querySelector(INTERACTIVE_ELEMENT)\n    ) {\n      return;\n    }\n    hasWarnedRef.current = true;\n    console.warn(\n      '[Click UI] TextTruncate: `children` holds an interactive element such as a link or button, which the tooltip would copy. Pass plain text as `tooltipContent`, or, when the whole text is the link or button, render `TextTruncate` inside it.'\n    );\n  }, [rootElement, tooltipContent, children]);\n\n  const mergedStyle = useMemo(\n    () =>\n      maxWidth === undefined\n        ? style\n        : ({ '--text-truncate-max-width': maxWidth, ...style } as CSSProperties),\n    [maxWidth, style]\n  );\n\n  const [start, end] = isMiddle ? splitMiddle(middleText, trailingChars) : ['', ''];\n  const hasTabStop = showTooltip && isTruncated && !isInsideControl;\n  const hasGroupRole = hasTabStop && (Component === 'span' || Component === 'div');\n  const isSelfLabelled =\n    hasGroupRole && ariaLabel === undefined && ariaLabelledBy === undefined;\n  const rootId = id ?? generatedId;\n\n  const root = (\n    <Component\n      ref={rootRef}\n      tabIndex={hasTabStop ? 0 : undefined}\n      role={hasGroupRole ? 'group' : undefined}\n      id={isSelfLabelled ? rootId : undefined}\n      aria-labelledby={isSelfLabelled ? rootId : undefined}\n      // Radix Slot lets a present `undefined` key win, so this key must stay absent unless the description is dropped.\n      {...(isSelfLabelled &&\n        tooltipContent === undefined && { 'aria-describedby': undefined })}\n      {...props}\n      style={mergedStyle}\n      className={cn(\n        textTruncateVariants({ middle: isMiddle, split: end !== '' }),\n        className\n      )}\n    >\n      {isMiddle ? (\n        <>\n          <span\n            ref={measureRef}\n            className={styles['text-truncate__start']}\n            aria-hidden={end ? true : undefined}\n          >\n            {start}\n          </span>\n          {end && (\n            <>\n              <span\n                className={styles['text-truncate__end']}\n                aria-hidden\n              >\n                {end}\n              </span>\n              <span className={styles['text-truncate__label']}>{middleText}</span>\n            </>\n          )}\n        </>\n      ) : (\n        children\n      )}\n    </Component>\n  );\n\n  if (!showTooltip) {\n    return root;\n  }\n\n  return (\n    <Tooltip\n      open={isTruncated && isTooltipOpen}\n      onOpenChange={open => setIsTooltipOpen(open && isTruncated)}\n    >\n      <Tooltip.Trigger asChild>{root}</Tooltip.Trigger>\n      <Tooltip.Content {...tooltipProps}>{tooltipContent ?? children}</Tooltip.Content>\n    </Tooltip>\n  );\n};\n\nTextTruncateComponent.displayName = 'TextTruncate';\n\nexport const TextTruncate: TextTruncatePolymorphicComponent =\n  forwardRef(TextTruncateComponent);\n"],"names":["cva","styles","useIsTruncated","useState","useRef","useId","useEffect","useMemo","mergeRefs","jsx","cn","jsxs","Fragment","Tooltip","forwardRef"],"mappings":"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"}