All Downloads are FREE. Search and download functionalities are using the official Maven repository.

package.dist.index.js Maven / Gradle / Ivy

The newest version!
'use strict';

var core = require('@zag-js/core');
var domQuery = require('@zag-js/dom-query');
var utils = require('@zag-js/utils');
var anatomy$1 = require('@zag-js/anatomy');
var dismissable = require('@zag-js/dismissable');
var domEvent = require('@zag-js/dom-event');

// src/toast-group.connect.ts
var anatomy = anatomy$1.createAnatomy("toast").parts(
  "group",
  "root",
  "title",
  "description",
  "actionTrigger",
  "closeTrigger"
);
var parts = anatomy.build();
var dom = domQuery.createScope({
  getRegionId: (placement) => `toast-group:${placement}`,
  getRegionEl: (ctx, placement) => dom.getById(ctx, `toast-group:${placement}`),
  getRootId: (ctx) => `toast:${ctx.id}`,
  getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
  getTitleId: (ctx) => `toast:${ctx.id}:title`,
  getDescriptionId: (ctx) => `toast:${ctx.id}:description`,
  getCloseTriggerId: (ctx) => `toast${ctx.id}:close`
});
function getToastsByPlacement(toasts, placement) {
  return toasts.filter((toast) => toast.state.context.placement === placement);
}
var defaultTimeouts = {
  info: 5e3,
  error: 5e3,
  success: 2e3,
  loading: Infinity,
  DEFAULT: 5e3
};
function getToastDuration(duration, type) {
  return duration ?? defaultTimeouts[type] ?? defaultTimeouts.DEFAULT;
}
function getGroupPlacementStyle(ctx, placement) {
  const offset = ctx.offsets;
  const computedOffset = typeof offset === "string" ? { left: offset, right: offset, bottom: offset, top: offset } : offset;
  const rtl = ctx.dir === "rtl";
  const computedPlacement = placement.replace("-start", rtl ? "-right" : "-left").replace("-end", rtl ? "-left" : "-right");
  const isRighty = computedPlacement.includes("right");
  const isLefty = computedPlacement.includes("left");
  const styles = {
    position: "fixed",
    pointerEvents: ctx.count > 0 ? void 0 : "none",
    display: "flex",
    flexDirection: "column",
    "--gap": `${ctx.gap}px`,
    "--first-height": `${ctx.heights[0]?.height || 0}px`,
    zIndex: domQuery.MAX_Z_INDEX
  };
  let alignItems = "center";
  if (isRighty) alignItems = "flex-end";
  if (isLefty) alignItems = "flex-start";
  styles.alignItems = alignItems;
  if (computedPlacement.includes("top")) {
    const offset2 = computedOffset.top;
    styles.top = `max(env(safe-area-inset-top, 0px), ${offset2})`;
  }
  if (computedPlacement.includes("bottom")) {
    const offset2 = computedOffset.bottom;
    styles.bottom = `max(env(safe-area-inset-bottom, 0px), ${offset2})`;
  }
  if (!computedPlacement.includes("left")) {
    const offset2 = computedOffset.right;
    styles.insetInlineEnd = `calc(env(safe-area-inset-right, 0px) + ${offset2})`;
  }
  if (!computedPlacement.includes("right")) {
    const offset2 = computedOffset.left;
    styles.insetInlineStart = `calc(env(safe-area-inset-left, 0px) + ${offset2})`;
  }
  return styles;
}
function getPlacementStyle(ctx, visible) {
  const [side] = ctx.placement.split("-");
  const sibling = !ctx.frontmost;
  const overlap = !ctx.stacked;
  const styles = {
    position: "absolute",
    pointerEvents: "auto",
    "--opacity": "0",
    "--remove-delay": `${ctx.removeDelay}ms`,
    "--duration": `${ctx.type === "loading" ? Number.MAX_SAFE_INTEGER : ctx.duration}ms`,
    "--initial-height": `${ctx.height}px`,
    "--offset": `${ctx.offset}px`,
    "--index": ctx.index,
    "--z-index": ctx.zIndex,
    "--lift-amount": "calc(var(--lift) * var(--gap))",
    "--y": "100%",
    "--x": "0"
  };
  const assign = (overrides) => Object.assign(styles, overrides);
  if (side === "top") {
    assign({
      top: "0",
      "--sign": "-1",
      "--y": "-100%",
      "--lift": "1"
    });
  } else if (side === "bottom") {
    assign({
      bottom: "0",
      "--sign": "1",
      "--y": "100%",
      "--lift": "-1"
    });
  }
  if (ctx.mounted) {
    assign({
      "--y": "0",
      "--opacity": "1"
    });
    if (ctx.stacked) {
      assign({
        "--y": "calc(var(--lift) * var(--offset))",
        "--height": "var(--initial-height)"
      });
    }
  }
  if (!visible) {
    assign({
      "--opacity": "0",
      pointerEvents: "none"
    });
  }
  if (sibling && overlap) {
    assign({
      "--base-scale": "var(--index) * 0.05 + 1",
      "--y": "calc(var(--lift-amount) * var(--index))",
      "--scale": "calc(-1 * var(--base-scale))",
      "--height": "var(--first-height)"
    });
    if (!visible) {
      assign({
        "--y": "calc(var(--sign) * 40%)"
      });
    }
  }
  if (sibling && ctx.stacked && !visible) {
    assign({
      "--y": "calc(var(--lift) * var(--offset) + var(--lift) * -100%)"
    });
  }
  if (ctx.frontmost && !visible) {
    assign({
      "--y": "calc(var(--lift) * -100%)"
    });
  }
  return styles;
}
function getGhostBeforeStyle(ctx, visible) {
  const styles = {
    position: "absolute",
    inset: "0",
    scale: "1 2",
    pointerEvents: visible ? "none" : "auto"
  };
  const assign = (overrides) => Object.assign(styles, overrides);
  if (ctx.frontmost && !visible) {
    assign({
      height: "calc(var(--initial-height) + 80%)"
    });
  }
  return styles;
}
function getGhostAfterStyle(_ctx, _visible) {
  return {
    position: "absolute",
    left: "0",
    height: "calc(var(--gap) + 2px)",
    bottom: "100%",
    width: "100%"
  };
}

// src/toast-group.connect.ts
function groupConnect(serviceOrState, send, normalize) {
  function getState() {
    const result = core.isMachine(serviceOrState) ? serviceOrState.getState() : serviceOrState;
    return result;
  }
  function getToastsByPlacementImpl(placement) {
    return getToastsByPlacement(getState().context.toasts, placement);
  }
  function isVisible(id) {
    const toasts = getState().context.toasts;
    if (!toasts.length) return false;
    return !!toasts.find((toast) => toast.id == id);
  }
  function create(options) {
    const uid = `toast:${utils.uuid()}`;
    const id = options.id ? options.id : uid;
    if (isVisible(id)) return id;
    send({ type: "ADD_TOAST", toast: { ...options, id } });
    return id;
  }
  function update(id, options) {
    if (!isVisible(id)) return id;
    send({ type: "UPDATE_TOAST", id, toast: options });
    return id;
  }
  function upsert(options) {
    const { id } = options;
    const visible = id ? isVisible(id) : false;
    if (visible && id != null) {
      return update(id, options);
    } else {
      return create(options);
    }
  }
  function dismiss(id) {
    if (id == null) {
      send("DISMISS_ALL");
    } else if (isVisible(id)) {
      send({ type: "DISMISS_TOAST", id });
    }
  }
  return {
    getCount() {
      return getState().context.count;
    },
    getPlacements() {
      const toasts = getState().context.toasts;
      const placements = toasts.map((toast) => toast.state.context.placement);
      return Array.from(new Set(placements));
    },
    getToastsByPlacement: getToastsByPlacementImpl,
    isVisible,
    create,
    update,
    upsert,
    dismiss,
    remove(id) {
      if (id == null) {
        send("REMOVE_ALL");
      } else if (isVisible(id)) {
        send({ type: "REMOVE_TOAST", id });
      }
    },
    dismissByPlacement(placement) {
      const toasts = getToastsByPlacementImpl(placement);
      toasts.forEach((toast) => dismiss(toast.id));
    },
    loading(options) {
      return upsert({ ...options, type: "loading" });
    },
    success(options) {
      return upsert({ ...options, type: "success" });
    },
    error(options) {
      return upsert({ ...options, type: "error" });
    },
    promise(promise, options, shared = {}) {
      const id = upsert({ ...shared, ...options.loading, type: "loading" });
      utils.runIfFn(promise).then((response) => {
        const successOptions = utils.runIfFn(options.success, response);
        upsert({ ...shared, ...successOptions, id, type: "success" });
      }).catch((error) => {
        const errorOptions = utils.runIfFn(options.error, error);
        upsert({ ...shared, ...errorOptions, id, type: "error" });
      }).finally(() => {
        options.finally?.();
      });
      return id;
    },
    pause(id) {
      if (id == null) {
        send("PAUSE_ALL");
      } else if (isVisible(id)) {
        send({ type: "PAUSE_TOAST", id });
      }
    },
    resume(id) {
      if (id == null) {
        send("RESUME_ALL");
      } else if (isVisible(id)) {
        send({ type: "RESUME_TOAST", id });
      }
    },
    getGroupProps(options) {
      const { placement, label = "Notifications" } = options;
      const state = getState();
      const hotkeyLabel = state.context.hotkey.join("+").replace(/Key/g, "").replace(/Digit/g, "");
      const [side, align = "center"] = placement.split("-");
      return normalize.element({
        ...parts.group.attrs,
        dir: state.context.dir,
        tabIndex: -1,
        "aria-label": `${placement} ${label} ${hotkeyLabel}`,
        id: dom.getRegionId(placement),
        "data-placement": placement,
        "data-side": side,
        "data-align": align,
        "aria-live": "polite",
        role: "region",
        style: getGroupPlacementStyle(state.context, placement),
        onMouseMove() {
          send({ type: "REGION.POINTER_ENTER", placement });
        },
        onMouseLeave() {
          send({ type: "REGION.POINTER_LEAVE", placement });
        },
        onFocus(event) {
          send({ type: "REGION.FOCUS", target: event.relatedTarget });
        },
        onBlur(event) {
          if (state.context.isFocusWithin && !domQuery.contains(event.currentTarget, event.relatedTarget)) {
            send({ type: "REGION.BLUR" });
          }
        }
      });
    },
    subscribe(fn) {
      const state = getState();
      return core.subscribe(state.context.toasts, () => {
        const toasts = getToastsByPlacementImpl(state.context.placement);
        const contexts = toasts.map((toast) => toast.getState().context);
        fn(contexts);
      });
    }
  };
}
var { not, and, or } = core.guards;
function createToastMachine(options) {
  const { type = "info", duration, id = "1", placement = "bottom", removeDelay = 200, ...restProps } = options;
  const ctx = utils.compact(restProps);
  const computedDuration = getToastDuration(duration, type);
  return core.createMachine(
    {
      id,
      context: {
        id,
        type,
        remaining: computedDuration,
        duration: computedDuration,
        removeDelay,
        createdAt: Date.now(),
        placement,
        ...ctx,
        height: 0,
        offset: 0,
        frontmost: false,
        mounted: false,
        index: -1,
        zIndex: 0
      },
      initial: type === "loading" ? "visible:persist" : "visible",
      on: {
        UPDATE: [
          {
            guard: and("hasTypeChanged", "isChangingToLoading"),
            target: "visible:persist",
            actions: ["setContext"]
          },
          {
            guard: or("hasDurationChanged", "hasTypeChanged"),
            target: "visible:updating",
            actions: ["setContext"]
          },
          {
            actions: ["setContext"]
          }
        ],
        MEASURE: {
          actions: ["measureHeight"]
        }
      },
      entry: ["invokeOnVisible"],
      activities: ["trackHeight"],
      states: {
        "visible:updating": {
          tags: ["visible", "updating"],
          after: {
            0: "visible"
          }
        },
        "visible:persist": {
          tags: ["visible", "paused"],
          on: {
            RESUME: {
              guard: not("isLoadingType"),
              target: "visible",
              actions: ["setCreatedAt"]
            },
            DISMISS: "dismissing"
          }
        },
        visible: {
          tags: ["visible"],
          after: {
            VISIBLE_DURATION: "dismissing"
          },
          on: {
            DISMISS: "dismissing",
            PAUSE: {
              target: "visible:persist",
              actions: "setRemainingDuration"
            }
          }
        },
        dismissing: {
          entry: "invokeOnDismiss",
          after: {
            REMOVE_DELAY: {
              target: "unmounted",
              actions: "notifyParentToRemove"
            }
          }
        },
        unmounted: {
          entry: "invokeOnUnmount",
          type: "final"
        }
      }
    },
    {
      activities: {
        trackHeight(ctx2, _evt, { self }) {
          let cleanup;
          domQuery.raf(() => {
            const rootEl = dom.getRootEl(ctx2);
            if (!rootEl) return;
            ctx2.mounted = true;
            const ghosts = domQuery.queryAll(rootEl, "[data-ghost]");
            utils.warn(
              ghosts.length !== 2,
              "[toast] No ghost element found in toast. Render the `ghostBefore` and `ghostAfter` elements"
            );
            const syncHeight = () => {
              const originalHeight = rootEl.style.height;
              rootEl.style.height = "auto";
              const newHeight = rootEl.getBoundingClientRect().height;
              rootEl.style.height = originalHeight;
              ctx2.height = newHeight;
              self.sendParent({ type: "UPDATE_HEIGHT", id: self.id, height: newHeight, placement: ctx2.placement });
            };
            syncHeight();
            const win = dom.getWin(ctx2);
            const observer = new win.MutationObserver(syncHeight);
            observer.observe(rootEl, { childList: true, subtree: true, characterData: true });
            cleanup = () => observer.disconnect();
          });
          return () => cleanup?.();
        }
      },
      guards: {
        isChangingToLoading: (_, evt) => evt.toast?.type === "loading",
        isLoadingType: (ctx2) => ctx2.type === "loading",
        hasTypeChanged: (ctx2, evt) => evt.toast?.type != null && evt.toast.type !== ctx2.type,
        hasDurationChanged: (ctx2, evt) => evt.toast?.duration != null && evt.toast.duration !== ctx2.duration
      },
      delays: {
        VISIBLE_DURATION: (ctx2) => ctx2.remaining,
        REMOVE_DELAY: (ctx2) => ctx2.removeDelay
      },
      actions: {
        measureHeight(ctx2, _evt, { self }) {
          domQuery.raf(() => {
            const rootEl = dom.getRootEl(ctx2);
            if (!rootEl) return;
            ctx2.mounted = true;
            const originalHeight = rootEl.style.height;
            rootEl.style.height = "auto";
            const newHeight = rootEl.getBoundingClientRect().height;
            rootEl.style.height = originalHeight;
            ctx2.height = newHeight;
            self.sendParent({ type: "UPDATE_HEIGHT", id: self.id, height: newHeight, placement: ctx2.placement });
          });
        },
        setRemainingDuration(ctx2) {
          ctx2.remaining -= Date.now() - ctx2.createdAt;
        },
        setCreatedAt(ctx2) {
          ctx2.createdAt = Date.now();
        },
        notifyParentToRemove(_ctx, _evt, { self }) {
          self.sendParent({ type: "REMOVE_TOAST", id: self.id });
        },
        invokeOnDismiss(ctx2) {
          ctx2.onStatusChange?.({ status: "dismissing" });
        },
        invokeOnUnmount(ctx2) {
          ctx2.onStatusChange?.({ status: "unmounted" });
        },
        invokeOnVisible(ctx2) {
          ctx2.onStatusChange?.({ status: "visible" });
        },
        setContext(ctx2, evt) {
          const duration2 = evt.toast?.duration;
          const type2 = evt.toast?.type ?? ctx2.type;
          const computedDuration2 = getToastDuration(duration2, type2);
          Object.assign(ctx2, {
            ...evt.toast,
            duration: computedDuration2,
            remaining: computedDuration2
          });
        }
      }
    }
  );
}

// src/toast-group.machine.ts
function groupMachine(userContext) {
  const ctx = utils.compact(userContext);
  return core.createMachine(
    {
      id: "toaster",
      initial: ctx.overlap ? "overlap" : "stack",
      context: {
        dir: "ltr",
        max: Number.MAX_SAFE_INTEGER,
        gap: 16,
        pauseOnPageIdle: false,
        hotkey: ["altKey", "KeyT"],
        offsets: "1rem",
        placement: "bottom",
        removeDelay: 200,
        ...ctx,
        toasts: [],
        lastFocusedEl: null,
        isFocusWithin: false,
        heights: []
      },
      computed: {
        count: (ctx2) => ctx2.toasts.length
      },
      activities: ["trackDocumentVisibility", "trackHotKeyPress"],
      watch: {
        toasts: ["collapsedIfEmpty", "setDismissableBranch"]
      },
      exit: ["removeToasts", "clearDismissableBranch", "clearLastFocusedEl"],
      on: {
        PAUSE_TOAST: {
          actions: ["pauseToast"]
        },
        PAUSE_ALL: {
          actions: ["pauseToasts"]
        },
        RESUME_TOAST: {
          actions: ["resumeToast"]
        },
        RESUME_ALL: {
          actions: ["resumeToasts"]
        },
        ADD_TOAST: {
          guard: "isWithinRange",
          actions: ["createToast", "syncToastIndex"]
        },
        UPDATE_TOAST: {
          actions: ["updateToast"]
        },
        DISMISS_TOAST: {
          actions: ["dismissToast"]
        },
        DISMISS_ALL: {
          actions: ["dismissToasts"]
        },
        REMOVE_TOAST: {
          actions: ["removeToast", "syncToastIndex", "syncToastOffset"]
        },
        REMOVE_ALL: {
          actions: ["removeToasts"]
        },
        UPDATE_HEIGHT: {
          actions: ["syncHeights", "syncToastOffset"]
        },
        "DOC.HOTKEY": {
          actions: ["focusRegionEl"]
        },
        "REGION.BLUR": [
          {
            guard: "isOverlapping",
            target: "overlap",
            actions: ["resumeToasts", "restoreLastFocusedEl"]
          },
          {
            actions: ["resumeToasts", "restoreLastFocusedEl"]
          }
        ]
      },
      states: {
        stack: {
          entry: ["expandToasts"],
          on: {
            "REGION.POINTER_LEAVE": [
              {
                guard: "isOverlapping",
                target: "overlap",
                actions: ["resumeToasts"]
              },
              {
                actions: ["resumeToasts"]
              }
            ],
            "REGION.OVERLAP": {
              target: "overlap"
            },
            "REGION.FOCUS": {
              actions: ["setLastFocusedEl", "pauseToasts"]
            },
            "REGION.POINTER_ENTER": {
              actions: ["pauseToasts"]
            }
          }
        },
        overlap: {
          entry: ["collapseToasts"],
          on: {
            "REGION.STACK": {
              target: "stack"
            },
            "REGION.POINTER_ENTER": {
              target: "stack",
              actions: ["pauseToasts"]
            },
            "REGION.FOCUS": {
              target: "stack",
              actions: ["setLastFocusedEl", "pauseToasts"]
            }
          }
        }
      }
    },
    {
      guards: {
        isWithinRange: (ctx2) => ctx2.toasts.length < ctx2.max,
        isOverlapping: (ctx2) => !!ctx2.overlap
      },
      activities: {
        trackHotKeyPress(ctx2, _evt, { send }) {
          const handleKeyDown = (event) => {
            const isHotkeyPressed = ctx2.hotkey.every((key) => event[key] || event.code === key);
            if (!isHotkeyPressed) return;
            send({ type: "DOC.HOTKEY" });
          };
          return domEvent.addDomEvent(document, "keydown", handleKeyDown, { capture: true });
        },
        trackDocumentVisibility(ctx2, _evt, { send }) {
          if (!ctx2.pauseOnPageIdle) return;
          const doc = dom.getDoc(ctx2);
          return domEvent.addDomEvent(doc, "visibilitychange", () => {
            send(doc.visibilityState === "hidden" ? "PAUSE_ALL" : "RESUME_ALL");
          });
        }
      },
      actions: {
        setDismissableBranch(ctx2) {
          const currentToasts = getToastsByPlacement(ctx2.toasts, ctx2.placement);
          const hasToasts = currentToasts.length > 0;
          if (!hasToasts) {
            ctx2._cleanup?.();
            return;
          }
          if (hasToasts && ctx2._cleanup) {
            return;
          }
          const groupEl = () => dom.getRegionEl(ctx2, ctx2.placement);
          ctx2._cleanup = dismissable.trackDismissableBranch(groupEl, { defer: true });
        },
        clearDismissableBranch(ctx2) {
          ctx2._cleanup?.();
        },
        focusRegionEl(ctx2) {
          queueMicrotask(() => {
            dom.getRegionEl(ctx2, ctx2.placement)?.focus();
          });
        },
        expandToasts(ctx2) {
          each(ctx2, (toast) => {
            toast.state.context.stacked = true;
          });
        },
        collapseToasts(ctx2) {
          each(ctx2, (toast) => {
            toast.state.context.stacked = false;
          });
        },
        collapsedIfEmpty(ctx2, _evt, { send }) {
          if (!ctx2.overlap || ctx2.toasts.length > 1) return;
          send("REGION.OVERLAP");
        },
        pauseToast(_ctx, evt, { self }) {
          self.sendChild("PAUSE", evt.id);
        },
        pauseToasts(ctx2) {
          ctx2.toasts.forEach((toast) => toast.send("PAUSE"));
        },
        resumeToast(_ctx, evt, { self }) {
          self.sendChild("RESUME", evt.id);
        },
        resumeToasts(ctx2) {
          ctx2.toasts.forEach((toast) => toast.send("RESUME"));
        },
        measureToasts(ctx2) {
          ctx2.toasts.forEach((toast) => toast.send("MEASURE"));
        },
        createToast(ctx2, evt, { self, getState }) {
          const options = {
            placement: ctx2.placement,
            duration: ctx2.duration,
            removeDelay: ctx2.removeDelay,
            ...evt.toast,
            dir: ctx2.dir,
            getRootNode: ctx2.getRootNode,
            stacked: getState().matches("stack")
          };
          const toast = createToastMachine(options);
          const actor = self.spawn(toast);
          ctx2.toasts = [actor, ...ctx2.toasts];
        },
        updateToast(_ctx, evt, { self }) {
          self.sendChild({ type: "UPDATE", toast: evt.toast }, evt.id);
        },
        dismissToast(_ctx, evt, { self }) {
          self.sendChild("DISMISS", evt.id);
        },
        dismissToasts(ctx2) {
          ctx2.toasts.forEach((toast) => toast.send("DISMISS"));
        },
        removeToast(ctx2, evt, { self }) {
          self.stopChild(evt.id);
          ctx2.toasts = ctx2.toasts.filter((toast) => toast.id !== evt.id);
          ctx2.heights = ctx2.heights.filter((height) => height.id !== evt.id);
        },
        removeToasts(ctx2, _evt, { self }) {
          ctx2.toasts.forEach((toast) => self.stopChild(toast.id));
          ctx2.toasts = [];
          ctx2.heights = [];
        },
        syncHeights(ctx2, evt) {
          const existing = ctx2.heights.find((height) => height.id === evt.id);
          if (existing) {
            existing.height = evt.height;
            existing.placement = evt.placement;
          } else {
            const newHeight = { id: evt.id, height: evt.height, placement: evt.placement };
            ctx2.heights = [newHeight, ...ctx2.heights];
          }
        },
        syncToastIndex(ctx2) {
          each(ctx2, (toast, index, toasts) => {
            toast.state.context.index = index;
            toast.state.context.frontmost = index === 0;
            toast.state.context.zIndex = toasts.length - index;
          });
        },
        syncToastOffset(ctx2, evt) {
          const placement = evt.placement ?? ctx2.placement;
          each({ ...ctx2, placement }, (toast) => {
            const heightIndex = Math.max(
              ctx2.heights.findIndex((height) => height.id === toast.id),
              0
            );
            const toastsHeightBefore = ctx2.heights.reduce((prev, curr, reducerIndex) => {
              if (reducerIndex >= heightIndex) return prev;
              return prev + curr.height;
            }, 0);
            toast.state.context.offset = heightIndex * ctx2.gap + toastsHeightBefore;
          });
        },
        setLastFocusedEl(ctx2, evt) {
          if (ctx2.isFocusWithin || !evt.target) return;
          ctx2.isFocusWithin = true;
          ctx2.lastFocusedEl = core.ref(evt.target);
        },
        restoreLastFocusedEl(ctx2) {
          ctx2.isFocusWithin = false;
          if (!ctx2.lastFocusedEl) return;
          ctx2.lastFocusedEl.focus({ preventScroll: true });
          ctx2.lastFocusedEl = null;
        },
        clearLastFocusedEl(ctx2) {
          if (!ctx2.lastFocusedEl) return;
          ctx2.lastFocusedEl.focus({ preventScroll: true });
          ctx2.lastFocusedEl = null;
          ctx2.isFocusWithin = false;
        }
      }
    }
  );
}
function each(ctx, fn) {
  const currentToasts = getToastsByPlacement(ctx.toasts, ctx.placement);
  currentToasts.forEach(fn);
}
function connect(state, send, normalize) {
  const visible = state.hasTag("visible");
  const paused = state.hasTag("paused");
  const placement = state.context.placement;
  const type = state.context.type;
  const [side, align = "center"] = placement.split("-");
  return {
    type,
    title: state.context.title,
    description: state.context.description,
    placement,
    visible,
    paused,
    pause() {
      send("PAUSE");
    },
    resume() {
      send("RESUME");
    },
    dismiss() {
      send("DISMISS");
    },
    getRootProps() {
      return normalize.element({
        ...parts.root.attrs,
        dir: state.context.dir,
        id: dom.getRootId(state.context),
        "data-state": visible ? "open" : "closed",
        "data-type": type,
        "data-placement": placement,
        "data-align": align,
        "data-side": side,
        "data-mounted": domQuery.dataAttr(state.context.mounted),
        "data-paused": domQuery.dataAttr(paused),
        "data-first": domQuery.dataAttr(state.context.frontmost),
        "data-sibling": domQuery.dataAttr(!state.context.frontmost),
        "data-stack": domQuery.dataAttr(state.context.stacked),
        "data-overlap": domQuery.dataAttr(!state.context.stacked),
        role: "status",
        "aria-atomic": "true",
        "aria-describedby": state.context.description ? dom.getDescriptionId(state.context) : void 0,
        "aria-labelledby": state.context.title ? dom.getTitleId(state.context) : void 0,
        tabIndex: 0,
        style: getPlacementStyle(state.context, visible),
        onKeyDown(event) {
          if (event.defaultPrevented) return;
          if (event.key == "Escape") {
            send("DISMISS");
            event.preventDefault();
          }
        }
      });
    },
    /* Leave a ghost div to avoid setting hover to false when transitioning out */
    getGhostBeforeProps() {
      return normalize.element({
        "data-ghost": "before",
        style: getGhostBeforeStyle(state.context, visible)
      });
    },
    /* Needed to avoid setting hover to false when in between toasts */
    getGhostAfterProps() {
      return normalize.element({
        "data-ghost": "after",
        style: getGhostAfterStyle()
      });
    },
    getTitleProps() {
      return normalize.element({
        ...parts.title.attrs,
        id: dom.getTitleId(state.context)
      });
    },
    getDescriptionProps() {
      return normalize.element({
        ...parts.description.attrs,
        id: dom.getDescriptionId(state.context)
      });
    },
    getActionTriggerProps() {
      return normalize.button({
        ...parts.actionTrigger.attrs,
        type: "button",
        onClick(event) {
          if (event.defaultPrevented) return;
          state.context.action?.onClick?.();
          send("DISMISS");
        }
      });
    },
    getCloseTriggerProps() {
      return normalize.button({
        id: dom.getCloseTriggerId(state.context),
        ...parts.closeTrigger.attrs,
        type: "button",
        "aria-label": "Dismiss notification",
        onClick(event) {
          if (event.defaultPrevented) return;
          send("DISMISS");
        }
      });
    }
  };
}

// src/index.ts
var group = {
  connect: groupConnect,
  machine: groupMachine
};

exports.anatomy = anatomy;
exports.connect = connect;
exports.createMachine = createToastMachine;
exports.group = group;




© 2015 - 2025 Weber Informatics LLC | Privacy Policy