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 pressed state changed. Emitted on the third arg of
 * `onPressedChange(next, event, reason)` and accepted by
 * `c.setPressed(next, event?, reason?)` / `c.toggle(event?, reason?)`.
 *
 * - `"trigger-press"` — click (or keyboard activation that bubbles to click)
 *   on the trigger slot.
 * - `"imperative"` — programmatic `setPressed` / `toggle` with no
 *   originating DOM event.
 *
 * Outer compounds that embed Toggle (ToggleGroup) translate this to their
 * own reason taxonomy.
 */

/**
 * Options for {@link createToggle}.
 *
 * Every reactive input is `MaybeAccessor<T>` — pass an accessor to make the
 * value reactive, or a bare value for one-shot config. Read at use time via
 * `readOption(opt)`.
 *
 * **Solid-native shape (2026-04-30).** No internal state. `pressed` is
 * required and the consumer always owns the signal. The primitive is
 * a pure function from `(pressed, onPressedChange) → api`. Migration from
 * pre-2026-04-30: `createToggle({ defaultPressed: false })` becomes
 * `const [pressed, setPressed] = createSignal(false); createToggle({ pressed, onPressedChange: setPressed })`.
 * See `solidify.md` §6 for rationale.
 */

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

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

const ToggleContext = createContext(null);

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

/**
 * Solid 2.0-native compound primitive for a two-state pressed button. One
 * call owns logical state (pressed/disabled, onPressedChange). Composite-list
 * registration, keyboard-driven activation, and group-mode behaviour are
 * NOT in this primitive — they belong to the wrapping `<Toggle>` /
 * `<ToggleGroup>` adapters.
 */
export function createToggle(options) {
  // `pressed` 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 and so dev-time observability
  // (`name`) lines up with the rest of the api's signals.
  const pressed = createMemo(() => Boolean(readOption(options.pressed)), {
    name: "toggle.pressed"
  });
  const disabled = createMemo(() => Boolean(readOption(options.disabled)), {
    name: "toggle.disabled"
  });

  // `setPressed` / `toggle` are pure event-emitters. They fire
  // `onPressedChange(next, event, reason)`; the consumer is responsible
  // for updating their pressed-signal in response. There is no internal
  // state to write — `event.preventDefault()` is now a no-op for the
  // primitive (the consumer's handler is the only writer).
  const setPressed = (next, event, reason = "imperative") => {
    const ev = event ?? new Event("pressedchange", {
      cancelable: true
    });
    options.onPressedChange?.(next, ev, reason);
  };
  const toggle = (event, reason = "imperative") => {
    if (untrack(disabled)) return;
    setPressed(!untrack(pressed), event, reason);
  };
  const triggerInternal = {
    type: "button",
    get "aria-pressed"() {
      return pressed() ? "true" : "false";
    },
    get "data-pressed"() {
      return pressed() ? "" : undefined;
    },
    get "data-disabled"() {
      return disabled() ? "" : undefined;
    },
    onClick(event) {
      if (disabled()) return;
      setPressed(!untrack(pressed), event, "trigger-press");
    }
  };
  const trigger = userProps => mergeRootProps(triggerInternal, userProps);
  const triggerRef = () => makeSlotRefDirective(() => trigger());
  const api = {
    pressed,
    disabled,
    toggle,
    setPressed,
    trigger,
    triggerRef,
    Provider: props => <ToggleContext value={api}>{props.children}</ToggleContext>
  };
  api[SNAPSHOT_KEYS] = TOGGLE_SNAPSHOT_KEYS;
  return api;
}
const TOGGLE_SNAPSHOT_KEYS = snapshotKeys("pressed", "disabled");
//# sourceMappingURL=create-toggle.jsx.map
