/**
 * Contexts used by the composite primitives.
 *
 * There are two distinct contexts:
 *
 * - `CompositeListContext` — exposes registration helpers + the shared
 *   `elementsRef` / `labelsRef` plain arrays. `useCompositeListItem` reads
 *   from this context; `CompositeList` provides it.
 * - `CompositeRootContext` — exposes `highlightedIndex()` + its setter so
 *   child items can read/update the focused-item state. This mirrors Base
 *   UI React's `CompositeRootContext`.
 *
 * Solid 2 context providers are "context-as-provider" (RFC 02), so a
 * `<CompositeListContext value={...}>{...}</CompositeListContext>` is used at
 * the call sites — there is no `.Provider`.
 */

import { createContext, useContext } from "solid-js";

/**
 * Per-item metadata carried alongside the `Element → metadata` map. `index`
 * is managed by `CompositeList` — consumers supply their own custom fields.
 */

/**
 * A disposer returned by subscription helpers.
 */

/**
 * The notification payload shared through `CompositeListContext.subscribe`.
 * Consumers receive the sorted map on every change.
 */

/**
 * Phantom brand carried by the erased context value. The brand exists only
 * in the type system — at runtime the field is absent — so there's no cost
 * beyond TypeScript's assignability check. It prevents arbitrary
 * `CompositeListContextValue<X>` objects from being mistaken for the erased
 * shape: only values produced by `eraseCompositeListContext` (or the frozen
 * no-op default) carry the brand.
 */

/**
 * Erased storage shape for `CompositeListContext`. `Metadata` is fixed to
 * `unknown` so the shape is concrete and the context can hold a single
 * monomorphic type. Providers erase via `eraseCompositeListContext`;
 * consumers reify via `useCompositeListContext<Metadata>()`. Both ends
 * preserve the brand so the erasure can't be bypassed with a plain cast.
 */

/**
 * Erase the `Metadata` type parameter so a concrete
 * `CompositeListContextValue<Metadata>` can be stored on the shared context.
 * The cast is confined here — the context's `register`/`subscribeMapChange`
 * handlers never actually observe values typed against the wrong `Metadata`
 * because the corresponding `useCompositeListContext<Metadata>()` reader on
 * the other side re-projects them to the same concrete type before the
 * caller sees them.
 */
export function eraseCompositeListContext(value) {
  return value;
}
const NOOP_REGISTER = (_source, _node, _metadata) => {};
const NOOP_UNREGISTER = _source => {};
const NOOP_SUBSCRIBE = _fn => {
  return () => {};
};

/**
 * Default value used when `useCompositeListItem` is rendered outside of a
 * `<CompositeList>`. Keeping the shape complete (rather than `undefined`)
 * lets tier-2 consumers (like `RadioGroup`'s items) call the hook
 * unconditionally and simply behave as "unregistered" when the wrapper is
 * absent.
 */
const NOOP_COMPOSITE_LIST_CONTEXT = eraseCompositeListContext({
  register: NOOP_REGISTER,
  unregister: NOOP_UNREGISTER,
  subscribeMapChange: NOOP_SUBSCRIBE,
  elementsRef: []
});

/**
 * The context stores the erased shape. `<CompositeList>` passes its concrete
 * `CompositeListContextValue<Metadata>` through `eraseCompositeListContext`;
 * consumers pull the branded value back out through
 * `useCompositeListContext<Metadata>()` which reifies `Metadata` at the call
 * site.
 */
export const CompositeListContext = createContext(NOOP_COMPOSITE_LIST_CONTEXT);

/**
 * Read the nearest `CompositeListContext`. Returns the no-op default when
 * there is no provider, so callers don't have to handle `undefined`. The
 * single cast here is the only place `Metadata` is re-reified from the
 * erased storage shape.
 */
export function useCompositeListContext() {
  return useContext(CompositeListContext);
}
/**
 * No-op sentinel for when no `<Composite.Root>` ancestor exists. Solid 2's
 * `useContext` throws `ContextNotFoundError` when the default is literal
 * `undefined` — even inside an owner — so we always supply a sentinel and
 * let consumers branch on `.present`.
 */
const NOOP_COMPOSITE_ROOT_CONTEXT = {
  highlightedIndex: () => -1,
  onHighlightedIndexChange: () => {},
  highlightItemOnHover: () => false,
  relayKeyboardEvent: () => {},
  present: false
};
export const CompositeRootContext = createContext(NOOP_COMPOSITE_ROOT_CONTEXT);

/**
 * Read the composite root context. Returns `undefined` in the `optional: true`
 * form when no real `<Composite.Root>` is an ancestor; otherwise throws.
 */

export function useCompositeRootContext(optional = false) {
  const context = useContext(CompositeRootContext);
  if (!context.present) {
    if (optional) return undefined;
    throw new Error("Base UI: CompositeRootContext is missing. Composite parts must be placed within <Composite.Root>.");
  }
  return context;
}
//# sourceMappingURL=composite-context.jsx.map
