{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "dependencies": [],
  "description": "Accessible native form label with implicit, explicit, and multiple-label support. Base-compatible double-click selection protection and full native-prop/render/ref composition keep browser association authoritative.",
  "files": [
    {
      "content": "\"use client\";\n\n/**\n * heidi-ui Label — a native label with Base-compatible interaction polish.\n *\n * The browser owns association, accessible naming, focus transfer, activation,\n * and support for implicit/explicit/multiple labels. Heidi adds only the small\n * double-click selection guard used by current Base UI and Radix labels, plus\n * the library-wide native-prop/render/ref composition surface.\n *\n * `render` must ultimately resolve to a real <label>. A non-label host cannot\n * provide native association and is reported during development.\n */\n\nimport {\n  type ComponentPropsWithoutRef,\n  type MouseEvent,\n  type ReactNode,\n  type Ref,\n  useCallback,\n  useRef\n} from \"react\";\nimport {\n  composeHeidiEventHandlers,\n  mergeHeidiRefs,\n  renderHeidiElement,\n  type HeidiIntrinsicHostProps\n} from \"../_internal/render-element\";\nimport { LABEL_CLASSES } from \"./label.classes.generated\";\n\nexport type LabelRootState = Record<string, never>;\n\ntype LabelRootNativeProps = Omit<\n  ComponentPropsWithoutRef<\"label\">,\n  | \"children\"\n  | \"className\"\n  | \"htmlFor\"\n  | \"onMouseDown\"\n  | \"ref\"\n  | \"style\"\n>;\n\nexport type LabelRootProps = HeidiIntrinsicHostProps<\n  LabelRootState,\n  \"label\"\n> &\n  LabelRootNativeProps & {\n    children?: ReactNode;\n    htmlFor?: string;\n    onMouseDown?: ComponentPropsWithoutRef<\"label\">[\"onMouseDown\"];\n    ref?: Ref<HTMLLabelElement>;\n  };\n\nexport function LabelRoot({\n  children,\n  className,\n  htmlFor,\n  onMouseDown,\n  ref,\n  render,\n  style,\n  ...nativeProps\n}: LabelRootProps) {\n  const warnedHostRef = useRef(false);\n  const verifyNativeHost = useCallback((element: HTMLLabelElement | null) => {\n    if (\n      process.env.NODE_ENV !== \"production\" &&\n      element &&\n      element.tagName !== \"LABEL\" &&\n      !warnedHostRef.current\n    ) {\n      warnedHostRef.current = true;\n      // oxlint-disable-next-line no-console -- losing native label semantics is an accessibility failure.\n      console.error(\n        \"heidi-ui Label: render must resolve to a native <label>; non-label hosts cannot provide native form-control association.\"\n      );\n    }\n  }, []);\n  const handleMouseDown = composeHeidiEventHandlers(\n    onMouseDown,\n    (event: MouseEvent<HTMLLabelElement>) => {\n      const target = event.target;\n      const control = event.currentTarget.control;\n      const ownerWindow = event.currentTarget.ownerDocument.defaultView;\n      const ElementConstructor = ownerWindow?.Element;\n      const NodeConstructor = ownerWindow?.Node;\n      if (\n        (NodeConstructor && target instanceof NodeConstructor && control?.contains(target)) ||\n        (ElementConstructor && target instanceof ElementConstructor &&\n          target.closest(\"button,input,select,textarea\"))\n      ) {\n        return;\n      }\n      if (event.detail > 1) {\n        event.preventDefault();\n      }\n    }\n  );\n\n  return renderHeidiElement({\n    className: LABEL_CLASSES.root,\n    dataPart: \"label-root\",\n    element: \"label\",\n    props: {\n      ...nativeProps,\n      children,\n      htmlFor,\n      onMouseDown: handleMouseDown,\n      ref: mergeHeidiRefs(ref, verifyNativeHost)\n    },\n    renderProps: { className, render, style },\n    state: {}\n  });\n}\n\nexport const Label = {\n  Root: LabelRoot\n} as const;\n",
      "path": "packages/heidi-ui/src/label/label.tsx",
      "target": "components/ui/heidi/label/label.tsx",
      "type": "registry:ui"
    },
    {
      "content": "/*\n * heidi-ui label — STRUCTURAL CSS only. No --hui-*.\n * Preserve native inline layout while containing hostile unbroken text.\n */\n\n@layer heidi-ui-base {\n  .hui-label-root {\n    overflow-wrap: anywhere;\n  }\n}\n",
      "path": "packages/heidi-ui/src/label/label.base.css",
      "target": "components/ui/heidi/label/label.base.css",
      "type": "registry:ui"
    },
    {
      "content": "/*\n * heidi-ui label — VISUAL theme (opt-in). Consumes --hui-*.\n */\n\n@layer heidi-ui {\n  .hui-label-root {\n    color: var(--hui-color-fg-strong);\n    font-size: var(--hui-text-body-size);\n    font-weight: var(--hui-font-weight-medium);\n  }\n}\n",
      "path": "packages/heidi-ui/src/label/label.theme.css",
      "target": "components/ui/heidi/label/label.theme.css",
      "type": "registry:ui"
    },
    {
      "content": "/*\n * heidi-ui label — aggregator.\n */\n\n@import \"./label.base.css\";\n@import \"../../../../styles/heidi-ui-adapter.css\";\n@import \"./label.theme.css\";\n",
      "path": "packages/heidi-ui/src/label/label.css",
      "target": "components/ui/heidi/label/label.css",
      "type": "registry:ui"
    },
    {
      "content": "/** GENERATED from packages/heidi-ui/src/label/label.base.css + packages/heidi-ui/src/label/label.theme.css — do not edit by hand.\n * Rebuild: `bun run hui:build`. Freshness: `bun run contracts:check`. */\nexport const LABEL_CLASSES = {\n  root: \"hui-label-root\",\n} as const;\n",
      "path": "packages/heidi-ui/src/label/label.classes.generated.ts",
      "target": "components/ui/heidi/label/label.classes.generated.ts",
      "type": "registry:ui"
    },
    {
      "content": "/** GENERATED from label.anatomy.json + label.base.css + label.theme.css — do not edit by hand.\n * Rebuild: `bun run hui:build`. Freshness: `bun run contracts:check`. */\n\n\nexport const LABEL_ANATOMY = {\n  \"component\": \"label\",\n  \"description\": \"Accessible native form label with implicit, explicit, and multiple-label support. Base-compatible double-click selection protection and full native-prop/render/ref composition keep browser association authoritative.\",\n  \"schemaVersion\": 2,\n  \"parts\": {\n    \"root\": {\n      \"aria\": {\n        \"owns\": [],\n        \"role\": null\n      },\n      \"class\": \"hui-label-root\",\n      \"css\": {\n        \"structural\": [\n          \"overflow-wrap\"\n        ]\n      },\n      \"dataPart\": \"label-root\",\n      \"description\": \"Native label element; htmlFor associates with a labelable control id. The render host must remain a label so native focus, activation, and accessible naming survive.\",\n      \"element\": \"label\",\n      \"nativeProps\": true,\n      \"props\": [\n        \"className\",\n        \"htmlFor\",\n        \"onMouseDown\",\n        \"ref\",\n        \"render\",\n        \"style\"\n      ],\n      \"pseudoStates\": [],\n      \"states\": {}\n    }\n  },\n  \"rootProps\": [\n    \"htmlFor\"\n  ],\n  \"tokens\": [\n    \"--hui-color-fg-strong\",\n    \"--hui-font-weight-medium\",\n    \"--hui-text-body-size\"\n  ]\n} as const;\n",
      "path": "packages/heidi-ui/src/label/label.anatomy.generated.ts",
      "target": "components/ui/heidi/label/label.anatomy.generated.ts",
      "type": "registry:ui"
    },
    {
      "content": "{\n  \"component\": \"label\",\n  \"description\": \"Accessible native form label with implicit, explicit, and multiple-label support. Base-compatible double-click selection protection and full native-prop/render/ref composition keep browser association authoritative.\",\n  \"schemaVersion\": 2,\n  \"parts\": {\n    \"root\": {\n      \"aria\": {\n        \"owns\": [],\n        \"role\": null\n      },\n      \"class\": \"hui-label-root\",\n      \"css\": {\n        \"structural\": [\"overflow-wrap\"]\n      },\n      \"dataPart\": \"label-root\",\n      \"description\": \"Native label element; htmlFor associates with a labelable control id. The render host must remain a label so native focus, activation, and accessible naming survive.\",\n      \"element\": \"label\",\n      \"nativeProps\": true,\n      \"props\": [\"className\", \"htmlFor\", \"onMouseDown\", \"ref\", \"render\", \"style\"],\n      \"pseudoStates\": [],\n      \"states\": {}\n    }\n  },\n  \"rootProps\": [\"htmlFor\"]\n}\n",
      "path": "packages/heidi-ui/src/label/label.anatomy.json",
      "target": "components/ui/heidi/label/label.anatomy.json",
      "type": "registry:ui"
    },
    {
      "content": "/**\n * Shared host rendering for heidi-ui parts — Base-UI-shaped composition\n * (docs/HEIDI-UI-HEADLESS.md § 4 / HEIDI-UI.md § 4.5):\n *   - className / style as value or (state) => value\n *   - render as ReactElement or (props, state) => ReactElement\n *   - ref forwarding\n *   - data-hui-part always set (stable unstyled hook)\n *\n * Structural inline styles (e.g. anchorName) are merged last so a consumer\n * style override cannot drop platform wiring.\n */\n\nimport {\n  cloneElement,\n  createElement,\n  isValidElement,\n  type CSSProperties,\n  type ComponentPropsWithRef,\n  type HTMLAttributes,\n  type ReactElement,\n  type ReactNode,\n  type Ref,\n  type RefCallback\n} from \"react\";\n\nexport type HeidiClassName<State> = string | ((state: State) => string | undefined) | undefined;\n\nexport type HeidiStyle<State> =\n  | CSSProperties\n  | ((state: State) => CSSProperties | undefined)\n  | undefined;\n\nexport type HeidiRenderFn<State, Props> = (\n  props: Props,\n  state: State\n) => ReactElement;\n\nexport type HeidiRender<State, Props> =\n  | ReactElement\n  | HeidiRenderFn<State, Props>\n  | undefined;\n\ntype DefaultRenderProps = HTMLAttributes<HTMLElement> & { ref?: Ref<HTMLElement> };\n\nexport type HeidiHostProps<\n  State,\n  RenderProps extends object = DefaultRenderProps\n> = {\n  className?: HeidiClassName<State>;\n  render?: HeidiRender<State, RenderProps>;\n  style?: HeidiStyle<State>;\n};\n\nexport type HeidiIntrinsicHostProps<\n  State,\n  Tag extends keyof HTMLElementTagNameMap\n> = HeidiHostProps<State, ComponentPropsWithRef<Tag>>;\n\nfunction resolveClassName<State>(\n  className: HeidiClassName<State>,\n  state: State\n): string | undefined {\n  return typeof className === \"function\" ? className(state) : className;\n}\n\nfunction resolveStyle<State>(style: HeidiStyle<State>, state: State): CSSProperties | undefined {\n  return typeof style === \"function\" ? style(state) : style;\n}\n\nfunction mergeClassNames(...parts: Array<string | undefined>): string | undefined {\n  const merged = parts.filter(Boolean).join(\" \");\n  return merged.length > 0 ? merged : undefined;\n}\n\n/**\n * Compose a consumer event with library behavior. Consumers run first and may\n * cancel the component behavior with `event.preventDefault()`. Heidi keeps\n * this native-event convention intentionally: it avoids a second branded event\n * API while still making async/controlled actions vetoable.\n */\nexport function composeHeidiEventHandlers<Event extends { defaultPrevented: boolean }>(\n  consumer: ((event: Event) => void) | undefined,\n  library: (event: Event) => void\n): (event: Event) => void {\n  return (event) => {\n    consumer?.(event);\n    if (!event.defaultPrevented) {\n      library(event);\n    }\n  };\n}\n\n/** React 19-safe ref fan-out, including callback-ref cleanup functions. */\nexport function mergeHeidiRefs<Element>(\n  ...inputRefs: Array<Ref<Element> | undefined>\n): Ref<Element> | undefined {\n  const refs = Array.from(\n    new Set(\n      inputRefs.filter(\n        (ref): ref is Exclude<Ref<Element>, null> => ref != null\n      )\n    )\n  );\n  if (refs.length === 0) {\n    return undefined;\n  }\n  if (refs.length === 1) {\n    return refs[0];\n  }\n\n  let cache = mergedRefCache;\n  for (const ref of refs) {\n    const key = ref as object;\n    let child = cache.children.get(key);\n    if (!child) {\n      child = { children: new WeakMap() };\n      cache.children.set(key, child);\n    }\n    cache = child;\n  }\n  if (cache.callback) {\n    return cache.callback as RefCallback<Element>;\n  }\n\n  const callback: RefCallback<Element> = (node) => {\n    const cleanups: Array<() => void> = [];\n    for (const ref of refs) {\n      if (typeof ref === \"function\") {\n        const cleanup = ref(node);\n        if (node !== null) {\n          cleanups.push(typeof cleanup === \"function\" ? cleanup : () => ref(null));\n        }\n      } else if (ref) {\n        ref.current = node;\n        if (node !== null) {\n          cleanups.push(() => {\n            ref.current = null;\n          });\n        }\n      }\n    }\n    return cleanups.length > 0\n      ? () => {\n          for (const cleanup of cleanups) {\n            cleanup();\n          }\n        }\n      : undefined;\n  };\n  cache.callback = callback as RefCallback<unknown>;\n  return callback;\n}\n\ntype MergedRefCache = {\n  callback?: RefCallback<unknown>;\n  children: WeakMap<object, MergedRefCache>;\n};\n\nconst mergedRefCache: MergedRefCache = { children: new WeakMap() };\n\ntype UnknownHandler = (...args: never[]) => unknown;\n\nfunction isEventHandler(key: string, value: unknown): value is UnknownHandler {\n  return /^on[A-Z]/.test(key) && typeof value === \"function\";\n}\n\nfunction defaultPrevented(args: unknown[]): boolean {\n  const event = args[0];\n  return (\n    typeof event === \"object\" &&\n    event !== null &&\n    \"defaultPrevented\" in event &&\n    event.defaultPrevented === true\n  );\n}\n\nfunction composeUnknownHandlers(\n  consumer: UnknownHandler,\n  library: UnknownHandler\n): UnknownHandler {\n  if (consumer === library) {\n    return library;\n  }\n  return ((...args: unknown[]) => {\n    (consumer as (...handlerArgs: unknown[]) => unknown)(...args);\n    if (!defaultPrevented(args)) {\n      (library as (...handlerArgs: unknown[]) => unknown)(...args);\n    }\n  }) as UnknownHandler;\n}\n\n/** Library-owned host props — permissive so button `type`, `data-*`, `popover`, etc. type-check. */\nexport type HeidiElementProps<Tag extends keyof HTMLElementTagNameMap> = Record<\n  string,\n  unknown\n> & {\n  children?: ReactNode;\n  className?: string;\n  ref?: Ref<HTMLElementTagNameMap[Tag]>;\n  style?: CSSProperties;\n};\n\ntype RenderElementParams<\n  State,\n  Tag extends keyof HTMLElementTagNameMap,\n  RenderProps extends object = DefaultRenderProps\n> = {\n  /** Default class from the generated hui-* map (theme/base target). */\n  className?: string;\n  /** Stable machine hook — always emitted. */\n  dataPart: string;\n  /** Intrinsic tag when `render` is omitted. */\n  element: Tag;\n  /** Props the library owns (aria, ids, handlers, popover, …). */\n  props: HeidiElementProps<Tag>;\n  /** Optional consumer composition props. */\n  renderProps?: HeidiHostProps<State, RenderProps>;\n  /** Typed state passed to functional className/style/render. */\n  state: State;\n  /** Structural inline styles that must survive consumer style merges. */\n  structuralStyle?: CSSProperties;\n  /**\n   * Render-element handlers to remove instead of composing. This is reserved\n   * for states such as a focusable disabled composite item where the public\n   * contract requires press handlers to be completely inert.\n   */\n  suppressRenderedHandlers?: readonly string[];\n};\n\n/**\n * Render a heidi-ui host element with optional Base-shaped composition.\n */\nexport function renderHeidiElement<\n  State,\n  Tag extends keyof HTMLElementTagNameMap,\n  RenderProps extends object = DefaultRenderProps\n>(\n  params: RenderElementParams<State, Tag, RenderProps>\n): ReactElement {\n  const {\n    className,\n    dataPart,\n    element,\n    props,\n    renderProps,\n    state,\n    structuralStyle,\n    suppressRenderedHandlers\n  } = params;\n  const consumerClass = resolveClassName(renderProps?.className, state);\n  const consumerStyle = resolveStyle(renderProps?.style, state);\n  const mergedStyle: CSSProperties | undefined =\n    props.style || consumerStyle || structuralStyle\n      ? { ...props.style, ...consumerStyle, ...structuralStyle }\n      : undefined;\n\n  const outProps: HTMLAttributes<HTMLElement> & {\n    \"data-hui-part\": string;\n    ref?: Ref<HTMLElement>;\n  } = {\n    ...(props as HTMLAttributes<HTMLElement> & { ref?: Ref<HTMLElement> }),\n    className: mergeClassNames(consumerClass, className),\n    \"data-hui-part\": dataPart,\n    style: mergedStyle\n  };\n\n  const render = renderProps?.render;\n  if (typeof render === \"function\") {\n    // Post-merge the returned element as well. This deliberately makes the\n    // stable data hook, owned semantics, refs, and internal handlers survive\n    // even when a render function forgets to spread one of the supplied props.\n    return mergeRenderedElement(\n      render(outProps as unknown as RenderProps, state),\n      outProps,\n      dataPart,\n      structuralStyle,\n      suppressRenderedHandlers\n    );\n  }\n  if (isValidElement(render)) {\n    return mergeRenderedElement(\n      render,\n      outProps,\n      dataPart,\n      structuralStyle,\n      suppressRenderedHandlers\n    );\n  }\n\n  return createElement(element, outProps as never, props.children);\n}\n\ntype RenderedProps = Record<string, unknown> & {\n  children?: ReactNode;\n  className?: string;\n  ref?: Ref<HTMLElement>;\n  style?: CSSProperties;\n};\n\nfunction mergeRenderedElement(\n  element: ReactElement,\n  libraryProps: HTMLAttributes<HTMLElement> & {\n    \"data-hui-part\": string;\n    ref?: Ref<HTMLElement>;\n  },\n  dataPart: string,\n  structuralStyle: CSSProperties | undefined,\n  suppressRenderedHandlers: readonly string[] | undefined\n): ReactElement {\n  const rendered = element as ReactElement<RenderedProps>;\n  const renderedProps = rendered.props;\n  const renderedClass =\n    renderedProps.className === libraryProps.className\n      ? undefined\n      : renderedProps.className;\n  const merged: RenderedProps = {\n    ...renderedProps,\n    ...libraryProps,\n    className: mergeClassNames(renderedClass, libraryProps.className),\n    \"data-hui-part\": dataPart,\n    ref: mergeHeidiRefs(libraryProps.ref, renderedProps.ref),\n    style: {\n      ...libraryProps.style,\n      ...renderedProps.style,\n      ...structuralStyle\n    }\n  };\n\n  if (Object.prototype.hasOwnProperty.call(renderedProps, \"children\")) {\n    merged.children = renderedProps.children;\n  }\n\n  const suppressedHandlers = suppressRenderedHandlers\n    ? new Set(suppressRenderedHandlers)\n    : null;\n  for (const key of new Set([...Object.keys(renderedProps), ...Object.keys(libraryProps)])) {\n    const consumer = renderedProps[key];\n    const library = (libraryProps as unknown as Record<string, unknown>)[key];\n    if (suppressedHandlers?.has(key)) {\n      merged[key] = library;\n      continue;\n    }\n    if (isEventHandler(key, consumer) && isEventHandler(key, library)) {\n      merged[key] = composeUnknownHandlers(consumer, library);\n    }\n  }\n\n  return cloneElement(rendered, merged as never);\n}\n",
      "path": "packages/heidi-ui/src/_internal/render-element.ts",
      "target": "components/ui/heidi/_internal/render-element.ts",
      "type": "registry:ui"
    }
  ],
  "name": "label",
  "registryDependencies": [
    "@heidi-ui/heidi-tokens"
  ],
  "title": "Label",
  "type": "registry:ui"
}
