{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"truncate","title":"Truncate","description":"Cut text after one line or a number of lines with an ellipsis, and show the full text in a tooltip. Search terms: line clamp, line-clamp, text overflow, clamp, overflow tooltip.","dependencies":["@base-ui/react@1.7.0"],"registryDependencies":["@siteplane/base","@siteplane/tooltip"],"files":[{"path":"packages/ui/src/components/truncate/truncate.tsx","content":"\"use client\";\n\nimport { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport type * as React from \"react\";\n\nimport { useTruncated } from \"../../system/hooks/use-truncated\";\nimport { cn } from \"../../system/utils/cn\";\nimport { slotClass } from \"../../system/utils/slot-class\";\nimport { Tooltip, TooltipPopup, TooltipTrigger } from \"../tooltip\";\n\n/** The props of the TooltipPopup that shows the full text. */\nexport type TruncateTooltipProps = React.ComponentProps<typeof TooltipPopup>;\n\nexport interface TruncateProps extends useRender.ComponentProps<\"span\"> {\n  /**\n   * The lines the text keeps before it ends in an ellipsis. One, the default,\n   * keeps the text on one line and cuts it where its box ends: the width of\n   * its container, or a width a class sets, such as `max-w-1/2`. More lines\n   * wrap the text and cut it at the end of the last of them. A value below two\n   * counts as one.\n   */\n  lines?: number | undefined;\n  /**\n   * Shows the full text in the kit's Tooltip on hover while the text is cut,\n   * and on focus where the element takes focus, such as a link. `false` turns\n   * it off. An object passes props to the TooltipPopup, such as `side`, or\n   * `children` for content other than the text.\n   */\n  tooltip?: boolean | TruncateTooltipProps | undefined;\n}\n\n/**\n * Text that ends in an ellipsis after one line or a number of `lines`, with the\n * full text in a Tooltip on hover while it is cut. It renders a `span`, or the\n * element of `render`. The cut is visual: the element keeps the whole text, so\n * assistive technology reads it once, and the tooltip is hidden from it. The\n * server and the first render in the browser render no tooltip; the text is\n * measured before the first paint and whenever its size changes. The layout is\n * the Truncate rules in design-rework.css.\n */\nexport function Truncate({\n  children,\n  className,\n  lines = 1,\n  render,\n  tooltip = true,\n  ...props\n}: TruncateProps): React.ReactElement {\n  const count = Number.isFinite(lines) && lines >= 2 ? Math.floor(lines) : 1;\n  const tooltipOn = tooltip !== false;\n  const [ref, truncated] = useTruncated<HTMLElement>(tooltipOn);\n  // A clamp of several lines takes its count from the style attribute, as\n  // Textarea's line counts do; a policy that blocks the attribute keeps two.\n  const defaultProps = {\n    children,\n    className: cn(slotClass(\"truncate\", props, render), className),\n    \"data-lines\": count > 1 ? count : undefined,\n    \"data-slot\": \"truncate\",\n    style:\n      count > 1\n        ? ({ \"--truncate-lines\": count } as React.CSSProperties)\n        : undefined,\n  };\n  const element = useRender({\n    defaultTagName: \"span\",\n    props: mergeProps<\"span\">(defaultProps, props),\n    ref: tooltipOn ? ref : undefined,\n    render,\n  });\n  if (!tooltipOn) return element;\n\n  const {\n    children: content = children,\n    className: popupClassName,\n    ...popupProps\n  } = tooltip === true ? {} : tooltip;\n  // The Tooltip stays mounted, so the element stays the same node; it opens\n  // only while the text is cut. The trigger reads `disabled` as it renders, so\n  // the server and the first render already have no tooltip; the root, which\n  // takes it a moment later, closes an open tooltip once the text fits. The\n  // popup repeats text the element already gives assistive technology, so it\n  // is hidden from it, and Base UI links no description to the trigger. It\n  // wraps the full text in the Tooltip's own width.\n  return (\n    <Tooltip disabled={!truncated}>\n      <TooltipTrigger\n        disabled={!truncated}\n        render={element as React.ReactElement<Record<string, unknown>>}\n      />\n      <TooltipPopup aria-hidden className={popupClassName} {...popupProps}>\n        {content}\n      </TooltipPopup>\n    </Tooltip>\n  );\n}\n","type":"registry:ui","target":"~/src/siteplane/components/truncate/truncate.tsx"},{"path":"packages/ui/src/components/truncate/index.ts","content":"export * from \"./truncate\";\n","type":"registry:ui","target":"~/src/siteplane/components/truncate/index.ts"}],"type":"registry:ui","docs":"https://ui.siteplane.io/docs-markdown/components/truncate.md","categories":["Layout & utilities"],"meta":{"avoidWhen":["Avoid for text people must read in full, such as an error, an instruction or a legal notice; let it wrap.","Avoid for menu rows, Badge and Tag labels and Button labels; they end in an ellipsis themselves."],"description":"Cut text after one line or a number of lines with an ellipsis, and show the full text in a tooltip.","knownLimitations":["The tooltip opens on hover, and on focus only where the element takes focus, such as a link through render; assistive technology reads the full text from the element itself.","In a table cell or another box that grows with its content, give the Truncate or the cell a width, such as max-w-48, so the text has an edge to end at.","The line count of a clamp over several lines comes from the style attribute; a Content Security Policy that blocks style attributes keeps two lines."],"providerNotes":["The tooltip is the installed Tooltip. A TooltipProvider sets its delay; without one it opens after Base UI's default delay."],"releaseStatus":"stable","searchTerms":["truncate","ellipsis","line clamp","line-clamp","text overflow","clamp","overflow tooltip"],"useWhen":["Use for a title or name that may be longer than its space, such as a card title, a list row or a table cell, with the full text on hover.","Use for a description that should keep its first two or three lines."]}}