{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "code-block",
  "title": "Code Block",
  "description": "Code in a tray, with a title, actions, line numbers and diffs. The app highlights it.",
  "dependencies": [
    "@base-ui/react",
    "@stylexjs/stylex"
  ],
  "registryDependencies": [
    "https://constella.aayush.cv/r/base.json",
    "https://constella.aayush.cv/r/scroll-fade.json"
  ],
  "files": [
    {
      "path": "src/components/ai/code-block.tsx",
      "content": "import { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport * as stylex from \"@stylexjs/stylex\";\nimport type { ComponentProps, ReactNode } from \"react\";\n\nimport { scrollFade } from \"@/lib/constella/scroll-fade\";\nimport { scrollFadeVars } from \"@/lib/constella/scroll-fade.stylex\";\nimport type { Sx } from \"@/lib/constella/styles\";\nimport { typeStyles } from \"@/lib/constella/styles\";\nimport {\n  codeBlockVars,\n  colors,\n  fonts,\n  fontWeights,\n  lineHeights,\n  radii,\n  sizes,\n  space,\n} from \"@/lib/constella/tokens.stylex\";\n\nconst codeBlockColors = [\"danger\"] as const;\nconst codeBlockSizes = [\"sm\", \"default\"] as const;\nconst codeBlockLineVariants = [\n  \"default\",\n  \"added\",\n  \"removed\",\n  \"highlighted\",\n] as const;\n\ntype CodeBlockColor = (typeof codeBlockColors)[number];\ntype CodeBlockSize = (typeof codeBlockSizes)[number];\ntype CodeBlockLineVariant = (typeof codeBlockLineVariants)[number];\n\ntype Styled<T> = Omit<T, \"className\" | \"style\"> & {\n  sx?: Sx;\n};\n\nconst danger = \":is([data-slot='code-block'][data-color='danger'] *)\";\nconst numbered = \":is([data-numbered] *)\";\nconst numberedSelf = \":is([data-numbered])\";\nconst marks =\n  \"pre:not([data-numbered]):has([data-variant='added'], [data-variant='removed'])\";\nconst marked = `:is(${marks} *)`;\nconst markedSelf = `:is(${marks})`;\nconst wrapped = \":is([data-wrap] *)\";\nconst onBlock = \":is([data-slot='code-block'] > *)\";\nconst besideFloating =\n  \":is([data-slot='code-block']:has(> [data-slot='code-block-actions']) > * > *)\";\nconst underHeader =\n  \":is([data-slot='code-block']:has(> [data-slot='code-block-header']) > *)\";\nconst overFooter =\n  \":is([data-slot='code-block']:has(> [data-slot='code-block-footer']) > *)\";\n\nconst pad = codeBlockVars.padInline;\n// The header icon's column: line numbers and diff marks sit in it, so code starts under the title.\nconst gutter = `calc(${pad} + ${sizes.icon} + ${space.xs})`;\nconst clearActions = `calc(${space.xs} + ${sizes.controlSm} + ${space.xs})`;\nconst floating =\n  \":is([data-slot='code-block']:has(> [data-slot='code-block-actions']) > *)\";\n\nconst styles = stylex.create({\n  block: {\n    [codeBlockVars.padBlock]: space.sm,\n    [codeBlockVars.padInline]: space.md,\n    backgroundColor: colors.fillSubtle,\n    borderStartStartRadius: radii.md,\n    borderStartEndRadius: radii.md,\n    borderEndStartRadius: radii.md,\n    borderEndEndRadius: radii.md,\n    color: colors.textPrimary,\n    display: \"flex\",\n    flexDirection: \"column\",\n    minWidth: 0,\n    overflow: \"hidden\",\n    position: \"relative\",\n    width: \"100%\",\n  },\n  sm: {\n    [codeBlockVars.padBlock]: space.xs,\n    [codeBlockVars.padInline]: space.sm,\n  },\n  danger: { backgroundColor: colors.dangerSubtle, color: colors.dangerText },\n  header: {\n    alignItems: \"center\",\n    color: { default: colors.textSecondary, [danger]: colors.dangerText },\n    display: \"flex\",\n    flexShrink: 0,\n    gap: space.xs,\n    minHeight: sizes.controlSm,\n    minWidth: 0,\n    paddingBlockStart: `calc(${codeBlockVars.padBlock} - ${space.xxs})`,\n    paddingInlineEnd: space.xs,\n    paddingInlineStart: pad,\n  },\n  title: {\n    color: { default: colors.textPrimary, [danger]: colors.dangerText },\n    fontFamily: fonts.sans,\n    fontWeight: fontWeights.medium,\n    minWidth: 0,\n    overflow: \"hidden\",\n    textOverflow: \"ellipsis\",\n    whiteSpace: \"nowrap\",\n  },\n  actions: {\n    alignItems: \"center\",\n    display: \"flex\",\n    flexShrink: 0,\n    gap: space.xxs,\n    marginInlineStart: \"auto\",\n    // Centered on the first line.\n    insetBlockStart: {\n      default: null,\n      [onBlock]: `calc(${codeBlockVars.padBlock} + (${lineHeights.textSm} - ${sizes.controlSm}) / 2)`,\n    },\n    // Physical, since the code under it is always left to right.\n    right: { default: null, [onBlock]: space.xs },\n    position: { default: null, [onBlock]: \"absolute\" },\n  },\n  // The numbers' containing block, outside the scroller.\n  content: {\n    flexGrow: 1,\n    fontFamily: fonts.mono,\n    fontVariantLigatures: \"none\",\n    lineHeight: lineHeights.textSm,\n    minHeight: 0,\n    minWidth: 0,\n    paddingBlockEnd: {\n      default: codeBlockVars.padBlock,\n      [overFooter]: space.xxs,\n    },\n    paddingBlockStart: {\n      default: codeBlockVars.padBlock,\n      [underHeader]: space.xxs,\n    },\n    position: \"relative\",\n  },\n  // The fade ends where the floating action starts, so code never shows beside it.\n  contentBesideActions: {\n    [scrollFadeVars.endInset]: { default: null, [floating]: clearActions },\n  },\n  // Never a containing block (no position, transform, filter, contain, container-type or will-change), or it would scroll and clip the numbers.\n  pre: {\n    fontFamily: \"inherit\",\n    fontSize: \"inherit\",\n    marginBlockEnd: 0,\n    marginBlockStart: 0,\n    // The numbers' column sits beside the scroller, never over it: code under a cover shows through at fractional scroll offsets.\n    marginInlineStart: {\n      default: 0,\n      [numberedSelf]: gutter,\n      [markedSelf]: gutter,\n    },\n    minWidth: 0,\n    overflow: \"auto\",\n    // The scroll fade shows there's more, as in Suggestions.\n    scrollbarWidth: \"none\",\n    paddingInlineEnd: { default: pad, [besideFloating]: clearActions },\n    paddingInlineStart: { default: pad, [numberedSelf]: 0, [markedSelf]: 0 },\n    tabSize: 2,\n    textAlign: \"start\",\n  },\n  start: (line: number) => ({ counterReset: `line ${line}` }),\n  wrap: {\n    overflowWrap: \"anywhere\",\n    whiteSpace: \"pre-wrap\",\n  },\n  code: {\n    display: \"block\",\n    fontFamily: \"inherit\",\n    minWidth: \"100%\",\n    width: { default: \"max-content\", [wrapped]: \"auto\" },\n  },\n  // Not positioned, so its number and mark place against the content, outside the scroller.\n  line: {\n    counterIncrement: { default: null, [numbered]: \"line\" },\n    display: \"block\",\n    marginInlineEnd: `calc(-1 * ${pad})`,\n    marginInlineStart: {\n      default: `calc(-1 * ${pad})`,\n      [numbered]: 0,\n      [marked]: 0,\n    },\n    minHeight: lineHeights.textSm,\n    paddingInlineEnd: pad,\n    paddingInlineStart: { default: pad, [numbered]: 0, [marked]: 0 },\n    // Its block position is the line's own; only its inline position is set.\n    \"::before\": {\n      boxSizing: \"border-box\",\n      color: colors.textMuted,\n      content: { default: null, [numbered]: \"counter(line) / ''\" },\n      insetInlineStart: 0,\n      paddingInlineEnd: space.xs,\n      paddingInlineStart: pad,\n      position: \"absolute\",\n      textAlign: \"end\",\n      userSelect: \"none\",\n      width: gutter,\n    },\n    // The diff mark: beside a number, or alone in the gutter, filled like its line.\n    \"::after\": {\n      boxSizing: \"border-box\",\n      insetInlineStart: { default: space.xxs, [marked]: 0 },\n      paddingInlineEnd: { default: null, [marked]: space.xs },\n      paddingInlineStart: { default: null, [marked]: pad },\n      position: \"absolute\",\n      textAlign: \"end\",\n      userSelect: \"none\",\n      width: { default: null, [marked]: gutter },\n    },\n  },\n  added: {\n    backgroundColor: colors.successSubtle,\n    \"::after\": {\n      backgroundColor: colors.successSubtle,\n      color: colors.successText,\n      content: \"'+'\",\n    },\n    \"::before\": { backgroundColor: colors.successSubtle },\n  },\n  removed: {\n    backgroundColor: colors.dangerSubtle,\n    \"::after\": {\n      backgroundColor: colors.dangerSubtle,\n      color: colors.dangerText,\n      content: \"'−'\",\n    },\n    \"::before\": { backgroundColor: colors.dangerSubtle },\n  },\n  highlighted: {\n    backgroundColor: colors.fill,\n    \"::before\": { backgroundColor: colors.fill },\n  },\n  footer: {\n    alignItems: \"center\",\n    color: { default: colors.textSecondary, [danger]: colors.dangerText },\n    display: \"flex\",\n    flexShrink: 0,\n    fontFamily: fonts.sans,\n    gap: space.xs,\n    minWidth: 0,\n    paddingBlockEnd: codeBlockVars.padBlock,\n    paddingInlineEnd: pad,\n    paddingInlineStart: pad,\n  },\n});\n\nconst colorStyles = {\n  danger: styles.danger,\n} satisfies Record<CodeBlockColor, stylex.StyleXStyles>;\n\nconst lineVariantStyles = {\n  added: styles.added,\n  default: null,\n  highlighted: styles.highlighted,\n  removed: styles.removed,\n} satisfies Record<CodeBlockLineVariant, stylex.StyleXStyles>;\n\n/** A tray of code. The app highlights it; the block lays it out. */\nfunction CodeBlock({\n  size = \"default\",\n  color,\n  sx,\n  ...props\n}: Styled<ComponentProps<\"div\">> & {\n  size?: CodeBlockSize;\n  color?: CodeBlockColor;\n}) {\n  return (\n    <div\n      data-size={size}\n      data-slot=\"code-block\"\n      data-color={color}\n      {...props}\n      {...stylex.props(\n        [typeStyles.textSm, styles.block],\n        size === \"sm\" && [typeStyles.captionLg, styles.sm],\n        color && colorStyles[color],\n        sx\n      )}\n    />\n  );\n}\n\nfunction CodeBlockHeader({ sx, ...props }: Styled<ComponentProps<\"div\">>) {\n  return (\n    <div\n      data-slot=\"code-block-header\"\n      {...props}\n      {...stylex.props(styles.header, sx)}\n    />\n  );\n}\n\n/** The file name or language, cut short on one line. */\nfunction CodeBlockTitle({\n  render,\n  sx,\n  ...props\n}: Styled<useRender.ComponentProps<\"div\">>) {\n  return useRender({\n    defaultTagName: \"div\",\n    props: mergeProps<\"div\">(props, stylex.props(styles.title, sx)),\n    render,\n    state: { slot: \"code-block-title\" },\n  });\n}\n\n/** Buttons for the code: at the header's end, or floating on the first line when the block holds them itself. */\nfunction CodeBlockActions({ sx, ...props }: Styled<ComponentProps<\"div\">>) {\n  return (\n    <div\n      data-slot=\"code-block-actions\"\n      {...props}\n      {...stylex.props(styles.actions, sx)}\n    />\n  );\n}\n\n/** The code, scrolling sideways on its own (never down) and always left to right. A string with `lineNumbers` splits into lines; `sx` styles the wrapper, `ref` and the rest reach the `pre`. */\nfunction CodeBlockContent({\n  children,\n  lineNumbers = false,\n  startLine = 1,\n  sx,\n  wrap = false,\n  ...props\n}: Omit<ComponentProps<\"pre\">, \"className\" | \"style\"> & {\n  lineNumbers?: boolean;\n  startLine?: number;\n  sx?: Sx;\n  wrap?: boolean;\n}) {\n  return (\n    <div\n      data-slot=\"code-block-content\"\n      dir=\"ltr\"\n      {...stylex.props(\n        styles.content,\n        scrollFade.xEndAround,\n        styles.contentBesideActions,\n        sx\n      )}\n    >\n      <pre\n        data-numbered={lineNumbers || undefined}\n        data-wrap={wrap || undefined}\n        {...props}\n        {...stylex.props(\n          styles.pre,\n          scrollFade.source,\n          styles.start(startLine - 1),\n          wrap && styles.wrap\n        )}\n      >\n        <code data-slot=\"code-block-code\" {...stylex.props(styles.code)}>\n          {/* oxlint-disable-next-line anti-slop/no-runtime-typeof -- `children` is documented as plain text or lines */}\n          {lineNumbers && typeof children === \"string\"\n            ? children\n                .replace(/\\n$/u, \"\")\n                .split(\"\\n\")\n                .map((line, index) => (\n                  // oxlint-disable-next-line react/no-array-index-key -- a line's place is its identity\n                  <CodeBlockLine key={index}>{line}</CodeBlockLine>\n                ))\n            : children}\n        </code>\n      </pre>\n    </div>\n  );\n}\n\n/** One line, to mark it added, removed or highlighted. */\nfunction CodeBlockLine({\n  children,\n  sx,\n  variant = \"default\",\n  ...props\n}: Styled<ComponentProps<\"span\">> & {\n  children?: ReactNode;\n  variant?: CodeBlockLineVariant;\n}) {\n  // An empty line holds a newline, so a copied selection keeps it.\n  const empty =\n    children === undefined ||\n    children === null ||\n    children === \"\" ||\n    children === false ||\n    (Array.isArray(children) && children.length === 0);\n  return (\n    <span\n      data-slot=\"code-block-line\"\n      data-variant={variant}\n      {...props}\n      {...stylex.props(styles.line, lineVariantStyles[variant], sx)}\n    >\n      <span>{empty ? \"\\n\" : children}</span>\n    </span>\n  );\n}\n\nfunction CodeBlockFooter({ sx, ...props }: Styled<ComponentProps<\"div\">>) {\n  return (\n    <div\n      data-slot=\"code-block-footer\"\n      {...props}\n      {...stylex.props(styles.footer, sx)}\n    />\n  );\n}\n\nexport {\n  CodeBlock,\n  CodeBlockActions,\n  CodeBlockContent,\n  CodeBlockFooter,\n  CodeBlockHeader,\n  CodeBlockLine,\n  codeBlockLineVariants,\n  codeBlockSizes,\n  CodeBlockTitle,\n  codeBlockColors,\n};\nexport type { CodeBlockLineVariant, CodeBlockSize, CodeBlockColor };\n",
      "type": "registry:component"
    }
  ],
  "docs": "Usage: https://constella.aayush.cv/docs/components/code-block/index.md",
  "type": "registry:ui"
}