import { createContext, createMemo, untrack, useContext } from "solid-js";
import { makeSlotRefDirective } from "../internals/make-slot-ref-directive.jsx";
import { readOption } from "../internals/maybe-accessor.jsx";
import { mergeRootProps } from "../internals/merge-root-props.jsx";
import { SNAPSHOT_KEYS, snapshotKeys } from "../internals/observability/snapshot.jsx";

/**
 * Why the checked state changed. Emitted on the third arg of
 * `onCheckedChange(next, event, reason)`.
 *
 * - `"trigger-press"` — click / keyboard activation that bubbles to click on
 *   the switch root, OR a change on the co-located hidden `<input>` (AT /
 *   keyboard activating the checkbox directly).
 * - `"imperative"` — programmatic `setChecked` / `toggle` with no originating
 *   DOM event.
 */

/**
 * Options for {@link createSwitch}. Every reactive input is
 * `MaybeAccessor<T>` — pass an accessor to make the value reactive.
 *
 * **Solid-native shape (2026-04-30).** No internal state. `checked` is
 * required and the consumer always owns the signal. The primitive is a pure
 * function from `(checked, onCheckedChange) → api`. Migration:
 * `createSwitch({ defaultChecked: false })` becomes
 * `const [checked, setChecked] = createSignal(false); createSwitch({ checked, onCheckedChange: setChecked })`.
 * See `solidify.md` §6 for rationale.
 */

/**
 * Public API returned by {@link createSwitch}. Flat accessors and setters at
 * the root; no `state` snapshot blob.
 */

/** Shape of attributes emitted by `c.trigger()`. */

const SwitchContext = createContext(null);

/**
 * Read the nearest {@link SwitchApi} provided by `c.Provider`. Throws when
 * used outside a Provider.
 */
export function useSwitch() {
  const ctx = useContext(SwitchContext);
  if (ctx == null) {
    throw new Error("Base UI: useSwitch() must be called inside a <c.Provider>.");
  }
  return ctx;
}

/**
 * Solid 2.0-native compound primitive for a two-state switch. One call owns
 * logical state (checked/disabled/readOnly/required, onCheckedChange). Form
 * wiring (the hidden `<input>`, name/value, field-control validation) is the
 * `<Switch.Root>` wrapper's job — those are integration concerns layered on
 * top of this primitive.
 */
export function createSwitch(options) {
  // `checked` reads through the consumer's accessor — no internal signal,
  // no controlled-or-internal branching. Memoized so dependents see the
  // same identity within a tracking scope.
  const checked = createMemo(() => Boolean(readOption(options.checked)), {
    name: "switch.checked"
  });
  const disabled = createMemo(() => Boolean(readOption(options.disabled)), {
    name: "switch.disabled"
  });
  const readOnly = createMemo(() => Boolean(readOption(options.readOnly)), {
    name: "switch.readOnly"
  });
  const required = createMemo(() => Boolean(readOption(options.required)), {
    name: "switch.required"
  });

  // `setChecked` / `toggle` are pure event-emitters. They fire
  // `onCheckedChange(next, event, reason)`; the consumer is responsible
  // for updating their checked-signal in response. There is no internal
  // state to write — `event.preventDefault()` is now a no-op for the
  // primitive.
  const setChecked = (next, event, reason = "imperative") => {
    if (untrack(disabled) || untrack(readOnly)) return;
    const ev = event ?? new Event("checkedchange", {
      cancelable: true
    });
    options.onCheckedChange?.(next, ev, reason);
  };
  const toggle = (event, reason = "imperative") => {
    setChecked(!untrack(checked), event, reason);
  };
  const triggerInternal = {
    type: "button",
    role: "switch",
    get "aria-checked"() {
      return checked() ? "true" : "false";
    },
    get "aria-readonly"() {
      return readOnly() ? "true" : undefined;
    },
    get "aria-required"() {
      return required() ? "true" : undefined;
    },
    get "data-checked"() {
      return checked() ? "" : undefined;
    },
    get "data-unchecked"() {
      return checked() ? undefined : "";
    },
    get "data-disabled"() {
      return disabled() ? "" : undefined;
    },
    get "data-readonly"() {
      return readOnly() ? "" : undefined;
    },
    get "data-required"() {
      return required() ? "" : undefined;
    },
    onClick(event) {
      if (disabled() || readOnly()) return;
      setChecked(!untrack(checked), event, "trigger-press");
    }
  };
  const trigger = userProps => mergeRootProps(triggerInternal, userProps);
  const triggerRef = () => makeSlotRefDirective(() => trigger());
  const api = {
    checked,
    disabled,
    readOnly,
    required,
    toggle,
    setChecked,
    trigger,
    triggerRef,
    Provider: props => <SwitchContext value={api}>{props.children}</SwitchContext>
  };
  api[SNAPSHOT_KEYS] = SWITCH_SNAPSHOT_KEYS;
  return api;
}
const SWITCH_SNAPSHOT_KEYS = snapshotKeys("checked", "disabled", "readOnly", "required");
//# sourceMappingURL=create-switch.jsx.map
