/**
 * Value-to-label resolution for `<Select.Value>`. Mirrors Base UI React's
 * `packages/react/src/internals/resolveValueLabel.ts` — trimmed to the
 * subset the Solid port wires:
 *
 *  - `stringifyAsValue(value, itemToStringValue)` → string form for form
 *    submission + hidden-input `value`.
 *  - `stringifyAsLabel(value, itemToStringLabel)` → string form for
 *    trigger display text.
 *  - `resolveSelectedLabel` / `resolveMultipleLabels` — select display
 *    resolution with optional `items` registry support.
 *  - `hasNullItemLabel` — detects `null` entries in the items registry.
 */

/** Group shape accepted in the `items` prop. */

function isGroup(item) {
  return typeof item === "object" && item !== null && "items" in item && !("value" in item);
}
function isRecord(items) {
  return typeof items === "object" && items !== null && !Array.isArray(items);
}
function stringifyValue(value) {
  if (value == null) return "";
  if (typeof value === "string") return value;
  if (typeof value === "number" || typeof value === "boolean") {
    return String(value);
  }
  if (typeof value === "object") {
    // Object-with-value shortcut.
    if ("value" in value) {
      return stringifyValue(value.value);
    }
    try {
      return JSON.stringify(value);
    } catch {
      return "";
    }
  }
  return "";
}
export function stringifyAsValue(value, itemToStringValue) {
  if (itemToStringValue && value != null) {
    try {
      return itemToStringValue(value);
    } catch {
      /* fall through */
    }
  }
  return stringifyValue(value);
}
export function stringifyAsLabel(value, itemToStringLabel) {
  if (itemToStringLabel && value != null) {
    try {
      return itemToStringLabel(value);
    } catch {
      /* fall through */
    }
  }
  if (typeof value === "object" && value !== null && "label" in value) {
    const label = value.label;
    if (typeof label === "string") return label;
  }
  return stringifyValue(value);
}
export function resolveSelectedLabel(value, items, itemToStringLabel) {
  function fallback() {
    // `stringifyAsLabel` only ever calls this with the same `value`, so
    // widening the parameter to `unknown` is sound (function contravariance).
    return stringifyAsLabel(value, itemToStringLabel);
  }
  if (itemToStringLabel && value != null) {
    try {
      return itemToStringLabel(value);
    } catch {
      /* fall through */
    }
  }
  if (typeof value === "object" && value !== null && "label" in value) {
    const label = value.label;
    if (label != null) {
      return value.label;
    }
  }
  if (isRecord(items)) {
    const match = items[value];
    if (match != null) return match;
  } else if (Array.isArray(items)) {
    for (const entry of items) {
      if (isGroup(entry)) {
        if (isRecord(entry.items)) {
          const key = stringifyValue(value);
          if (key in entry.items) return entry.items[key];
        } else {
          for (const item of entry.items) {
            if (Object.is(item.value, value)) return item.label;
          }
        }
      } else if (typeof entry === "object" && entry !== null && "value" in entry && Object.is(entry.value, value)) {
        return entry.label;
      }
    }
  }
  return fallback();
}
export function resolveMultipleLabels(values, items, itemToStringLabel) {
  if (!values || values.length === 0) return null;
  const labels = values.map(v => resolveSelectedLabel(v, items, itemToStringLabel) ?? "");
  // Join with ", " by default. Consumers who want custom formatting use a
  // children render function on `<Select.Value>`.
  return labels.map(label => typeof label === "string" ? label : stringifyValue(label)).filter(Boolean).join(", ");
}
export function hasNullItemLabel(items) {
  if (!items) return false;
  if (isRecord(items)) return "null" in items;
  for (const entry of items) {
    if (isGroup(entry)) {
      if (hasNullItemLabel(entry.items)) return true;
    } else if (typeof entry === "object" && entry !== null && "value" in entry && entry.value == null) {
      return true;
    }
  }
  return false;
}
//# sourceMappingURL=resolve-value-label.jsx.map
