import {
  DATA_TOP_LAYER_ATTR
} from "./3NI6FTA2.jsx";
import {
  ButtonRoot
} from "./UKTBL2JL.jsx";
import {
  createRegisterId
} from "./JNCCF6MP.jsx";
import {
  Polymorphic
} from "./FLVHQV4A.jsx";
import {
  __export
} from "./5WXHJDCZ.jsx";

// src/toast/index.tsx
var toast_exports = {};
__export(toast_exports, {
  CloseButton: () => ToastCloseButton,
  Description: () => ToastDescription,
  List: () => ToastList,
  ProgressFill: () => ToastProgressFill,
  ProgressTrack: () => ToastProgressTrack,
  Region: () => ToastRegion,
  Root: () => ToastRoot,
  Title: () => ToastTitle,
  Toast: () => Toast,
  toaster: () => toaster,
  useToastContext: () => useToastContext
});

// src/toast/toast-close-button.tsx
import { callHandler } from "@kobalte/utils";
import {
  splitProps
} from "solid-js";

// src/toast/toast-context.tsx
import { createContext, useContext } from "solid-js";
var ToastContext = createContext();
function useToastContext() {
  const context = useContext(ToastContext);
  if (context === void 0) {
    throw new Error(
      "[kobalte]: `useToastContext` must be used within a `Toast.Root` component"
    );
  }
  return context;
}

// src/toast/toast-close-button.tsx
function ToastCloseButton(props) {
  const context = useToastContext();
  const [local, others] = splitProps(props, [
    "aria-label",
    "onClick"
  ]);
  const onClick = (e) => {
    callHandler(e, local.onClick);
    context.close();
  };
  return <ButtonRoot
    aria-label={local["aria-label"] || context.translations().close}
    onClick={onClick}
    {...others}
  />;
}

// src/toast/toast-description.tsx
import { mergeDefaultProps } from "@kobalte/utils";
import {
  createEffect,
  onCleanup,
  splitProps as splitProps2
} from "solid-js";
function ToastDescription(props) {
  const context = useToastContext();
  const mergedProps = mergeDefaultProps(
    {
      id: context.generateId("description")
    },
    props
  );
  const [local, others] = splitProps2(mergedProps, ["id"]);
  createEffect(() => onCleanup(context.registerDescriptionId(local.id)));
  return <Polymorphic
    as="div"
    id={local.id}
    {...others}
  />;
}

// src/toast/toast-list.tsx
import {
  callHandler as callHandler2,
  contains,
  focusWithoutScrolling,
  getDocument,
  getWindow,
  mergeRefs
} from "@kobalte/utils";
import {
  For,
  createEffect as createEffect2,
  on,
  onCleanup as onCleanup2,
  splitProps as splitProps3
} from "solid-js";
import { isServer } from "solid-js/web";

// src/toast/toast-region-context.tsx
import { createContext as createContext2, useContext as useContext2 } from "solid-js";
var ToastRegionContext = createContext2();
function useToastRegionContext() {
  const context = useContext2(ToastRegionContext);
  if (context === void 0) {
    throw new Error(
      "[kobalte]: `useToastRegionContext` must be used within a `Toast.Region` component"
    );
  }
  return context;
}

// src/toast/toast-list.tsx
function ToastList(props) {
  let ref;
  const context = useToastRegionContext();
  const [local, others] = splitProps3(props, [
    "ref",
    "onFocusIn",
    "onFocusOut",
    "onPointerMove",
    "onPointerLeave"
  ]);
  const onFocusIn = (e) => {
    callHandler2(e, local.onFocusIn);
    if (context.pauseOnInteraction() && !context.isPaused()) {
      context.pauseAllTimer();
    }
  };
  const onFocusOut = (e) => {
    callHandler2(e, local.onFocusOut);
    if (!contains(ref, e.relatedTarget)) {
      context.resumeAllTimer();
    }
  };
  const onPointerMove = (e) => {
    callHandler2(e, local.onPointerMove);
    if (context.pauseOnInteraction() && !context.isPaused()) {
      context.pauseAllTimer();
    }
  };
  const onPointerLeave = (e) => {
    callHandler2(e, local.onPointerLeave);
    if (!contains(ref, getDocument(ref).activeElement)) {
      context.resumeAllTimer();
    }
  };
  createEffect2(
    on([() => ref, () => context.hotkey()], ([ref2, hotkey]) => {
      if (isServer) {
        return;
      }
      if (!ref2) {
        return;
      }
      const doc = getDocument(ref2);
      const onKeyDown = (event) => {
        const isHotkeyPressed = hotkey.every(
          (key) => event[key] || event.code === key
        );
        if (isHotkeyPressed) {
          focusWithoutScrolling(ref2);
        }
      };
      doc.addEventListener("keydown", onKeyDown);
      onCleanup2(() => doc.removeEventListener("keydown", onKeyDown));
    })
  );
  createEffect2(() => {
    if (!context.pauseOnPageIdle()) {
      return;
    }
    const win = getWindow(ref);
    win.addEventListener("blur", context.pauseAllTimer);
    win.addEventListener("focus", context.resumeAllTimer);
    onCleanup2(() => {
      win.removeEventListener("blur", context.pauseAllTimer);
      win.removeEventListener("focus", context.resumeAllTimer);
    });
  });
  return <Polymorphic
    as="ol"
    ref={mergeRefs((el) => ref = el, local.ref)}
    tabIndex={-1}
    onFocusIn={onFocusIn}
    onFocusOut={onFocusOut}
    onPointerMove={onPointerMove}
    onPointerLeave={onPointerLeave}
    {...others}
  ><For each={context.toasts()}>{(toast) => toast.toastComponent({
    get toastId() {
      return toast.id;
    }
  })}</For></Polymorphic>;
}

// src/toast/toast-progress-fill.tsx
import {
  createEffect as createEffect3,
  createSignal,
  onCleanup as onCleanup3,
  splitProps as splitProps4
} from "solid-js";
import { combineStyle } from "@solid-primitives/props";
function ToastProgressFill(props) {
  const rootContext = useToastRegionContext();
  const context = useToastContext();
  const [local, others] = splitProps4(props, [
    "style"
  ]);
  const [lifeTime, setLifeTime] = createSignal(100);
  let totalElapsedTime = 0;
  createEffect3(() => {
    if (rootContext.isPaused() || context.isPersistent()) {
      return;
    }
    const intervalId = setInterval(() => {
      const elapsedTime = (/* @__PURE__ */ new Date()).getTime() - context.closeTimerStartTime() + totalElapsedTime;
      const life = Math.trunc(100 - elapsedTime / context.duration() * 100);
      setLifeTime(life < 0 ? 0 : life);
    });
    onCleanup3(() => {
      totalElapsedTime += (/* @__PURE__ */ new Date()).getTime() - context.closeTimerStartTime();
      clearInterval(intervalId);
    });
  });
  return <Polymorphic
    as="div"
    style={combineStyle(
      {
        "--kb-toast-progress-fill-width": `${lifeTime()}%`
      },
      local.style
    )}
    {...others}
  />;
}

// src/toast/toast-progress-track.tsx
function ToastProgressTrack(props) {
  return <Polymorphic
    as="div"
    aria-hidden="true"
    role="presentation"
    {...props}
  />;
}

// src/toast/toast-region.tsx
import {
  createGenerateId,
  mergeDefaultProps as mergeDefaultProps2
} from "@kobalte/utils";
import {
  createMemo,
  createSignal as createSignal2,
  createUniqueId,
  splitProps as splitProps5
} from "solid-js";
import { combineStyle as combineStyle2 } from "@solid-primitives/props";

// src/toast/toast-store.ts
import { createStore } from "solid-js/store";
var [state, setState] = createStore({
  toasts: []
});
function add(toast) {
  setState("toasts", (prev) => [...prev, toast]);
}
function get(id) {
  return state.toasts.find((toast) => toast.id === id);
}
function update(id, toast) {
  const index = state.toasts.findIndex((toast2) => toast2.id === id);
  if (index !== -1) {
    setState("toasts", (prev) => [
      ...prev.slice(0, index),
      toast,
      ...prev.slice(index + 1)
    ]);
  }
}
function dismiss(id) {
  setState("toasts", (toast) => toast.id === id, "dismiss", true);
}
function remove(id) {
  setState("toasts", (prev) => prev.filter((toast) => toast.id !== id));
}
function clear() {
  setState("toasts", []);
}
var toastStore = {
  toasts: () => state.toasts,
  add,
  get,
  update,
  dismiss,
  remove,
  clear
};

// src/toast/toast.intl.ts
var TOAST_HOTKEY_PLACEHOLDER = "{hotkey}";
var TOAST_INTL_TRANSLATIONS = {
  // `aria-label` of Toast.CloseButton.
  close: "Close"
};
var TOAST_REGION_INTL_TRANSLATIONS = {
  // `aria-label` of Toast.Region with notification count.
  notifications: (hotkeyPlaceholder) => `Notifications (${hotkeyPlaceholder})`
};

// src/toast/toast-region.tsx
function ToastRegion(props) {
  const mergedProps = mergeDefaultProps2(
    {
      id: `toast-region-${createUniqueId()}`,
      hotkey: ["altKey", "KeyT"],
      duration: 5e3,
      limit: 3,
      swipeDirection: "right",
      swipeThreshold: 50,
      pauseOnInteraction: true,
      pauseOnPageIdle: true,
      topLayer: true,
      translations: TOAST_REGION_INTL_TRANSLATIONS
    },
    props
  );
  const [local, others] = splitProps5(
    mergedProps,
    [
      "translations",
      "style",
      "hotkey",
      "duration",
      "limit",
      "swipeDirection",
      "swipeThreshold",
      "pauseOnInteraction",
      "pauseOnPageIdle",
      "topLayer",
      "aria-label",
      "regionId"
    ]
  );
  const toasts = createMemo(
    () => toastStore.toasts().filter(
      (toast) => toast.region === local.regionId && toast.dismiss === false
    ).slice(0, local.limit)
  );
  const [isPaused, setIsPaused] = createSignal2(false);
  const hasToasts = () => toasts().length > 0;
  const hotkeyLabel = () => {
    return local.hotkey.join("+").replace(/Key/g, "").replace(/Digit/g, "");
  };
  const ariaLabel = () => {
    const label = local["aria-label"] || local.translations.notifications(TOAST_HOTKEY_PLACEHOLDER);
    return label.replace(TOAST_HOTKEY_PLACEHOLDER, hotkeyLabel());
  };
  const topLayerAttr = () => ({
    [DATA_TOP_LAYER_ATTR]: local.topLayer ? "" : void 0
  });
  const context = {
    isPaused,
    toasts,
    hotkey: () => local.hotkey,
    duration: () => local.duration,
    swipeDirection: () => local.swipeDirection,
    swipeThreshold: () => local.swipeThreshold,
    pauseOnInteraction: () => local.pauseOnInteraction,
    pauseOnPageIdle: () => local.pauseOnPageIdle,
    pauseAllTimer: () => setIsPaused(true),
    resumeAllTimer: () => setIsPaused(false),
    generateId: createGenerateId(() => others.id)
  };
  return <ToastRegionContext.Provider value={context}><Polymorphic
    as="div"
    role="region"
    tabIndex={-1}
    aria-label={ariaLabel()}
    style={combineStyle2(
      {
        "pointer-events": hasToasts() ? local.topLayer ? "auto" : void 0 : "none"
      },
      local.style
    )}
    {...topLayerAttr()}
    {...others}
  /></ToastRegionContext.Provider>;
}

// src/toast/toast-root.tsx
import {
  callHandler as callHandler3,
  createGenerateId as createGenerateId2,
  mergeDefaultProps as mergeDefaultProps3,
  mergeRefs as mergeRefs2
} from "@kobalte/utils";
import {
  Show,
  createEffect as createEffect4,
  createMemo as createMemo2,
  createSignal as createSignal3,
  createUniqueId as createUniqueId2,
  on as on2,
  onMount,
  splitProps as splitProps6
} from "solid-js";
import { combineStyle as combineStyle3 } from "@solid-primitives/props";
import createPresence from "solid-presence";
var TOAST_SWIPE_START_EVENT = "toast.swipeStart";
var TOAST_SWIPE_MOVE_EVENT = "toast.swipeMove";
var TOAST_SWIPE_CANCEL_EVENT = "toast.swipeCancel";
var TOAST_SWIPE_END_EVENT = "toast.swipeEnd";
function ToastRoot(props) {
  const rootContext = useToastRegionContext();
  const mergedProps = mergeDefaultProps3(
    {
      id: `toast-${createUniqueId2()}`,
      priority: "high",
      translations: TOAST_INTL_TRANSLATIONS
    },
    props
  );
  const [local, others] = splitProps6(
    mergedProps,
    [
      "ref",
      "translations",
      "toastId",
      "style",
      "priority",
      "duration",
      "persistent",
      "onPause",
      "onResume",
      "onSwipeStart",
      "onSwipeMove",
      "onSwipeCancel",
      "onSwipeEnd",
      "onEscapeKeyDown",
      "onKeyDown",
      "onPointerDown",
      "onPointerMove",
      "onPointerUp"
    ]
  );
  const [isOpen, setIsOpen] = createSignal3(true);
  const [titleId, setTitleId] = createSignal3();
  const [descriptionId, setDescriptionId] = createSignal3();
  const [isAnimationEnabled, setIsAnimationEnabled] = createSignal3(true);
  const [ref, setRef] = createSignal3();
  const { present } = createPresence({
    show: isOpen,
    element: () => ref() ?? null
  });
  const duration = createMemo2(() => local.duration || rootContext.duration());
  let closeTimerId;
  let closeTimerStartTime = 0;
  let closeTimerRemainingTime = duration();
  let pointerStart = null;
  let swipeDelta = null;
  const close = () => {
    setIsOpen(false);
    setIsAnimationEnabled(true);
  };
  const deleteToast = () => {
    toastStore.remove(local.toastId);
  };
  const startTimer = (duration2) => {
    if (!duration2 || local.persistent) {
      return;
    }
    window.clearTimeout(closeTimerId);
    closeTimerStartTime = (/* @__PURE__ */ new Date()).getTime();
    closeTimerId = window.setTimeout(close, duration2);
  };
  const resumeTimer = () => {
    startTimer(closeTimerRemainingTime);
    local.onResume?.();
  };
  const pauseTimer = () => {
    const elapsedTime = (/* @__PURE__ */ new Date()).getTime() - closeTimerStartTime;
    closeTimerRemainingTime = closeTimerRemainingTime - elapsedTime;
    window.clearTimeout(closeTimerId);
    local.onPause?.();
  };
  const onKeyDown = (e) => {
    callHandler3(e, local.onKeyDown);
    if (e.key !== "Escape") {
      return;
    }
    local.onEscapeKeyDown?.(e);
    if (!e.defaultPrevented) {
      close();
    }
  };
  const onPointerDown = (e) => {
    callHandler3(e, local.onPointerDown);
    if (e.button !== 0) {
      return;
    }
    pointerStart = { x: e.clientX, y: e.clientY };
  };
  const onPointerMove = (e) => {
    callHandler3(e, local.onPointerMove);
    if (!pointerStart) {
      return;
    }
    const x = e.clientX - pointerStart.x;
    const y = e.clientY - pointerStart.y;
    const hasSwipeMoveStarted = Boolean(swipeDelta);
    const isHorizontalSwipe = ["left", "right"].includes(
      rootContext.swipeDirection()
    );
    const clamp = ["left", "up"].includes(rootContext.swipeDirection()) ? Math.min : Math.max;
    const clampedX = isHorizontalSwipe ? clamp(0, x) : 0;
    const clampedY = !isHorizontalSwipe ? clamp(0, y) : 0;
    const moveStartBuffer = e.pointerType === "touch" ? 10 : 2;
    const delta = { x: clampedX, y: clampedY };
    const eventDetail = { originalEvent: e, delta };
    if (hasSwipeMoveStarted) {
      swipeDelta = delta;
      handleAndDispatchCustomEvent(
        TOAST_SWIPE_MOVE_EVENT,
        local.onSwipeMove,
        eventDetail
      );
      const { x: x2, y: y2 } = delta;
      e.currentTarget.setAttribute("data-swipe", "move");
      e.currentTarget.style.setProperty("--kb-toast-swipe-move-x", `${x2}px`);
      e.currentTarget.style.setProperty("--kb-toast-swipe-move-y", `${y2}px`);
    } else if (isDeltaInDirection(delta, rootContext.swipeDirection(), moveStartBuffer)) {
      swipeDelta = delta;
      handleAndDispatchCustomEvent(
        TOAST_SWIPE_START_EVENT,
        local.onSwipeStart,
        eventDetail
      );
      e.currentTarget.setAttribute("data-swipe", "start");
      e.target.setPointerCapture(e.pointerId);
    } else if (Math.abs(x) > moveStartBuffer || Math.abs(y) > moveStartBuffer) {
      pointerStart = null;
    }
  };
  const onPointerUp = (e) => {
    callHandler3(e, local.onPointerUp);
    const delta = swipeDelta;
    const target = e.target;
    if (target.hasPointerCapture(e.pointerId)) {
      target.releasePointerCapture(e.pointerId);
    }
    swipeDelta = null;
    pointerStart = null;
    if (delta) {
      const toast = e.currentTarget;
      const eventDetail = { originalEvent: e, delta };
      if (isDeltaInDirection(
        delta,
        rootContext.swipeDirection(),
        rootContext.swipeThreshold()
      )) {
        handleAndDispatchCustomEvent(
          TOAST_SWIPE_END_EVENT,
          local.onSwipeEnd,
          eventDetail
        );
        const { x, y } = delta;
        e.currentTarget.setAttribute("data-swipe", "end");
        e.currentTarget.style.removeProperty("--kb-toast-swipe-move-x");
        e.currentTarget.style.removeProperty("--kb-toast-swipe-move-y");
        e.currentTarget.style.setProperty("--kb-toast-swipe-end-x", `${x}px`);
        e.currentTarget.style.setProperty("--kb-toast-swipe-end-y", `${y}px`);
        close();
      } else {
        handleAndDispatchCustomEvent(
          TOAST_SWIPE_CANCEL_EVENT,
          local.onSwipeCancel,
          eventDetail
        );
        e.currentTarget.setAttribute("data-swipe", "cancel");
        e.currentTarget.style.removeProperty("--kb-toast-swipe-move-x");
        e.currentTarget.style.removeProperty("--kb-toast-swipe-move-y");
        e.currentTarget.style.removeProperty("--kb-toast-swipe-end-x");
        e.currentTarget.style.removeProperty("--kb-toast-swipe-end-y");
      }
      toast.addEventListener("click", (event) => event.preventDefault(), {
        once: true
      });
    }
  };
  onMount(() => {
    if (rootContext.toasts().find((toast) => toast.id === local.toastId && toast.update)) {
      setIsAnimationEnabled(false);
    }
  });
  createEffect4(
    on2(
      () => rootContext.isPaused(),
      (isPaused) => {
        if (isPaused) {
          pauseTimer();
        } else {
          resumeTimer();
        }
      },
      {
        defer: true
      }
    )
  );
  createEffect4(
    on2([isOpen, duration], ([isOpen2, duration2]) => {
      if (isOpen2 && !rootContext.isPaused()) {
        startTimer(duration2);
      }
    })
  );
  createEffect4(
    on2(
      () => toastStore.get(local.toastId)?.dismiss,
      (dismiss3) => dismiss3 && close()
    )
  );
  createEffect4(
    on2(
      () => present(),
      (isPresent) => !isPresent && deleteToast()
    )
  );
  const context = {
    translations: () => local.translations,
    close,
    duration,
    isPersistent: () => local.persistent ?? false,
    closeTimerStartTime: () => closeTimerStartTime,
    generateId: createGenerateId2(() => others.id),
    registerTitleId: createRegisterId(setTitleId),
    registerDescriptionId: createRegisterId(setDescriptionId)
  };
  return <Show when={present()}><ToastContext.Provider value={context}><Polymorphic
    as="li"
    ref={mergeRefs2(setRef, local.ref)}
    role="status"
    tabIndex={0}
    style={combineStyle3(
      {
        animation: isAnimationEnabled() ? void 0 : "none",
        "user-select": "none",
        "touch-action": "none"
      },
      local.style
    )}
    aria-live={local.priority === "high" ? "assertive" : "polite"}
    aria-atomic="true"
    aria-labelledby={titleId()}
    aria-describedby={descriptionId()}
    data-opened={isOpen() ? "" : void 0}
    data-closed={!isOpen() ? "" : void 0}
    data-swipe-direction={rootContext.swipeDirection()}
    onKeyDown={onKeyDown}
    onPointerDown={onPointerDown}
    onPointerMove={onPointerMove}
    onPointerUp={onPointerUp}
    {...others}
  /></ToastContext.Provider></Show>;
}
function isDeltaInDirection(delta, direction, threshold = 0) {
  const deltaX = Math.abs(delta.x);
  const deltaY = Math.abs(delta.y);
  const isDeltaX = deltaX > deltaY;
  if (direction === "left" || direction === "right") {
    return isDeltaX && deltaX > threshold;
  }
  return !isDeltaX && deltaY > threshold;
}
function handleAndDispatchCustomEvent(name, handler, detail) {
  const currentTarget = detail.originalEvent.currentTarget;
  const event = new CustomEvent(name, {
    bubbles: true,
    cancelable: true,
    detail
  });
  if (handler) {
    currentTarget.addEventListener(name, handler, {
      once: true
    });
  }
  currentTarget.dispatchEvent(event);
}

// src/toast/toast-title.tsx
import { mergeDefaultProps as mergeDefaultProps4 } from "@kobalte/utils";
import {
  createEffect as createEffect5,
  onCleanup as onCleanup4,
  splitProps as splitProps7
} from "solid-js";
function ToastTitle(props) {
  const context = useToastContext();
  const mergedProps = mergeDefaultProps4(
    {
      id: context.generateId("title")
    },
    props
  );
  const [local, others] = splitProps7(mergedProps, ["id"]);
  createEffect5(() => onCleanup4(context.registerTitleId(local.id)));
  return <Polymorphic as="div" id={local.id} {...others} />;
}

// src/toast/toaster.ts
import { isFunction } from "@kobalte/utils";
var toastsCounter = 0;
function show(toastComponent, options) {
  const id = toastsCounter++;
  toastStore.add({
    id,
    toastComponent,
    dismiss: false,
    update: false,
    region: options?.region
  });
  return id;
}
function update2(id, toastComponent) {
  toastStore.update(id, { id, toastComponent, dismiss: false, update: true });
}
function promise(promise2, toastComponent, options) {
  const id = show((props) => {
    return toastComponent({
      get toastId() {
        return props.toastId;
      },
      state: "pending"
    });
  }, options);
  (isFunction(promise2) ? promise2() : promise2).then(
    (data) => update2(id, (props) => {
      return toastComponent({
        get toastId() {
          return props.toastId;
        },
        state: "fulfilled",
        data
      });
    })
  ).catch(
    (error) => update2(id, (props) => {
      return toastComponent({
        get toastId() {
          return props.toastId;
        },
        state: "rejected",
        error
      });
    })
  );
  return id;
}
function dismiss2(id) {
  toastStore.dismiss(id);
  return id;
}
function clear2() {
  toastStore.clear();
}
var toaster = {
  show,
  update: update2,
  promise,
  dismiss: dismiss2,
  clear: clear2
};

// src/toast/index.tsx
var Toast = Object.assign(ToastRoot, {
  CloseButton: ToastCloseButton,
  Description: ToastDescription,
  List: ToastList,
  ProgressFill: ToastProgressFill,
  ProgressTrack: ToastProgressTrack,
  Region: ToastRegion,
  Title: ToastTitle,
  toaster
});

export {
  toaster,
  useToastContext,
  ToastCloseButton,
  ToastDescription,
  ToastList,
  ToastProgressFill,
  ToastProgressTrack,
  ToastRegion,
  ToastRoot,
  ToastTitle,
  Toast,
  toast_exports
};
