New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

solid-sonner

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

solid-sonner - npm Package Compare versions

Comparing version
0.2.8
to
0.3.0
+666
-387
dist/dev.js

@@ -1,3 +0,3 @@

import { delegateEvents, createComponent, insert, use, setAttribute, effect, className, style, template, addEventListener, memo } from 'solid-js/web';
import { mergeProps, createSignal, onMount, onCleanup, createEffect, on, Show, For } from 'solid-js';
import { delegateEvents, insert, createComponent, use, setAttribute, effect, className, style, memo, template } from 'solid-js/web';
import { createSignal, onMount, onCleanup, mergeProps, createMemo, createEffect, For, Show, on } from 'solid-js';
import { createStore, produce, reconcile } from 'solid-js/store';

@@ -30,4 +30,4 @@

// src/styles.css
styleInject(':where(html[dir=ltr]),\n:where([data-sonner-toaster][dir=ltr]) {\n --toast-icon-margin-start: -3px;\n --toast-icon-margin-end: 4px;\n --toast-svg-margin-start: -1px;\n --toast-svg-margin-end: 0px;\n --toast-button-margin-start: auto;\n --toast-button-margin-end: 0;\n --toast-close-button-start: 0;\n --toast-close-button-end: unset;\n --toast-close-button-transform: translate(-35%, -35%);\n}\n:where(html[dir=rtl]),\n:where([data-sonner-toaster][dir=rtl]) {\n --toast-icon-margin-start: 4px;\n --toast-icon-margin-end: -3px;\n --toast-svg-margin-start: 0px;\n --toast-svg-margin-end: -1px;\n --toast-button-margin-start: 0;\n --toast-button-margin-end: auto;\n --toast-close-button-start: unset;\n --toast-close-button-end: 0;\n --toast-close-button-transform: translate(35%, -35%);\n}\n:where([data-sonner-toaster]) {\n position: fixed;\n width: var(--width);\n font-family:\n ui-sans-serif,\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n Segoe UI,\n Roboto,\n Helvetica Neue,\n Arial,\n Noto Sans,\n sans-serif,\n Apple Color Emoji,\n Segoe UI Emoji,\n Segoe UI Symbol,\n Noto Color Emoji;\n --gray1: hsl(0, 0%, 99%);\n --gray2: hsl(0, 0%, 97.3%);\n --gray3: hsl(0, 0%, 95.1%);\n --gray4: hsl(0, 0%, 93%);\n --gray5: hsl(0, 0%, 90.9%);\n --gray6: hsl(0, 0%, 88.7%);\n --gray7: hsl(0, 0%, 85.8%);\n --gray8: hsl(0, 0%, 78%);\n --gray9: hsl(0, 0%, 56.1%);\n --gray10: hsl(0, 0%, 52.3%);\n --gray11: hsl(0, 0%, 43.5%);\n --gray12: hsl(0, 0%, 9%);\n --border-radius: 8px;\n box-sizing: border-box;\n padding: 0;\n margin: 0;\n list-style: none;\n outline: none;\n z-index: 999999999;\n}\n:where([data-sonner-toaster][data-x-position=right]) {\n right: max(var(--offset), env(safe-area-inset-right));\n}\n:where([data-sonner-toaster][data-x-position=left]) {\n left: max(var(--offset), env(safe-area-inset-left));\n}\n:where([data-sonner-toaster][data-x-position=center]) {\n left: 50%;\n transform: translateX(-50%);\n}\n:where([data-sonner-toaster][data-y-position=top]) {\n top: max(var(--offset), env(safe-area-inset-top));\n}\n:where([data-sonner-toaster][data-y-position=bottom]) {\n bottom: max(var(--offset), env(safe-area-inset-bottom));\n}\n:where([data-sonner-toast]) {\n --y: translateY(100%);\n --lift-amount: calc(var(--lift) * var(--gap));\n z-index: var(--z-index);\n position: absolute;\n opacity: 0;\n transform: var(--y);\n filter: blur(0);\n touch-action: none;\n transition:\n transform 400ms,\n opacity 400ms,\n height 400ms,\n box-shadow 200ms;\n box-sizing: border-box;\n outline: none;\n overflow-wrap: anywhere;\n}\n:where([data-sonner-toast][data-styled=true]) {\n padding: 16px;\n background: var(--normal-bg);\n border: 1px solid var(--normal-border);\n color: var(--normal-text);\n border-radius: var(--border-radius);\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1);\n width: var(--width);\n font-size: 13px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n:where([data-sonner-toast]:focus-visible) {\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1), 0 0 0 2px rgba(0, 0, 0, 0.2);\n}\n:where([data-sonner-toast][data-y-position=top]) {\n top: 0;\n --y: translateY(-100%);\n --lift: 1;\n --lift-amount: calc(1 * var(--gap));\n}\n:where([data-sonner-toast][data-y-position=bottom]) {\n bottom: 0;\n --y: translateY(100%);\n --lift: -1;\n --lift-amount: calc(var(--lift) * var(--gap));\n}\n:where([data-sonner-toast]) :where([data-description]) {\n font-weight: 400;\n line-height: 1.4;\n color: inherit;\n}\n:where([data-sonner-toast]) :where([data-title]) {\n font-weight: 500;\n line-height: 1.5;\n color: inherit;\n}\n:where([data-sonner-toast]) :where([data-icon]) {\n display: flex;\n height: 16px;\n width: 16px;\n position: relative;\n justify-content: flex-start;\n align-items: center;\n flex-shrink: 0;\n margin-left: var(--toast-icon-margin-start);\n margin-right: var(--toast-icon-margin-end);\n}\n:where([data-sonner-toast][data-promise=true]) :where([data-icon]) > svg {\n opacity: 0;\n transform: scale(0.8);\n transform-origin: center;\n animation: sonner-fade-in 300ms ease forwards;\n}\n:where([data-sonner-toast]) :where([data-icon]) > * {\n flex-shrink: 0;\n}\n:where([data-sonner-toast]) :where([data-icon]) svg {\n margin-left: var(--toast-svg-margin-start);\n margin-right: var(--toast-svg-margin-end);\n}\n:where([data-sonner-toast]) :where([data-content]) {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n[data-sonner-toast][data-styled=true] [data-button] {\n border-radius: 4px;\n padding-left: 8px;\n padding-right: 8px;\n height: 24px;\n font-size: 12px;\n color: var(--normal-bg);\n background: var(--normal-text);\n margin-left: var(--toast-button-margin-start);\n margin-right: var(--toast-button-margin-end);\n border: none;\n cursor: pointer;\n outline: none;\n display: flex;\n align-items: center;\n flex-shrink: 0;\n transition: opacity 400ms, box-shadow 200ms;\n}\n:where([data-sonner-toast]) :where([data-button]):focus-visible {\n box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.4);\n}\n:where([data-sonner-toast]) :where([data-button]):first-of-type {\n margin-left: var(--toast-button-margin-start);\n margin-right: var(--toast-button-margin-end);\n}\n:where([data-sonner-toast]) :where([data-cancel]) {\n color: var(--normal-text);\n background: rgba(0, 0, 0, 0.08);\n}\n:where([data-sonner-toast][data-theme=dark]) :where([data-cancel]) {\n background: rgba(255, 255, 255, 0.3);\n}\n:where([data-sonner-toast]) :where([data-close-button]) {\n position: absolute;\n left: var(--toast-close-button-start);\n right: var(--toast-close-button-end);\n top: 0;\n height: 20px;\n width: 20px;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 0;\n background: var(--gray1);\n color: var(--gray12);\n border: 1px solid var(--gray4);\n transform: var(--toast-close-button-transform);\n border-radius: 50%;\n cursor: pointer;\n z-index: 1;\n transition:\n opacity 100ms,\n background 200ms,\n border-color 200ms;\n}\n:where([data-sonner-toast]) :where([data-close-button]):focus-visible {\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1), 0 0 0 2px rgba(0, 0, 0, 0.2);\n}\n:where([data-sonner-toast]) :where([data-disabled=true]) {\n cursor: not-allowed;\n}\n:where([data-sonner-toast]):hover :where([data-close-button]):hover {\n background: var(--gray2);\n border-color: var(--gray5);\n}\n:where([data-sonner-toast][data-swiping=true])::before {\n content: "";\n position: absolute;\n left: 0;\n right: 0;\n height: 100%;\n z-index: -1;\n}\n:where([data-sonner-toast][data-y-position=top][data-swiping=true])::before {\n bottom: 50%;\n transform: scaleY(3) translateY(50%);\n}\n:where([data-sonner-toast][data-y-position=bottom][data-swiping=true])::before {\n top: 50%;\n transform: scaleY(3) translateY(-50%);\n}\n:where([data-sonner-toast][data-swiping=false][data-removed=true])::before {\n content: "";\n position: absolute;\n inset: 0;\n transform: scaleY(2);\n}\n:where([data-sonner-toast])::after {\n content: "";\n position: absolute;\n left: 0;\n height: calc(var(--gap) + 1px);\n bottom: 100%;\n width: 100%;\n}\n:where([data-sonner-toast][data-mounted=true]) {\n --y: translateY(0);\n opacity: 1;\n}\n:where([data-sonner-toast][data-expanded=false][data-front=false]) {\n --scale: var(--toasts-before) * 0.05 + 1;\n --y: translateY(calc(var(--lift-amount) * var(--toasts-before))) scale(calc(-1 * var(--scale)));\n height: var(--front-toast-height);\n}\n:where([data-sonner-toast]) > * {\n transition: opacity 400ms;\n}\n:where([data-sonner-toast][data-expanded=false][data-front=false][data-styled=true]) > * {\n opacity: 0;\n}\n:where([data-sonner-toast][data-visible=false]) {\n opacity: 0;\n pointer-events: none;\n}\n:where([data-sonner-toast][data-mounted=true][data-expanded=true]) {\n --y: translateY(calc(var(--lift) * var(--offset)));\n height: var(--initial-height);\n}\n:where([data-sonner-toast][data-removed=true][data-front=true][data-swipe-out=false]) {\n --y: translateY(calc(var(--lift) * -100%));\n opacity: 0;\n}\n:where([data-sonner-toast][data-removed=true][data-front=false][data-swipe-out=false][data-expanded=true]) {\n --y: translateY(calc(var(--lift) * var(--offset) + var(--lift) * -100%));\n opacity: 0;\n}\n:where([data-sonner-toast][data-removed=true][data-front=false][data-swipe-out=false][data-expanded=false]) {\n --y: translateY(40%);\n opacity: 0;\n transition: transform 500ms, opacity 200ms;\n}\n:where([data-sonner-toast][data-removed=true][data-front=false])::before {\n height: calc(var(--initial-height) + 20%);\n}\n[data-sonner-toast][data-swiping=true] {\n transform: var(--y) translateY(var(--swipe-amount, 0px));\n transition: none;\n}\n[data-sonner-toast][data-swipe-out=true][data-y-position=bottom],\n[data-sonner-toast][data-swipe-out=true][data-y-position=top] {\n animation: swipe-out 200ms ease-out forwards;\n}\n@keyframes swipe-out {\n from {\n transform: translateY(calc(var(--lift) * var(--offset) + var(--swipe-amount)));\n opacity: 1;\n }\n to {\n transform: translateY(calc(var(--lift) * var(--offset) + var(--swipe-amount) + var(--lift) * -100%));\n opacity: 0;\n }\n}\n@media (max-width: 600px) {\n [data-sonner-toaster] {\n position: fixed;\n --mobile-offset: 16px;\n right: var(--mobile-offset);\n left: var(--mobile-offset);\n width: 100%;\n }\n [data-sonner-toaster] [data-sonner-toast] {\n left: 0;\n right: 0;\n width: calc(100% - var(--mobile-offset) * 2);\n }\n [data-sonner-toaster][data-x-position=left] {\n left: var(--mobile-offset);\n }\n [data-sonner-toaster][data-y-position=bottom] {\n bottom: 20px;\n }\n [data-sonner-toaster][data-y-position=top] {\n top: 20px;\n }\n [data-sonner-toaster][data-x-position=center] {\n left: var(--mobile-offset);\n right: var(--mobile-offset);\n transform: none;\n }\n}\n[data-sonner-toaster][data-theme=light] {\n --normal-bg: #fff;\n --normal-border: var(--gray4);\n --normal-text: var(--gray12);\n --success-bg: hsl(143, 85%, 96%);\n --success-border: hsl(145, 92%, 91%);\n --success-text: hsl(140, 100%, 27%);\n --info-bg: hsl(208, 100%, 97%);\n --info-border: hsl(221, 91%, 91%);\n --info-text: hsl(210, 92%, 45%);\n --warning-bg: hsl(49, 100%, 97%);\n --warning-border: hsl(49, 91%, 91%);\n --warning-text: hsl(31, 92%, 45%);\n --error-bg: hsl(359, 100%, 97%);\n --error-border: hsl(359, 100%, 94%);\n --error-text: hsl(360, 100%, 45%);\n}\n[data-sonner-toaster][data-theme=light] [data-sonner-toast][data-invert=true] {\n --normal-bg: #000;\n --normal-border: hsl(0, 0%, 20%);\n --normal-text: var(--gray1);\n}\n[data-sonner-toaster][data-theme=dark] [data-sonner-toast][data-invert=true] {\n --normal-bg: #fff;\n --normal-border: var(--gray3);\n --normal-text: var(--gray12);\n}\n[data-sonner-toaster][data-theme=dark] {\n --normal-bg: #000;\n --normal-border: hsl(0, 0%, 20%);\n --normal-text: var(--gray1);\n --success-bg: hsl(150, 100%, 6%);\n --success-border: hsl(147, 100%, 12%);\n --success-text: hsl(150, 86%, 65%);\n --info-bg: hsl(215, 100%, 6%);\n --info-border: hsl(223, 100%, 12%);\n --info-text: hsl(216, 87%, 65%);\n --warning-bg: hsl(64, 100%, 6%);\n --warning-border: hsl(60, 100%, 12%);\n --warning-text: hsl(46, 87%, 65%);\n --error-bg: hsl(358, 76%, 10%);\n --error-border: hsl(357, 89%, 16%);\n --error-text: hsl(358, 100%, 81%);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=success] {\n background: var(--success-bg);\n border-color: var(--success-border);\n color: var(--success-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=success] [data-close-button] {\n background: var(--success-bg);\n border-color: var(--success-border);\n color: var(--success-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=info] {\n background: var(--info-bg);\n border-color: var(--info-border);\n color: var(--info-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=info] [data-close-button] {\n background: var(--info-bg);\n border-color: var(--info-border);\n color: var(--info-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=warning] {\n background: var(--warning-bg);\n border-color: var(--warning-border);\n color: var(--warning-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=warning] [data-close-button] {\n background: var(--warning-bg);\n border-color: var(--warning-border);\n color: var(--warning-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=error] {\n background: var(--error-bg);\n border-color: var(--error-border);\n color: var(--error-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=error] [data-close-button] {\n background: var(--error-bg);\n border-color: var(--error-border);\n color: var(--error-text);\n}\n.sonner-loading-wrapper {\n --size: 16px;\n height: var(--size);\n width: var(--size);\n position: absolute;\n inset: 0;\n z-index: 10;\n}\n.sonner-loading-wrapper[data-visible=false] {\n transform-origin: center;\n animation: sonner-fade-out 0.2s ease forwards;\n}\n.sonner-spinner {\n position: relative;\n top: 50%;\n left: 50%;\n height: var(--size);\n width: var(--size);\n}\n.sonner-loading-bar {\n animation: sonner-spin 1.2s linear infinite;\n background: var(--gray11);\n border-radius: 6px;\n height: 8%;\n left: -10%;\n position: absolute;\n top: -3.9%;\n width: 24%;\n}\n.sonner-loading-bar:nth-child(1) {\n animation-delay: -1.2s;\n transform: rotate(0.0001deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(2) {\n animation-delay: -1.1s;\n transform: rotate(30deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(3) {\n animation-delay: -1s;\n transform: rotate(60deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(4) {\n animation-delay: -0.9s;\n transform: rotate(90deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(5) {\n animation-delay: -0.8s;\n transform: rotate(120deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(6) {\n animation-delay: -0.7s;\n transform: rotate(150deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(7) {\n animation-delay: -0.6s;\n transform: rotate(180deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(8) {\n animation-delay: -0.5s;\n transform: rotate(210deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(9) {\n animation-delay: -0.4s;\n transform: rotate(240deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(10) {\n animation-delay: -0.3s;\n transform: rotate(270deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(11) {\n animation-delay: -0.2s;\n transform: rotate(300deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(12) {\n animation-delay: -0.1s;\n transform: rotate(330deg) translate(146%);\n}\n@keyframes sonner-fade-in {\n 0% {\n opacity: 0;\n transform: scale(0.8);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n}\n@keyframes sonner-fade-out {\n 0% {\n opacity: 1;\n transform: scale(1);\n }\n 100% {\n opacity: 0;\n transform: scale(0.8);\n }\n}\n@keyframes sonner-spin {\n 0% {\n opacity: 1;\n }\n 100% {\n opacity: 0.15;\n }\n}\n@media (prefers-reduced-motion) {\n [data-sonner-toast],\n [data-sonner-toast] > *,\n .sonner-loading-bar {\n transition: none !important;\n animation: none !important;\n }\n}\n.sonner-loader {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n transform-origin: center;\n transition: opacity 200ms, transform 200ms;\n}\n.sonner-loader[data-visible=false] {\n opacity: 0;\n transform: scale(0.8) translate(-50%, -50%);\n}\n');
var _tmpl$ = /* @__PURE__ */ template(`<div class=sonner-loading-wrapper><div class=sonner-spinner>`);
styleInject('html[dir=ltr],\n[data-sonner-toaster][dir=ltr] {\n --toast-icon-margin-start: -3px;\n --toast-icon-margin-end: 4px;\n --toast-svg-margin-start: -1px;\n --toast-svg-margin-end: 0px;\n --toast-button-margin-start: auto;\n --toast-button-margin-end: 0;\n --toast-close-button-start: 0;\n --toast-close-button-end: unset;\n --toast-close-button-transform: translate(-35%, -35%);\n}\nhtml[dir=rtl],\n[data-sonner-toaster][dir=rtl] {\n --toast-icon-margin-start: 4px;\n --toast-icon-margin-end: -3px;\n --toast-svg-margin-start: 0px;\n --toast-svg-margin-end: -1px;\n --toast-button-margin-start: 0;\n --toast-button-margin-end: auto;\n --toast-close-button-start: unset;\n --toast-close-button-end: 0;\n --toast-close-button-transform: translate(35%, -35%);\n}\n[data-sonner-toaster] {\n position: fixed;\n width: var(--width);\n font-family:\n ui-sans-serif,\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n Segoe UI,\n Roboto,\n Helvetica Neue,\n Arial,\n Noto Sans,\n sans-serif,\n Apple Color Emoji,\n Segoe UI Emoji,\n Segoe UI Symbol,\n Noto Color Emoji;\n --gray1: hsl(0, 0%, 99%);\n --gray2: hsl(0, 0%, 97.3%);\n --gray3: hsl(0, 0%, 95.1%);\n --gray4: hsl(0, 0%, 93%);\n --gray5: hsl(0, 0%, 90.9%);\n --gray6: hsl(0, 0%, 88.7%);\n --gray7: hsl(0, 0%, 85.8%);\n --gray8: hsl(0, 0%, 78%);\n --gray9: hsl(0, 0%, 56.1%);\n --gray10: hsl(0, 0%, 52.3%);\n --gray11: hsl(0, 0%, 43.5%);\n --gray12: hsl(0, 0%, 9%);\n --border-radius: 8px;\n box-sizing: border-box;\n padding: 0;\n margin: 0;\n list-style: none;\n outline: none;\n z-index: 999999999;\n transition: transform 400ms ease;\n}\n@media (hover: none) and (pointer: coarse) {\n [data-sonner-toaster][data-lifted=true] {\n transform: none;\n }\n}\n[data-sonner-toaster][data-x-position=right] {\n right: var(--offset-right);\n}\n[data-sonner-toaster][data-x-position=left] {\n left: var(--offset-left);\n}\n[data-sonner-toaster][data-x-position=center] {\n left: 50%;\n transform: translateX(-50%);\n}\n[data-sonner-toaster][data-y-position=top] {\n top: var(--offset-top);\n}\n[data-sonner-toaster][data-y-position=bottom] {\n bottom: var(--offset-bottom);\n}\n[data-sonner-toast] {\n --y: translateY(100%);\n --lift-amount: calc(var(--lift) * var(--gap));\n z-index: var(--z-index);\n position: absolute;\n opacity: 0;\n transform: var(--y);\n touch-action: none;\n transition:\n transform 400ms,\n opacity 400ms,\n height 400ms,\n box-shadow 200ms;\n box-sizing: border-box;\n outline: none;\n overflow-wrap: anywhere;\n}\n[data-sonner-toast][data-styled=true] {\n padding: 16px;\n background: var(--normal-bg);\n border: 1px solid var(--normal-border);\n color: var(--normal-text);\n border-radius: var(--border-radius);\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1);\n width: var(--width);\n font-size: 13px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n[data-sonner-toast]:focus-visible {\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1), 0 0 0 2px rgba(0, 0, 0, 0.2);\n}\n[data-sonner-toast][data-y-position=top] {\n top: 0;\n --y: translateY(-100%);\n --lift: 1;\n --lift-amount: calc(1 * var(--gap));\n}\n[data-sonner-toast][data-y-position=bottom] {\n bottom: 0;\n --y: translateY(100%);\n --lift: -1;\n --lift-amount: calc(var(--lift) * var(--gap));\n}\n[data-sonner-toast][data-styled=true] [data-description] {\n font-weight: 400;\n line-height: 1.4;\n color: #3f3f3f;\n}\n[data-rich-colors=true][data-sonner-toast][data-styled=true] [data-description] {\n color: inherit;\n}\n[data-sonner-toaster][data-sonner-theme=dark] [data-description] {\n color: hsl(0, 0%, 91%);\n}\n[data-sonner-toast][data-styled=true] [data-title] {\n font-weight: 500;\n line-height: 1.5;\n color: inherit;\n}\n[data-sonner-toast][data-styled=true] [data-icon] {\n display: flex;\n height: 16px;\n width: 16px;\n position: relative;\n justify-content: flex-start;\n align-items: center;\n flex-shrink: 0;\n margin-left: var(--toast-icon-margin-start);\n margin-right: var(--toast-icon-margin-end);\n}\n[data-sonner-toast][data-promise=true] [data-icon] > svg {\n opacity: 0;\n transform: scale(0.8);\n transform-origin: center;\n animation: sonner-fade-in 300ms ease forwards;\n}\n[data-sonner-toast][data-styled=true] [data-icon] > * {\n flex-shrink: 0;\n}\n[data-sonner-toast][data-styled=true] [data-icon] svg {\n margin-left: var(--toast-svg-margin-start);\n margin-right: var(--toast-svg-margin-end);\n}\n[data-sonner-toast][data-styled=true] [data-content] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n[data-sonner-toast][data-styled=true] [data-button] {\n border-radius: 4px;\n padding-left: 8px;\n padding-right: 8px;\n height: 24px;\n font-size: 12px;\n color: var(--normal-bg);\n background: var(--normal-text);\n margin-left: var(--toast-button-margin-start);\n margin-right: var(--toast-button-margin-end);\n border: none;\n font-weight: 500;\n cursor: pointer;\n outline: none;\n display: flex;\n align-items: center;\n flex-shrink: 0;\n transition: opacity 400ms, box-shadow 200ms;\n}\n[data-sonner-toast][data-styled=true] [data-button]:focus-visible {\n box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.4);\n}\n[data-sonner-toast][data-styled=true] [data-button]:first-of-type {\n margin-left: var(--toast-button-margin-start);\n margin-right: var(--toast-button-margin-end);\n}\n[data-sonner-toast][data-styled=true] [data-cancel] {\n color: var(--normal-text);\n background: rgba(0, 0, 0, 0.08);\n}\n[data-sonner-toaster][data-sonner-theme=dark] [data-sonner-toast][data-styled=true] [data-cancel] {\n background: rgba(255, 255, 255, 0.3);\n}\n[data-sonner-toast][data-styled=true] [data-close-button] {\n position: absolute;\n left: var(--toast-close-button-start);\n right: var(--toast-close-button-end);\n top: 0;\n height: 20px;\n width: 20px;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 0;\n color: var(--normal-text);\n background: var(--normal-bg);\n border: 1px solid var(--normal-border);\n transform: var(--toast-close-button-transform);\n border-radius: 50%;\n cursor: pointer;\n z-index: 1;\n transition:\n opacity 100ms,\n background 200ms,\n border-color 200ms;\n}\n[data-sonner-toast][data-styled=true] [data-close-button]:focus-visible {\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1), 0 0 0 2px rgba(0, 0, 0, 0.2);\n}\n[data-sonner-toast][data-styled=true] [data-disabled=true] {\n cursor: not-allowed;\n}\n[data-sonner-toast][data-styled=true]:hover [data-close-button]:hover {\n background: var(--gray2);\n border-color: var(--gray5);\n}\n[data-sonner-toast][data-swiping=true]::before {\n content: "";\n position: absolute;\n left: -100%;\n right: -100%;\n height: 100%;\n z-index: -1;\n}\n[data-sonner-toast][data-y-position=top][data-swiping=true]::before {\n bottom: 50%;\n transform: scaleY(3) translateY(50%);\n}\n[data-sonner-toast][data-y-position=bottom][data-swiping=true]::before {\n top: 50%;\n transform: scaleY(3) translateY(-50%);\n}\n[data-sonner-toast][data-swiping=false][data-removed=true]::before {\n content: "";\n position: absolute;\n inset: 0;\n transform: scaleY(2);\n}\n[data-sonner-toast][data-expanded=true]::after {\n content: "";\n position: absolute;\n left: 0;\n height: calc(var(--gap) + 1px);\n bottom: 100%;\n width: 100%;\n}\n[data-sonner-toast][data-mounted=true] {\n --y: translateY(0);\n opacity: 1;\n}\n[data-sonner-toast][data-expanded=false][data-front=false] {\n --scale: var(--toasts-before) * 0.05 + 1;\n --y: translateY(calc(var(--lift-amount) * var(--toasts-before))) scale(calc(-1 * var(--scale)));\n height: var(--front-toast-height);\n}\n[data-sonner-toast] > * {\n transition: opacity 400ms;\n}\n[data-sonner-toast][data-x-position=right] {\n right: 0;\n}\n[data-sonner-toast][data-x-position=left] {\n left: 0;\n}\n[data-sonner-toast][data-expanded=false][data-front=false][data-styled=true] > * {\n opacity: 0;\n}\n[data-sonner-toast][data-visible=false] {\n opacity: 0;\n pointer-events: none;\n}\n[data-sonner-toast][data-mounted=true][data-expanded=true] {\n --y: translateY(calc(var(--lift) * var(--offset)));\n height: var(--initial-height);\n}\n[data-sonner-toast][data-removed=true][data-front=true][data-swipe-out=false] {\n --y: translateY(calc(var(--lift) * -100%));\n opacity: 0;\n}\n[data-sonner-toast][data-removed=true][data-front=false][data-swipe-out=false][data-expanded=true] {\n --y: translateY(calc(var(--lift) * var(--offset) + var(--lift) * -100%));\n opacity: 0;\n}\n[data-sonner-toast][data-removed=true][data-front=false][data-swipe-out=false][data-expanded=false] {\n --y: translateY(40%);\n opacity: 0;\n transition: transform 500ms, opacity 200ms;\n}\n[data-sonner-toast][data-removed=true][data-front=false]::before {\n height: calc(var(--initial-height) + 20%);\n}\n[data-sonner-toast][data-swiping=true] {\n transform: var(--y) translateY(var(--swipe-amount-y, 0px)) translateX(var(--swipe-amount-x, 0px));\n transition: none;\n}\n[data-sonner-toast][data-swiped=true] {\n -webkit-user-select: none;\n user-select: none;\n}\n[data-sonner-toast][data-swipe-out=true][data-y-position=bottom],\n[data-sonner-toast][data-swipe-out=true][data-y-position=top] {\n animation-duration: 200ms;\n animation-timing-function: ease-out;\n animation-fill-mode: forwards;\n}\n[data-sonner-toast][data-swipe-out=true][data-swipe-direction=left] {\n animation-name: swipe-out-left;\n}\n[data-sonner-toast][data-swipe-out=true][data-swipe-direction=right] {\n animation-name: swipe-out-right;\n}\n[data-sonner-toast][data-swipe-out=true][data-swipe-direction=up] {\n animation-name: swipe-out-up;\n}\n[data-sonner-toast][data-swipe-out=true][data-swipe-direction=down] {\n animation-name: swipe-out-down;\n}\n@keyframes swipe-out-left {\n from {\n transform: var(--y) translateX(var(--swipe-amount-x));\n opacity: 1;\n }\n to {\n transform: var(--y) translateX(calc(var(--swipe-amount-x) - 100%));\n opacity: 0;\n }\n}\n@keyframes swipe-out-right {\n from {\n transform: var(--y) translateX(var(--swipe-amount-x));\n opacity: 1;\n }\n to {\n transform: var(--y) translateX(calc(var(--swipe-amount-x) + 100%));\n opacity: 0;\n }\n}\n@keyframes swipe-out-up {\n from {\n transform: var(--y) translateY(var(--swipe-amount-y));\n opacity: 1;\n }\n to {\n transform: var(--y) translateY(calc(var(--swipe-amount-y) - 100%));\n opacity: 0;\n }\n}\n@keyframes swipe-out-down {\n from {\n transform: var(--y) translateY(var(--swipe-amount-y));\n opacity: 1;\n }\n to {\n transform: var(--y) translateY(calc(var(--swipe-amount-y) + 100%));\n opacity: 0;\n }\n}\n@media (max-width: 600px) {\n [data-sonner-toaster] {\n position: fixed;\n right: var(--mobile-offset-right);\n left: var(--mobile-offset-left);\n width: 100%;\n }\n [data-sonner-toaster][dir=rtl] {\n left: calc(var(--mobile-offset-left) * -1);\n }\n [data-sonner-toaster] [data-sonner-toast] {\n left: 0;\n right: 0;\n width: calc(100% - var(--mobile-offset-left) * 2);\n }\n [data-sonner-toaster][data-x-position=left] {\n left: var(--mobile-offset-left);\n }\n [data-sonner-toaster][data-y-position=bottom] {\n bottom: var(--mobile-offset-bottom);\n }\n [data-sonner-toaster][data-y-position=top] {\n top: var(--mobile-offset-top);\n }\n [data-sonner-toaster][data-x-position=center] {\n left: var(--mobile-offset-left);\n right: var(--mobile-offset-right);\n transform: none;\n }\n}\n[data-sonner-toaster][data-sonner-theme=light] {\n --normal-bg: #fff;\n --normal-border: var(--gray4);\n --normal-text: var(--gray12);\n --success-bg: hsl(143, 85%, 96%);\n --success-border: hsl(145, 92%, 87%);\n --success-text: hsl(140, 100%, 27%);\n --info-bg: hsl(208, 100%, 97%);\n --info-border: hsl(221, 91%, 93%);\n --info-text: hsl(210, 92%, 45%);\n --warning-bg: hsl(49, 100%, 97%);\n --warning-border: hsl(49, 91%, 84%);\n --warning-text: hsl(31, 92%, 45%);\n --error-bg: hsl(359, 100%, 97%);\n --error-border: hsl(359, 100%, 94%);\n --error-text: hsl(360, 100%, 45%);\n}\n[data-sonner-toaster][data-sonner-theme=light] [data-sonner-toast][data-invert=true] {\n --normal-bg: #000;\n --normal-border: hsl(0, 0%, 20%);\n --normal-text: var(--gray1);\n}\n[data-sonner-toaster][data-sonner-theme=dark] [data-sonner-toast][data-invert=true] {\n --normal-bg: #fff;\n --normal-border: var(--gray3);\n --normal-text: var(--gray12);\n}\n[data-sonner-toaster][data-sonner-theme=dark] {\n --normal-bg: #000;\n --normal-bg-hover: hsl(0, 0%, 12%);\n --normal-border: hsl(0, 0%, 20%);\n --normal-border-hover: hsl(0, 0%, 25%);\n --normal-text: var(--gray1);\n --success-bg: hsl(150, 100%, 6%);\n --success-border: hsl(147, 100%, 12%);\n --success-text: hsl(150, 86%, 65%);\n --info-bg: hsl(215, 100%, 6%);\n --info-border: hsl(223, 43%, 17%);\n --info-text: hsl(216, 87%, 65%);\n --warning-bg: hsl(64, 100%, 6%);\n --warning-border: hsl(60, 100%, 9%);\n --warning-text: hsl(46, 87%, 65%);\n --error-bg: hsl(358, 76%, 10%);\n --error-border: hsl(357, 89%, 16%);\n --error-text: hsl(358, 100%, 81%);\n}\n[data-sonner-toaster][data-sonner-theme=dark] [data-sonner-toast] [data-close-button] {\n background: var(--normal-bg);\n border-color: var(--normal-border);\n color: var(--normal-text);\n}\n[data-sonner-toaster][data-sonner-theme=dark] [data-sonner-toast] [data-close-button]:hover {\n background: var(--normal-bg-hover);\n border-color: var(--normal-border-hover);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=success] {\n background: var(--success-bg);\n border-color: var(--success-border);\n color: var(--success-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=success] [data-close-button] {\n background: var(--success-bg);\n border-color: var(--success-border);\n color: var(--success-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=info] {\n background: var(--info-bg);\n border-color: var(--info-border);\n color: var(--info-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=info] [data-close-button] {\n background: var(--info-bg);\n border-color: var(--info-border);\n color: var(--info-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=warning] {\n background: var(--warning-bg);\n border-color: var(--warning-border);\n color: var(--warning-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=warning] [data-close-button] {\n background: var(--warning-bg);\n border-color: var(--warning-border);\n color: var(--warning-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=error] {\n background: var(--error-bg);\n border-color: var(--error-border);\n color: var(--error-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=error] [data-close-button] {\n background: var(--error-bg);\n border-color: var(--error-border);\n color: var(--error-text);\n}\n.sonner-loading-wrapper {\n --size: 16px;\n height: var(--size);\n width: var(--size);\n position: absolute;\n inset: 0;\n z-index: 10;\n}\n.sonner-loading-wrapper[data-visible=false] {\n transform-origin: center;\n animation: sonner-fade-out 0.2s ease forwards;\n}\n.sonner-spinner {\n position: relative;\n top: 50%;\n left: 50%;\n height: var(--size);\n width: var(--size);\n}\n.sonner-loading-bar {\n animation: sonner-spin 1.2s linear infinite;\n background: var(--gray11);\n border-radius: 6px;\n height: 8%;\n left: -10%;\n position: absolute;\n top: -3.9%;\n width: 24%;\n}\n.sonner-loading-bar:nth-child(1) {\n animation-delay: -1.2s;\n transform: rotate(0.0001deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(2) {\n animation-delay: -1.1s;\n transform: rotate(30deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(3) {\n animation-delay: -1s;\n transform: rotate(60deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(4) {\n animation-delay: -0.9s;\n transform: rotate(90deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(5) {\n animation-delay: -0.8s;\n transform: rotate(120deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(6) {\n animation-delay: -0.7s;\n transform: rotate(150deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(7) {\n animation-delay: -0.6s;\n transform: rotate(180deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(8) {\n animation-delay: -0.5s;\n transform: rotate(210deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(9) {\n animation-delay: -0.4s;\n transform: rotate(240deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(10) {\n animation-delay: -0.3s;\n transform: rotate(270deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(11) {\n animation-delay: -0.2s;\n transform: rotate(300deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(12) {\n animation-delay: -0.1s;\n transform: rotate(330deg) translate(146%);\n}\n@keyframes sonner-fade-in {\n 0% {\n opacity: 0;\n transform: scale(0.8);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n}\n@keyframes sonner-fade-out {\n 0% {\n opacity: 1;\n transform: scale(1);\n }\n 100% {\n opacity: 0;\n transform: scale(0.8);\n }\n}\n@keyframes sonner-spin {\n 0% {\n opacity: 1;\n }\n 100% {\n opacity: 0.15;\n }\n}\n@media (prefers-reduced-motion) {\n [data-sonner-toast],\n [data-sonner-toast] > *,\n .sonner-loading-bar {\n transition: none !important;\n animation: none !important;\n }\n}\n.sonner-loader {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n transform-origin: center;\n transition: opacity 200ms, transform 200ms;\n}\n.sonner-loader[data-visible=false] {\n opacity: 0;\n transform: scale(0.8) translate(-50%, -50%);\n}\n');
var _tmpl$ = /* @__PURE__ */ template(`<div><div class=sonner-spinner>`);
var _tmpl$2 = /* @__PURE__ */ template(`<div class=sonner-loading-bar>`);

@@ -38,2 +38,3 @@ var _tmpl$3 = /* @__PURE__ */ template(`<svg xmlns=http://www.w3.org/2000/svg viewBox="0 0 20 20"fill=currentColor height=20 width=20><path fill-rule=evenodd d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"clip-rule=evenodd>`);

var _tmpl$6 = /* @__PURE__ */ template(`<svg xmlns=http://www.w3.org/2000/svg viewBox="0 0 20 20"fill=currentColor height=20 width=20><path fill-rule=evenodd d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-5a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 5zm0 10a1 1 0 100-2 1 1 0 000 2z"clip-rule=evenodd>`);
var _tmpl$7 = /* @__PURE__ */ template(`<svg xmlns=http://www.w3.org/2000/svg width=12 height=12 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=1.5 stroke-linecap=round stroke-linejoin=round><line x1=18 y1=6 x2=6 y2=18></line><line x1=6 y1=6 x2=18 y2=18>`);
var bars = Array(12).fill(0);

@@ -45,5 +46,17 @@ function Loader(props) {

each: bars,
children: () => _tmpl$2()
children: (_, i) => (() => {
var _el$3 = _tmpl$2();
effect(() => setAttribute(_el$3, "data-index", i()));
return _el$3;
})()
}));
effect(() => setAttribute(_el$, "data-visible", props.visible));
effect((_p$) => {
var _v$ = ["sonner-loading-wrapper", props.class ?? props.className].filter(Boolean).join(" "), _v$2 = props.visible;
_v$ !== _p$.e && className(_el$, _p$.e = _v$);
_v$2 !== _p$.t && setAttribute(_el$, "data-visible", _p$.t = _v$2);
return _p$;
}, {
e: void 0,
t: void 0
});
return _el$;

@@ -67,9 +80,9 @@ })();

case "success":
return SuccessIcon;
return createComponent(SuccessIcon, {});
case "info":
return InfoIcon;
return createComponent(InfoIcon, {});
case "warning":
return WarningIcon;
return createComponent(WarningIcon, {});
case "error":
return ErrorIcon;
return createComponent(ErrorIcon, {});
default:

@@ -79,13 +92,30 @@ return null;

}
function CloseIcon() {
return _tmpl$7();
}
function useIsDocumentHidden() {
const [isDocumentHidden, setIsDocumentHidden] = createSignal(typeof document !== "undefined" ? document.hidden : false);
onMount(() => {
const callback = () => {
setIsDocumentHidden(document.hidden);
};
document.addEventListener("visibilitychange", callback);
onCleanup(() => {
document.removeEventListener("visibilitychange", callback);
});
});
return isDocumentHidden;
}
// src/state.ts
var toastsCounter = 0;
var toastsCounter = 1;
var Observer = class {
subscribers;
toasts;
dismissedToasts;
constructor() {
this.subscribers = [];
this.toasts = [];
this.dismissedToasts = /* @__PURE__ */ new Set();
}
// We use arrow functions to maintain the correct `this` reference
subscribe = (subscriber) => {

@@ -107,11 +137,21 @@ this.subscribers.push(subscriber);

const { message, ...rest } = data;
const id = typeof data?.id === "number" || data.id && data.id?.length > 0 ? data.id : toastsCounter++;
const hasStringId = typeof data.id === "string" && data.id.length > 0;
const id = typeof data.id === "number" || hasStringId ? data.id : toastsCounter++;
const alreadyExists = this.toasts.find((toast2) => {
return toast2.id === id;
});
const dismissible = data.dismissible === void 0 ? true : data.dismissible;
if (this.dismissedToasts.has(id))
this.dismissedToasts.delete(id);
if (alreadyExists) {
this.toasts = this.toasts.map((toast2) => {
if (toast2.id === id) {
this.publish({ ...toast2, ...data, id, title: message });
return { ...toast2, ...data, id, title: message };
this.publish({ ...toast2, ...data, id, title: message, dismissible });
return {
...toast2,
...data,
id,
dismissible,
title: message
};
}

@@ -121,3 +161,3 @@ return toast2;

} else {
this.addToast({ title: message, ...rest, id });
this.addToast({ title: message, ...rest, dismissible, id });
}

@@ -127,8 +167,13 @@ return id;

dismiss = (id) => {
if (!id) {
if (id) {
this.dismissedToasts.add(id);
requestAnimationFrame(() => {
this.subscribers.forEach((subscriber) => subscriber({ id, dismiss: true }));
});
} else {
this.toasts.forEach((toast2) => {
this.dismissedToasts.add(toast2.id);
this.subscribers.forEach((subscriber) => subscriber({ id: toast2.id, dismiss: true }));
});
}
this.subscribers.forEach((subscriber) => subscriber({ id, dismiss: true }));
return id;

@@ -151,6 +196,8 @@ };

};
loading = (message, data) => {
return this.create({ ...data, type: "loading", message });
};
promise = (promise, data) => {
if (!data) {
if (!data)
return;
}
let id;

@@ -162,22 +209,41 @@ if (data.loading !== void 0) {

type: "loading",
message: data.loading
message: data.loading,
description: typeof data.description !== "function" ? data.description : void 0
});
}
const p = promise instanceof Promise ? promise : promise();
const p = Promise.resolve(typeof promise === "function" ? promise() : promise);
let shouldDismiss = id !== void 0;
p.then((response) => {
if (response && typeof response.ok === "boolean" && !response.ok) {
let result;
const originalPromise = p.then(async (response) => {
result = ["resolve", response];
if (isValidElement(response)) {
shouldDismiss = false;
const message = typeof data.error === "function" ? data.error(`HTTP error! status: ${response.status}`) : data.error;
this.create({ id, type: "error", message });
this.create({ id, type: "default", message: response });
} else if (isHttpResponse(response) && !response.ok) {
shouldDismiss = false;
const promiseData = typeof data.error === "function" ? await data.error(`HTTP error! status: ${response.status}`) : data.error;
const description = typeof data.description === "function" ? await data.description(`HTTP error! status: ${response.status}`) : data.description;
const toastSettings = isExtendedResult(promiseData) ? promiseData : { message: promiseData };
this.create({ id, type: "error", description, ...toastSettings });
} else if (response instanceof Error) {
shouldDismiss = false;
const promiseData = typeof data.error === "function" ? await data.error(response) : data.error;
const description = typeof data.description === "function" ? await data.description(response) : data.description;
const toastSettings = isExtendedResult(promiseData) ? promiseData : { message: promiseData };
this.create({ id, type: "error", description, ...toastSettings });
} else if (data.success !== void 0) {
shouldDismiss = false;
const message = typeof data.success === "function" ? data.success(response) : data.success;
this.create({ id, type: "success", message });
const promiseData = typeof data.success === "function" ? await data.success(response) : data.success;
const description = typeof data.description === "function" ? await data.description(response) : data.description;
const toastSettings = isExtendedResult(promiseData) ? promiseData : { message: promiseData };
this.create({ id, type: "success", description, ...toastSettings });
}
}).catch((error) => {
}).catch(async (error) => {
result = ["reject", error];
if (data.error !== void 0) {
shouldDismiss = false;
const message = typeof data.error === "function" ? data.error(error) : data.error;
this.create({ id, type: "error", message });
const promiseData = typeof data.error === "function" ? await data.error(error) : data.error;
const description = typeof data.description === "function" ? await data.description(error) : data.description;
const toastSettings = isExtendedResult(promiseData) ? promiseData : { message: promiseData };
this.create({ id, type: "error", description, ...toastSettings });
}

@@ -191,14 +257,32 @@ }).finally(() => {

});
return id;
const unwrap = () => new Promise((resolve, reject) => {
originalPromise.then(() => {
if (result[0] === "reject")
reject(result[1]);
else
resolve(result[1]);
}).catch(reject);
});
if (typeof id !== "string" && typeof id !== "number")
return { unwrap };
return Object.assign(id, { unwrap });
};
loading = (message, data) => {
return this.create({ ...data, type: "loading", message });
};
// We can't provide the toast we just created as a prop as we didn't create it yet, so we can create a default toast object, I just don't know how to use function in argument when calling()?
custom = (jsx, data) => {
const id = data?.id || toastsCounter++;
this.publish({ jsx: jsx(id), id, ...data });
this.create({ jsx: jsx(id), ...data, id });
return id;
};
getActiveToasts = () => {
return this.toasts.filter((toast2) => !this.dismissedToasts.has(toast2.id));
};
};
function isHttpResponse(data) {
return data && typeof data === "object" && "ok" in data && typeof data.ok === "boolean" && "status" in data && typeof data.status === "number";
}
function isExtendedResult(value) {
return typeof value === "object" && value !== null && "message" in value;
}
function isValidElement(value) {
return typeof Node !== "undefined" && value instanceof Node;
}
var ToastState = new Observer();

@@ -215,49 +299,129 @@ function toastFunction(message, data) {

var basicToast = toastFunction;
var toast = Object.assign(basicToast, {
success: ToastState.success,
info: ToastState.info,
warning: ToastState.warning,
error: ToastState.error,
custom: ToastState.custom,
message: ToastState.message,
promise: ToastState.promise,
dismiss: ToastState.dismiss,
loading: ToastState.loading
});
function useIsDocumentHidden() {
const [isDocumentHidden, setIsDocumentHidden] = createSignal(false);
onMount(() => {
const callback = () => {
setIsDocumentHidden(document.hidden);
};
document.addEventListener("visibilitychange", callback);
onCleanup(() => {
window.removeEventListener("visibilitychange", callback);
});
});
return isDocumentHidden;
var getHistory = () => ToastState.toasts;
var getToasts = () => ToastState.getActiveToasts();
var toast = Object.assign(
basicToast,
{
success: ToastState.success,
info: ToastState.info,
warning: ToastState.warning,
error: ToastState.error,
custom: ToastState.custom,
message: ToastState.message,
promise: ToastState.promise,
dismiss: ToastState.dismiss,
loading: ToastState.loading
},
{
getHistory,
getToasts
}
);
// src/types.ts
function isAction(action) {
return typeof action === "object" && action !== null && "label" in action;
}
// src/index.tsx
var _tmpl$7 = /* @__PURE__ */ template(`<div class=sonner-loader>`);
var _tmpl$22 = /* @__PURE__ */ template(`<button aria-label="Close toast"data-close-button><svg xmlns=http://www.w3.org/2000/svg width=12 height=12 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=1.5 stroke-linecap=round stroke-linejoin=round><line x1=18 y1=6 x2=6 y2=18></line><line x1=6 y1=6 x2=18 y2=18>`);
var _tmpl$32 = /* @__PURE__ */ template(`<li aria-atomic=true role=status tabindex=0 data-sonner-toast="">`);
var _tmpl$42 = /* @__PURE__ */ template(`<div data-icon="">`);
var _tmpl$52 = /* @__PURE__ */ template(`<div data-description="">`);
var _tmpl$62 = /* @__PURE__ */ template(`<div data-content=""><div data-title="">`);
var _tmpl$72 = /* @__PURE__ */ template(`<button data-button data-cancel>`);
var _tmpl$8 = /* @__PURE__ */ template(`<button data-button="">`);
var _tmpl$9 = /* @__PURE__ */ template(`<section tabindex=-1>`);
var _tmpl$10 = /* @__PURE__ */ template(`<ol tabindex=-1 data-sonner-toaster>`);
var _tmpl$8 = /* @__PURE__ */ template(`<div>`);
var _tmpl$22 = /* @__PURE__ */ template(`<button data-close-button>`);
var _tmpl$32 = /* @__PURE__ */ template(`<div data-icon>`);
var _tmpl$42 = /* @__PURE__ */ template(`<div data-description>`);
var _tmpl$52 = /* @__PURE__ */ template(`<li tabindex=0 data-sonner-toast><div data-content><div data-title>`);
var _tmpl$62 = /* @__PURE__ */ template(`<button data-button data-cancel>`);
var _tmpl$72 = /* @__PURE__ */ template(`<button data-button data-action>`);
var _tmpl$82 = /* @__PURE__ */ template(`<section tabindex=-1 aria-live=polite aria-relevant="additions text"aria-atomic=false data-react-aria-top-layer>`);
var _tmpl$9 = /* @__PURE__ */ template(`<ol tabindex=-1 data-sonner-toaster style=--width:356px>`);
var VISIBLE_TOASTS_AMOUNT = 3;
var VIEWPORT_OFFSET = "32px";
var VIEWPORT_OFFSET = "24px";
var MOBILE_VIEWPORT_OFFSET = "16px";
var TOAST_LIFETIME = 4e3;
var TOAST_WIDTH = 356;
var GAP = 14;
var SWIPE_TRESHOLD = 20;
var SWIPE_THRESHOLD = 45;
var TIME_BEFORE_UNMOUNT = 200;
function _cn(...classes) {
function cn(...classes) {
return classes.filter(Boolean).join(" ");
}
var Toast = (props) => {
function resolveContent(content) {
return typeof content === "function" ? content() : content;
}
function getDefaultSwipeDirections(position) {
const [y, x] = position.split("-");
const directions = [];
if (y) directions.push(y);
if (x) directions.push(x);
return directions;
}
function getDocumentDirection() {
if (typeof window === "undefined" || typeof document === "undefined") return "ltr";
const dirAttribute = document.documentElement.getAttribute("dir");
if (dirAttribute === "auto" || !dirAttribute) return window.getComputedStyle(document.documentElement).direction;
return dirAttribute;
}
function assignOffset(defaultOffset, mobileOffset) {
const styles = {};
[defaultOffset, mobileOffset].forEach((offset, index) => {
const isMobile = index === 1;
const prefix = isMobile ? "--mobile-offset" : "--offset";
const defaultValue = isMobile ? MOBILE_VIEWPORT_OFFSET : VIEWPORT_OFFSET;
const assignAll = (value) => {
for (const key of ["top", "right", "bottom", "left"]) styles[`${prefix}-${key}`] = typeof value === "number" ? `${value}px` : value;
};
if (typeof offset === "number" || typeof offset === "string") {
assignAll(offset);
return;
}
if (typeof offset === "object" && offset !== null) {
for (const key of ["top", "right", "bottom", "left"]) {
const value = offset[key];
styles[`${prefix}-${key}`] = value === void 0 ? defaultValue : typeof value === "number" ? `${value}px` : value;
}
return;
}
assignAll(defaultValue);
});
return styles;
}
function mergeClassNames(classNames, legacy) {
return classNames ?? legacy;
}
function mergeDescriptionClassName(descriptionClassName, legacy) {
return descriptionClassName ?? legacy ?? "";
}
function mergeClassName(className, legacy) {
return className ?? legacy ?? "";
}
function useSonner() {
const [activeToasts, setActiveToasts] = createSignal(toast.getToasts());
onMount(() => {
const unsubscribe = ToastState.subscribe((toastItem) => {
if (toastItem.dismiss) {
requestAnimationFrame(() => {
setActiveToasts((toasts) => toasts.filter((t) => t.id !== toastItem.id));
});
return;
}
const nextToast = toastItem;
setActiveToasts((toasts) => {
const indexOfExistingToast = toasts.findIndex((t) => t.id === nextToast.id);
if (indexOfExistingToast !== -1) {
return [...toasts.slice(0, indexOfExistingToast), {
...toasts[indexOfExistingToast],
...nextToast
}, ...toasts.slice(indexOfExistingToast + 1)];
}
return [nextToast, ...toasts];
});
});
onCleanup(unsubscribe);
});
return {
toasts: activeToasts
};
}
function createToastTheme(theme) {
return theme !== "system" ? theme : typeof window !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
}
function Toast(props) {
const [mounted, setMounted] = createSignal(false);

@@ -267,20 +431,32 @@ const [removed, setRemoved] = createSignal(false);

const [swipeOut, setSwipeOut] = createSignal(false);
const [isSwiped, setIsSwiped] = createSignal(false);
const [swipeDirection, setSwipeDirection] = createSignal(null);
const [swipeOutDirection, setSwipeOutDirection] = createSignal(null);
const [offsetBeforeRemove, setOffsetBeforeRemove] = createSignal(0);
const [initialHeight, setInitialHeight] = createSignal(0);
let toastRef;
let dragStartTime = null;
let closeTimerStartTimeRef = 0;
let lastCloseTimerStartTimeRef = 0;
let remainingTime = TOAST_LIFETIME;
const [pointerStartRef, setPointerStartRef] = createSignal(null);
const isFront = () => props.index === 0;
const isVisible = () => props.index + 1 <= props.visibleToasts;
const toastType = () => props.toast.type;
const toastClassname = () => props.toast.class || "";
const toastDescriptionClassname = () => props.toast.descriptionClass || "";
const propsWithDefaults = mergeProps({
gap: GAP
}, props);
const heightIndex = () => props.heights.findIndex((height) => height.toastId === props.toast.id) || 0;
const duration = () => props.toast.duration || props.duration || TOAST_LIFETIME;
let closeTimerStartTimeRef = 0;
let lastCloseTimerStartTimeRef = 0;
const [pointerStartRef, setPointerStartRef] = createSignal(null);
const coords = () => props.position.split("-");
const toastsHeightBefore = () => {
const dismissible = () => props.toast.dismissible !== false;
const classNames = () => mergeClassNames(props.classNames, props.classes);
const className$1 = () => mergeClassName(props.className, props.class);
const descriptionClassName = () => mergeDescriptionClassName(props.descriptionClassName, props.descriptionClass);
const toastClassName = () => mergeClassName(props.toast.className, props.toast.class);
const toastDescriptionClassName = () => mergeDescriptionClassName(props.toast.descriptionClassName, props.toast.descriptionClass);
const toastClassNames = () => mergeClassNames(props.toast.classNames, props.toast.classes);
const closeButton = () => props.toast.closeButton ?? props.closeButton;
const duration = () => props.toast.duration ?? props.duration ?? TOAST_LIFETIME;
const invert = () => props.toast.invert ?? props.invert;
const disabled = () => toastType() === "loading";
const swipeDirections = () => props.swipeDirections ?? getDefaultSwipeDirections(props.position);
const y = createMemo(() => props.position.split("-")[0]);
const x = createMemo(() => props.position.split("-")[1]);
const heightIndex = createMemo(() => Math.max(0, props.heights.findIndex((height) => height.toastId === props.toast.id)));
const toastsHeightBefore = createMemo(() => {
return props.heights.reduce((prev, curr, reducerIndex) => {

@@ -290,13 +466,30 @@ if (reducerIndex >= heightIndex()) return prev;

}, 0);
};
});
const offset = createMemo(() => heightIndex() * (props.gap ?? GAP) + toastsHeightBefore());
const isDocumentHidden = useIsDocumentHidden();
const invert = () => props.toast.invert || props.invert;
const disabled = () => toastType() === "loading";
const offset = () => heightIndex() * propsWithDefaults.gap + toastsHeightBefore();
createEffect(() => {
remainingTime = duration();
});
function deleteToast() {
setRemoved(true);
setOffsetBeforeRemove(offset());
props.setHeights((heights) => heights.filter((height) => height.toastId !== props.toast.id));
window.setTimeout(() => {
props.removeToast(props.toast);
}, TIME_BEFORE_UNMOUNT);
}
function getLoadingIcon() {
if (props.icons?.loading) {
return (() => {
var _el$ = _tmpl$7();
var _el$ = _tmpl$8();
insert(_el$, () => props.icons.loading);
effect(() => setAttribute(_el$, "data-visible", toastType() === "loading"));
effect((_p$) => {
var _v$ = cn(classNames()?.loader, toastClassNames()?.loader, "sonner-loader"), _v$2 = toastType() === "loading";
_v$ !== _p$.e && className(_el$, _p$.e = _v$);
_v$2 !== _p$.t && setAttribute(_el$, "data-visible", _p$.t = _v$2);
return _p$;
}, {
e: void 0,
t: void 0
});
return _el$;

@@ -306,2 +499,5 @@ })();

return createComponent(Loader, {
get ["class"]() {
return cn(classNames()?.loader, toastClassNames()?.loader);
},
get visible() {

@@ -312,38 +508,43 @@ return toastType() === "loading";

}
const icon = () => props.toast.icon ?? props.icons?.[toastType()] ?? getAsset(toastType());
onMount(() => {
setMounted(true);
if (!toastRef) return;
const height = toastRef.getBoundingClientRect().height;
setInitialHeight(height);
props.setHeights((h) => [{
toastId: props.toast.id,
toasterId: props.toast.toasterId,
height,
position: props.toast.position
}, ...h]);
onCleanup(() => {
props.setHeights((h) => h.filter((height2) => height2.toastId !== props.toast.id));
});
});
onMount(() => {
const toastNode = toastRef;
const originalHeight = toastNode.style.height;
toastNode.style.height = "auto";
const newHeight = toastNode.getBoundingClientRect().height;
toastNode.style.height = originalHeight;
setInitialHeight(newHeight);
createEffect(() => {
props.setHeights((heights) => {
const alreadyExists = heights.find((height) => height.toastId === props.toast.id);
if (!alreadyExists) return [{
toastId: props.toast.id,
height: newHeight,
position: props.toast.position
}, ...heights];
else return heights.map((height) => height.toastId === props.toast.id ? {
...height,
height: newHeight
} : height);
});
createEffect(() => {
if (!mounted() || !toastRef) return;
resolveContent(props.toast.title);
resolveContent(props.toast.description);
const originalHeight = toastRef.style.height;
toastRef.style.height = "auto";
const nextHeight = toastRef.getBoundingClientRect().height;
toastRef.style.height = originalHeight;
setInitialHeight(nextHeight);
props.setHeights((heights) => {
const alreadyExists = heights.find((height) => height.toastId === props.toast.id);
if (!alreadyExists) return [{
toastId: props.toast.id,
toasterId: props.toast.toasterId,
height: nextHeight,
position: props.toast.position
}, ...heights];
return heights.map((height) => height.toastId === props.toast.id ? {
...height,
height: nextHeight
} : height);
});
});
const deleteToast = () => {
setRemoved(true);
setOffsetBeforeRemove(offset());
props.setHeights((h) => h.filter((height) => height.toastId !== props.toast.id));
setTimeout(() => {
props.removeToast(props.toast);
}, TIME_BEFORE_UNMOUNT);
};
let remainingTime = duration();
createEffect(on(() => [props.expanded, props.interacting, props.toast, duration(), props.toast.promise, toastType(), props.pauseWhenPageIsHidden, isDocumentHidden()], ([expanded, interacting, toast2, duration2, promise, toastType2, pauseWhenPageIsHidden, isDocumentHidden2]) => {
if (promise && toastType2 === "loading" || duration2 === Number.POSITIVE_INFINITY) return;
createEffect(on(() => [props.expanded, props.interacting, props.toast, toastType(), isDocumentHidden(), duration()], ([expanded, interacting, currentToast, currentType]) => {
if (currentToast.promise && currentType === "loading" || currentToast.duration === Number.POSITIVE_INFINITY || currentType === "loading") return;
let timeoutId;

@@ -353,3 +554,3 @@ const pauseTimer = () => {

const elapsedTime = (/* @__PURE__ */ new Date()).getTime() - closeTimerStartTimeRef;
remainingTime = remainingTime - elapsedTime;
remainingTime -= elapsedTime;
}

@@ -359,55 +560,66 @@ lastCloseTimerStartTimeRef = (/* @__PURE__ */ new Date()).getTime();

const startTimer = () => {
if (remainingTime === Number.POSITIVE_INFINITY) return;
closeTimerStartTimeRef = (/* @__PURE__ */ new Date()).getTime();
timeoutId = setTimeout(() => {
toast2.onAutoClose?.(toast2);
currentToast.onAutoClose?.(currentToast);
deleteToast();
}, remainingTime);
};
if (expanded || interacting || pauseWhenPageIsHidden && isDocumentHidden2) pauseTimer();
const shouldPause = expanded || interacting || (props.pauseWhenPageIsHidden ?? true) && isDocumentHidden();
if (shouldPause) pauseTimer();
else startTimer();
onCleanup(() => {
clearTimeout(timeoutId);
if (timeoutId) clearTimeout(timeoutId);
});
}));
createEffect(on(() => props.toast.id, (toastId) => {
const toastNode = toastRef;
if (toastNode) {
const height = toastNode.getBoundingClientRect().height;
setInitialHeight(height);
props.setHeights((h) => [{
toastId,
height,
position: props.toast.position
}, ...h]);
onCleanup(() => {
props.setHeights((h) => h.filter((height2) => height2.toastId !== toastId));
});
createEffect(on(() => props.toast.delete, (shouldDelete) => {
if (shouldDelete) {
deleteToast();
props.toast.onDismiss?.(props.toast);
}
}));
createEffect(on(() => props.toast.delete, (d) => {
if (d) deleteToast();
}));
return (() => {
var _el$2 = _tmpl$32();
var _el$2 = _tmpl$52(), _el$5 = _el$2.firstChild, _el$6 = _el$5.firstChild;
_el$2.$$pointermove = (event) => {
if (!pointerStartRef()) return;
const yPosition = event.clientY - pointerStartRef().y;
const xPosition = event.clientX - pointerStartRef().x;
const clamp = coords()[0] === "top" ? Math.min : Math.max;
const clampedY = clamp(0, yPosition);
const swipeStartThreshold = event.pointerType === "touch" ? 10 : 2;
const isAllowedToSwipe = Math.abs(clampedY) > swipeStartThreshold;
if (isAllowedToSwipe) {
toastRef?.style.setProperty("--swipe-amount", `${yPosition}px`);
} else if (Math.abs(xPosition) > swipeStartThreshold) {
setPointerStartRef(null);
if (!pointerStartRef() || !dismissible()) return;
if ((window.getSelection()?.toString().length ?? 0) > 0) return;
const yDelta = event.clientY - pointerStartRef().y;
const xDelta = event.clientX - pointerStartRef().x;
if (!swipeDirection() && (Math.abs(xDelta) > 1 || Math.abs(yDelta) > 1)) setSwipeDirection(Math.abs(xDelta) > Math.abs(yDelta) ? "x" : "y");
const swipeAmount = {
x: 0,
y: 0
};
const getDampening = (delta) => {
const factor = Math.abs(delta) / 20;
return 1 / (1.5 + factor);
};
if (swipeDirection() === "y") {
if (swipeDirections().includes("top") || swipeDirections().includes("bottom")) {
if (swipeDirections().includes("top") && yDelta < 0 || swipeDirections().includes("bottom") && yDelta > 0) swipeAmount.y = yDelta;
else swipeAmount.y = yDelta * getDampening(yDelta);
}
} else if (swipeDirection() === "x") {
if (swipeDirections().includes("left") || swipeDirections().includes("right")) {
if (swipeDirections().includes("left") && xDelta < 0 || swipeDirections().includes("right") && xDelta > 0) swipeAmount.x = xDelta;
else swipeAmount.x = xDelta * getDampening(xDelta);
}
}
if (Math.abs(swipeAmount.x) > 0 || Math.abs(swipeAmount.y) > 0) setIsSwiped(true);
toastRef?.style.setProperty("--swipe-amount-x", `${swipeAmount.x}px`);
toastRef?.style.setProperty("--swipe-amount-y", `${swipeAmount.y}px`);
};
_el$2.$$pointerup = () => {
if (swipeOut()) return;
if (swipeOut() || !dismissible()) return;
setPointerStartRef(null);
const swipeAmount = Number(toastRef?.style.getPropertyValue("--swipe-amount").replace("px", "") || 0);
if (Math.abs(swipeAmount) >= SWIPE_TRESHOLD) {
const swipeAmountX = Number(toastRef?.style.getPropertyValue("--swipe-amount-x").replace("px", "") || 0);
const swipeAmountY = Number(toastRef?.style.getPropertyValue("--swipe-amount-y").replace("px", "") || 0);
const timeTaken = Math.max(1, (/* @__PURE__ */ new Date()).getTime() - (dragStartTime?.getTime() ?? 0));
const swipeAmount = swipeDirection() === "x" ? swipeAmountX : swipeAmountY;
const velocity = Math.abs(swipeAmount) / timeTaken;
if (Math.abs(swipeAmount) >= SWIPE_THRESHOLD || velocity > 0.11) {
setOffsetBeforeRemove(offset());
props.toast.onDismiss?.(props.toast);
if (swipeDirection() === "x") setSwipeOutDirection(swipeAmountX > 0 ? "right" : "left");
else setSwipeOutDirection(swipeAmountY > 0 ? "down" : "up");
deleteToast();

@@ -417,9 +629,14 @@ setSwipeOut(true);

}
toastRef?.style.setProperty("--swipe-amount", "0px");
toastRef?.style.setProperty("--swipe-amount-x", "0px");
toastRef?.style.setProperty("--swipe-amount-y", "0px");
setIsSwiped(false);
setSwiping(false);
setSwipeDirection(null);
};
_el$2.$$pointerdown = (event) => {
if (disabled()) return;
if (event.button === 2) return;
if (disabled() || !dismissible()) return;
dragStartTime = /* @__PURE__ */ new Date();
setOffsetBeforeRemove(offset());
event.target.setPointerCapture(event.pointerId);
event.currentTarget.setPointerCapture(event.pointerId);
if (event.target.tagName === "BUTTON") return;

@@ -432,2 +649,7 @@ setSwiping(true);

};
_el$2.addEventListener("dragend", () => {
setSwiping(false);
setSwipeDirection(null);
setPointerStartRef(null);
});
var _ref$ = toastRef;

@@ -437,74 +659,81 @@ typeof _ref$ === "function" ? use(_ref$, _el$2) : toastRef = _el$2;

get when() {
return props.closeButton && !props.toast.jsx;
return memo(() => !!(closeButton() && !props.toast.jsx))() && toastType() !== "loading";
},
get children() {
var _el$3 = _tmpl$22();
addEventListener(_el$3, "click", disabled() ? void 0 : () => {
_el$3.$$click = () => {
if (disabled() || !dismissible()) return;
deleteToast();
props.toast.onDismiss?.(props.toast);
}, true);
};
insert(_el$3, () => props.icons?.close ?? createComponent(CloseIcon, {}));
effect((_p$) => {
var _v$ = disabled(), _v$2 = _cn(props.classes?.closeButton, props.toast?.classes?.closeButton);
_v$ !== _p$.e && setAttribute(_el$3, "data-disabled", _p$.e = _v$);
_v$2 !== _p$.t && className(_el$3, _p$.t = _v$2);
var _v$3 = props.closeButtonAriaLabel ?? "Close toast", _v$4 = disabled(), _v$5 = cn(classNames()?.closeButton, toastClassNames()?.closeButton);
_v$3 !== _p$.e && setAttribute(_el$3, "aria-label", _p$.e = _v$3);
_v$4 !== _p$.t && setAttribute(_el$3, "data-disabled", _p$.t = _v$4);
_v$5 !== _p$.a && className(_el$3, _p$.a = _v$5);
return _p$;
}, {
e: void 0,
t: void 0
t: void 0,
a: void 0
});
return _el$3;
}
}), _el$5);
insert(_el$2, createComponent(Show, {
get when() {
return memo(() => !!((toastType() || props.toast.icon || props.toast.promise) && props.toast.icon !== null))() && (props.icons?.[toastType()] !== null || props.toast.icon);
},
get children() {
var _el$4 = _tmpl$32();
insert(_el$4, (() => {
var _c$ = memo(() => !!(props.toast.promise || props.toast.type === "loading" && !props.toast.icon));
return () => _c$() ? props.toast.icon || getLoadingIcon() : null;
})(), null);
insert(_el$4, (() => {
var _c$2 = memo(() => props.toast.type !== "loading");
return () => _c$2() ? icon() : null;
})(), null);
effect(() => className(_el$4, cn(classNames()?.icon, toastClassNames()?.icon)));
return _el$4;
}
}), _el$5);
insert(_el$6, (() => {
var _c$3 = memo(() => !!props.toast.jsx);
return () => _c$3() ? props.toast.jsx : resolveContent(props.toast.title);
})());
insert(_el$5, createComponent(Show, {
get when() {
return props.toast.description;
},
get children() {
var _el$7 = _tmpl$42();
insert(_el$7, () => resolveContent(props.toast.description));
effect(() => className(_el$7, cn(descriptionClassName(), toastDescriptionClassName(), classNames()?.description, toastClassNames()?.description)));
return _el$7;
}
}), null);
insert(_el$2, createComponent(Show, {
get when() {
return props.toast.jsx || props.toast.title instanceof Element;
return props.toast.cancel;
},
get fallback() {
return [createComponent(Show, {
get when() {
return toastType() || props.toast.icon || props.toast.promise;
},
get children() {
var _el$4 = _tmpl$42();
insert(_el$4, (() => {
var _c$ = memo(() => !!(props.toast.promise || props.toast.type === "loading" && !props.toast.icon));
return () => _c$() ? props.toast.icon || getLoadingIcon() : null;
})(), null);
insert(_el$4, (() => {
var _c$2 = memo(() => props.toast.type !== "loading");
return () => _c$2() ? props.toast.icon || props.icons?.[toastType()] || getAsset(toastType())() : null;
})(), null);
return _el$4;
}
}), (() => {
var _el$5 = _tmpl$62(), _el$6 = _el$5.firstChild;
insert(_el$6, () => props.toast.title);
insert(_el$5, createComponent(Show, {
get when() {
return props.toast.description;
},
get children() {
var _el$7 = _tmpl$52();
insert(_el$7, () => props.toast.description);
effect(() => className(_el$7, _cn(props.descriptionClass, toastDescriptionClassname(), props.classes?.description, props.toast?.classes?.description)));
return _el$7;
}
}), null);
effect(() => className(_el$6, _cn(props.classes?.title, props.toast?.classes?.title)));
return _el$5;
})(), createComponent(Show, {
get when() {
return props.toast.cancel;
},
get children() {
var _el$8 = _tmpl$72();
_el$8.$$click = () => {
children: (cancel) => createComponent(Show, {
get when() {
return !isAction(cancel());
},
get fallback() {
return (() => {
var _el$8 = _tmpl$62();
_el$8.$$click = (event) => {
const currentCancel = cancel();
if (!dismissible()) return;
currentCancel.onClick?.(event);
deleteToast();
if (props.toast.cancel?.onClick) props.toast.cancel.onClick();
};
insert(_el$8, () => props.toast.cancel.label);
insert(_el$8, () => cancel().label);
effect((_p$) => {
var _v$20 = props.toast.cancelButtonStyle || props.cancelButtonStyle, _v$21 = _cn(props.classes?.cancelButton, props.toast?.classes?.cancelButton);
_p$.e = style(_el$8, _v$20, _p$.e);
_v$21 !== _p$.t && className(_el$8, _p$.t = _v$21);
var _v$27 = props.toast.cancelButtonStyle ?? props.cancelButtonStyle, _v$28 = cn(classNames()?.cancelButton, toastClassNames()?.cancelButton);
_p$.e = style(_el$8, _v$27, _p$.e);
_v$28 !== _p$.t && className(_el$8, _p$.t = _v$28);
return _p$;

@@ -516,19 +745,31 @@ }, {

return _el$8;
}
}), createComponent(Show, {
get when() {
return props.toast.action;
},
get children() {
var _el$9 = _tmpl$8();
})();
},
get children() {
return cancel();
}
})
}), null);
insert(_el$2, createComponent(Show, {
get when() {
return props.toast.action;
},
children: (action) => createComponent(Show, {
get when() {
return !isAction(action());
},
get fallback() {
return (() => {
var _el$9 = _tmpl$72();
_el$9.$$click = (event) => {
props.toast.action?.onClick(event);
const currentAction = action();
currentAction.onClick?.(event);
if (event.defaultPrevented) return;
deleteToast();
};
insert(_el$9, () => props.toast.action.label);
insert(_el$9, () => action().label);
effect((_p$) => {
var _v$22 = props.toast.actionButtonStyle || props.actionButtonStyle, _v$23 = _cn(props.classes?.actionButton, props.toast?.classes?.actionButton);
_p$.e = style(_el$9, _v$22, _p$.e);
_v$23 !== _p$.t && className(_el$9, _p$.t = _v$23);
var _v$29 = props.toast.actionButtonStyle ?? props.actionButtonStyle, _v$30 = cn(classNames()?.actionButton, toastClassNames()?.actionButton);
_p$.e = style(_el$9, _v$29, _p$.e);
_v$30 !== _p$.t && className(_el$9, _p$.t = _v$30);
return _p$;

@@ -540,11 +781,11 @@ }, {

return _el$9;
}
})];
},
get children() {
return props.toast.jsx || props.toast.title;
}
})();
},
get children() {
return action();
}
})
}), null);
effect((_p$) => {
var _v$3 = props.toast.important ? "assertive" : "polite", _v$4 = _cn(props.class, toastClassname(), props.classes?.toast, props.toast?.classes?.toast, props.classes?.default, props.classes?.[toastType()], props.toast?.classes?.[toastType()]), _v$5 = !(props.toast.jsx || props.toast.unstyled || props.unstyled), _v$6 = mounted(), _v$7 = Boolean(props.toast.promise), _v$8 = removed(), _v$9 = isVisible(), _v$10 = coords()[0], _v$11 = coords()[1], _v$12 = props.index, _v$13 = isFront(), _v$14 = swiping(), _v$15 = toastType(), _v$16 = invert(), _v$17 = swipeOut(), _v$18 = Boolean(props.expanded || props.expandByDefault && mounted()), _v$19 = {
var _v$6 = cn(className$1(), toastClassName(), classNames()?.toast, toastClassNames()?.toast, classNames()?.default, classNames()?.[toastType()], toastClassNames()?.[toastType()]), _v$7 = props.toast.richColors ?? props.defaultRichColors, _v$8 = !(props.toast.jsx || props.toast.unstyled || props.unstyled), _v$9 = mounted(), _v$0 = Boolean(props.toast.promise), _v$1 = isSwiped(), _v$10 = removed(), _v$11 = isVisible(), _v$12 = y(), _v$13 = x(), _v$14 = props.index, _v$15 = isFront(), _v$16 = swiping(), _v$17 = dismissible(), _v$18 = toastType(), _v$19 = invert(), _v$20 = swipeOut(), _v$21 = swipeOutDirection(), _v$22 = Boolean(props.expanded || props.expandByDefault && mounted()), _v$23 = props.toast.testId, _v$24 = {
"--index": props.index,

@@ -557,20 +798,26 @@ "--toasts-before": props.index,

...props.toast.style
};
_v$3 !== _p$.e && setAttribute(_el$2, "aria-live", _p$.e = _v$3);
_v$4 !== _p$.t && className(_el$2, _p$.t = _v$4);
_v$5 !== _p$.a && setAttribute(_el$2, "data-styled", _p$.a = _v$5);
_v$6 !== _p$.o && setAttribute(_el$2, "data-mounted", _p$.o = _v$6);
_v$7 !== _p$.i && setAttribute(_el$2, "data-promise", _p$.i = _v$7);
_v$8 !== _p$.n && setAttribute(_el$2, "data-removed", _p$.n = _v$8);
_v$9 !== _p$.s && setAttribute(_el$2, "data-visible", _p$.s = _v$9);
_v$10 !== _p$.h && setAttribute(_el$2, "data-y-position", _p$.h = _v$10);
_v$11 !== _p$.r && setAttribute(_el$2, "data-x-position", _p$.r = _v$11);
_v$12 !== _p$.d && setAttribute(_el$2, "data-index", _p$.d = _v$12);
_v$13 !== _p$.l && setAttribute(_el$2, "data-front", _p$.l = _v$13);
_v$14 !== _p$.u && setAttribute(_el$2, "data-swiping", _p$.u = _v$14);
_v$15 !== _p$.c && setAttribute(_el$2, "data-type", _p$.c = _v$15);
_v$16 !== _p$.w && setAttribute(_el$2, "data-invert", _p$.w = _v$16);
_v$17 !== _p$.m && setAttribute(_el$2, "data-swipe-out", _p$.m = _v$17);
_v$18 !== _p$.f && setAttribute(_el$2, "data-expanded", _p$.f = _v$18);
_p$.y = style(_el$2, _v$19, _p$.y);
}, _v$25 = cn(classNames()?.content, toastClassNames()?.content), _v$26 = cn(classNames()?.title, toastClassNames()?.title);
_v$6 !== _p$.e && className(_el$2, _p$.e = _v$6);
_v$7 !== _p$.t && setAttribute(_el$2, "data-rich-colors", _p$.t = _v$7);
_v$8 !== _p$.a && setAttribute(_el$2, "data-styled", _p$.a = _v$8);
_v$9 !== _p$.o && setAttribute(_el$2, "data-mounted", _p$.o = _v$9);
_v$0 !== _p$.i && setAttribute(_el$2, "data-promise", _p$.i = _v$0);
_v$1 !== _p$.n && setAttribute(_el$2, "data-swiped", _p$.n = _v$1);
_v$10 !== _p$.s && setAttribute(_el$2, "data-removed", _p$.s = _v$10);
_v$11 !== _p$.h && setAttribute(_el$2, "data-visible", _p$.h = _v$11);
_v$12 !== _p$.r && setAttribute(_el$2, "data-y-position", _p$.r = _v$12);
_v$13 !== _p$.d && setAttribute(_el$2, "data-x-position", _p$.d = _v$13);
_v$14 !== _p$.l && setAttribute(_el$2, "data-index", _p$.l = _v$14);
_v$15 !== _p$.u && setAttribute(_el$2, "data-front", _p$.u = _v$15);
_v$16 !== _p$.c && setAttribute(_el$2, "data-swiping", _p$.c = _v$16);
_v$17 !== _p$.w && setAttribute(_el$2, "data-dismissible", _p$.w = _v$17);
_v$18 !== _p$.m && setAttribute(_el$2, "data-type", _p$.m = _v$18);
_v$19 !== _p$.f && setAttribute(_el$2, "data-invert", _p$.f = _v$19);
_v$20 !== _p$.y && setAttribute(_el$2, "data-swipe-out", _p$.y = _v$20);
_v$21 !== _p$.g && setAttribute(_el$2, "data-swipe-direction", _p$.g = _v$21);
_v$22 !== _p$.p && setAttribute(_el$2, "data-expanded", _p$.p = _v$22);
_v$23 !== _p$.b && setAttribute(_el$2, "data-testid", _p$.b = _v$23);
_p$.T = style(_el$2, _v$24, _p$.T);
_v$25 !== _p$.A && className(_el$5, _p$.A = _v$25);
_v$26 !== _p$.O && className(_el$6, _p$.O = _v$26);
return _p$;

@@ -594,15 +841,14 @@ }, {

f: void 0,
y: void 0
y: void 0,
g: void 0,
p: void 0,
b: void 0,
T: void 0,
A: void 0,
O: void 0
});
return _el$2;
})();
};
function getDocumentDirection() {
if (typeof window === "undefined") return "ltr";
if (typeof document === "undefined") return "ltr";
const dirAttribute = document.documentElement.getAttribute("dir");
if (dirAttribute === "auto" || !dirAttribute) return window.getComputedStyle(document.documentElement).direction;
return dirAttribute;
}
var Toaster = (props) => {
function Toaster(props) {
const propsWithDefaults = mergeProps({

@@ -612,46 +858,66 @@ position: "bottom-right",

theme: "light",
gap: GAP,
visibleToasts: VISIBLE_TOASTS_AMOUNT,
dir: getDocumentDirection()
dir: getDocumentDirection(),
containerAriaLabel: "Notifications"
}, props);
const initialTheme = createToastTheme(propsWithDefaults.theme);
const [toastsStore, setToastsStore] = createStore({
toasts: []
});
const possiblePositions = () => {
return Array.from(new Set([propsWithDefaults.position].concat(toastsStore.toasts.filter((toast2) => toast2.position).map((toast2) => toast2.position))));
};
const filteredToasts = createMemo(() => {
const toasts = toastsStore.toasts;
if (propsWithDefaults.id) return toasts.filter((toast2) => toast2.toasterId === propsWithDefaults.id);
return toasts.filter((toast2) => !toast2.toasterId);
});
const possiblePositions = createMemo(() => {
return Array.from(/* @__PURE__ */ new Set([propsWithDefaults.position, ...filteredToasts().filter((toast2) => toast2.position).map((toast2) => toast2.position)]));
});
const [heights, setHeights] = createSignal([]);
const [expanded, setExpanded] = createSignal(false);
const [interacting, setInteracting] = createSignal(false);
const [actualTheme, setActualTheme] = createSignal(initialTheme);
const [lastFocusedElementRef, setLastFocusedElementRef] = createSignal(null);
const [isFocusWithinRef, setIsFocusWithinRef] = createSignal(false);
let listRef;
const hotkeyLabel = () => propsWithDefaults.hotkey.join("+").replace(/Key/g, "").replace(/Digit/g, "");
const [lastFocusedElementRef, setLastFocusedElementRef] = createSignal(null);
const [isFocusedWithinRef, setIsFocusedWithinRef] = createSignal(false);
const [actualTheme, setActualTheme] = createSignal(propsWithDefaults.theme !== "system" ? propsWithDefaults.theme : typeof window !== "undefined" ? window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : "light");
const removeToast = (toast2) => setToastsStore("toasts", (toasts) => toasts.filter(({
id
}) => id !== toast2.id));
const className$1 = () => mergeClassName(propsWithDefaults.className, propsWithDefaults.class);
const toastOptions = () => propsWithDefaults.toastOptions;
const toastClassNames = () => mergeClassNames(toastOptions()?.classNames, toastOptions()?.classes);
const toastDescriptionClassName = () => mergeDescriptionClassName(toastOptions()?.descriptionClassName, toastOptions()?.descriptionClass);
const toastClassName = () => mergeClassName(toastOptions()?.className, toastOptions()?.class);
const removeToast = (toastToRemove) => {
setToastsStore("toasts", (toasts) => {
if (!toasts.find((toast2) => toast2.id === toastToRemove.id)?.delete) ToastState.dismiss(toastToRemove.id);
return toasts.filter(({
id
}) => id !== toastToRemove.id);
});
};
onMount(() => {
const unsub = ToastState.subscribe((toast2) => {
if (toast2.dismiss) {
setToastsStore("toasts", produce((_toasts) => {
_toasts.forEach((t) => {
if (t.id === toast2.id) t.delete = true;
});
}));
const unsubscribe = ToastState.subscribe((toastItem) => {
if (toastItem.dismiss) {
requestAnimationFrame(() => {
setToastsStore("toasts", produce((toasts) => {
toasts.forEach((toast2) => {
if (toast2.id === toastItem.id) toast2.delete = true;
});
}));
});
return;
}
const changedIndex = toastsStore.toasts.findIndex((t) => t.id === toast2.id);
if (changedIndex !== -1) {
setToastsStore("toasts", [changedIndex], reconcile(toast2));
const nextToast = toastItem;
const indexOfExistingToast = toastsStore.toasts.findIndex((t) => t.id === nextToast.id);
if (indexOfExistingToast !== -1) {
setToastsStore("toasts", indexOfExistingToast, reconcile(nextToast));
return;
}
setToastsStore("toasts", produce((_toasts) => {
_toasts.unshift(toast2);
setToastsStore("toasts", produce((toasts) => {
toasts.unshift(nextToast);
}));
});
onCleanup(() => {
unsub();
});
onCleanup(unsubscribe);
});
createEffect(on(() => propsWithDefaults.theme, (theme) => {
createEffect(() => {
const theme = propsWithDefaults.theme;
if (theme !== "system") {

@@ -662,15 +928,23 @@ setActualTheme(theme);

if (typeof window === "undefined") return;
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", ({
const darkMediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
const updateTheme = ({
matches
}) => {
if (matches) setActualTheme("dark");
else setActualTheme("light");
});
}));
setActualTheme(matches ? "dark" : "light");
};
updateTheme(darkMediaQuery);
try {
darkMediaQuery.addEventListener("change", updateTheme);
onCleanup(() => darkMediaQuery.removeEventListener("change", updateTheme));
} catch {
darkMediaQuery.addListener(updateTheme);
onCleanup(() => darkMediaQuery.removeListener(updateTheme));
}
});
createEffect(() => {
if (toastsStore.toasts.length <= 1) setExpanded(false);
if (filteredToasts().length <= 1) setExpanded(false);
});
onMount(() => {
const handleKeyDown = (event) => {
const isHotkeyPressed = propsWithDefaults.hotkey.every((key) => event[key] || event.code === key);
const isHotkeyPressed = propsWithDefaults.hotkey.length > 0 && propsWithDefaults.hotkey.every((key) => event[key] || event.code === key);
if (isHotkeyPressed) {

@@ -683,51 +957,52 @@ setExpanded(true);

document.addEventListener("keydown", handleKeyDown);
onCleanup(() => {
document.removeEventListener("keydown", handleKeyDown);
});
onCleanup(() => document.removeEventListener("keydown", handleKeyDown));
});
createEffect(on(() => listRef, (ref) => {
if (ref) {
onCleanup(() => {
if (lastFocusedElementRef()) {
lastFocusedElementRef()?.focus({
preventScroll: true
});
setLastFocusedElementRef(null);
setIsFocusedWithinRef(false);
}
onCleanup(() => {
if (lastFocusedElementRef()) {
lastFocusedElementRef()?.focus({
preventScroll: true
});
setLastFocusedElementRef(null);
setIsFocusWithinRef(false);
}
}));
return createComponent(Show, {
get when() {
return toastsStore.toasts.length > 0;
},
get children() {
var _el$10 = _tmpl$9();
insert(_el$10, createComponent(For, {
get each() {
return possiblePositions();
},
children: (position, index) => {
const [y, x] = position.split("-");
return (() => {
var _el$11 = _tmpl$10();
_el$11.$$pointerup = () => setInteracting(false);
_el$11.$$pointerdown = () => {
});
return (() => {
var _el$0 = _tmpl$82();
insert(_el$0, createComponent(For, {
get each() {
return possiblePositions();
},
children: (position, index) => {
const [y, x] = position.split("-");
const toastsByPosition = createMemo(() => filteredToasts().filter((toast2) => !toast2.position && index() === 0 || toast2.position === position));
const heightsByPosition = createMemo(() => heights().filter((height) => index() === 0 && !height.position || height.position === position));
return createComponent(Show, {
get when() {
return filteredToasts().length > 0;
},
get children() {
var _el$1 = _tmpl$9();
_el$1.$$pointerup = () => setInteracting(false);
_el$1.$$pointerdown = (event) => {
const isNotDismissible = event.target instanceof HTMLElement && event.target.dataset.dismissible === "false";
if (isNotDismissible) return;
setInteracting(true);
};
_el$11.addEventListener("mouseleave", () => {
_el$1.addEventListener("dragend", () => setExpanded(false));
_el$1.addEventListener("mouseleave", () => {
if (!interacting()) setExpanded(false);
});
_el$11.$$mousemove = () => setExpanded(true);
_el$11.addEventListener("mouseenter", () => setExpanded(true));
_el$11.addEventListener("focus", (event) => {
if (!isFocusedWithinRef()) {
setIsFocusedWithinRef(true);
_el$1.$$mousemove = () => setExpanded(true);
_el$1.addEventListener("mouseenter", () => setExpanded(true));
_el$1.addEventListener("focus", (event) => {
const isNotDismissible = event.target instanceof HTMLElement && event.target.dataset.dismissible === "false";
if (isNotDismissible) return;
if (!isFocusWithinRef()) {
setIsFocusWithinRef(true);
setLastFocusedElementRef(event.relatedTarget);
}
});
_el$11.addEventListener("blur", (event) => {
if (isFocusedWithinRef() && !event.currentTarget.contains(event.relatedTarget)) {
setIsFocusedWithinRef(false);
_el$1.addEventListener("blur", (event) => {
if (isFocusWithinRef() && !event.currentTarget.contains(event.relatedTarget)) {
setIsFocusWithinRef(false);
if (lastFocusedElementRef()) {

@@ -742,35 +1017,29 @@ lastFocusedElementRef()?.focus({

var _ref$2 = listRef;
typeof _ref$2 === "function" ? use(_ref$2, _el$11) : listRef = _el$11;
setAttribute(_el$11, "data-y-position", y);
setAttribute(_el$11, "data-x-position", x);
insert(_el$11, createComponent(For, {
typeof _ref$2 === "function" ? use(_ref$2, _el$1) : listRef = _el$1;
setAttribute(_el$1, "data-y-position", y);
setAttribute(_el$1, "data-x-position", x);
insert(_el$1, createComponent(For, {
get each() {
return toastsStore.toasts.filter((toast2) => !toast2.position && index() === 0 || toast2.position === position);
return toastsByPosition();
},
children: (toast2, index2) => createComponent(Toast, {
get index() {
return index2();
},
children: (toastItem, toastIndex) => createComponent(Toast, {
get icons() {
return propsWithDefaults.icons;
},
toast: toast2,
get index() {
return toastIndex();
},
toast: toastItem,
get defaultRichColors() {
return propsWithDefaults.richColors;
},
get duration() {
return propsWithDefaults.toastOptions?.duration ?? props.duration;
return toastOptions()?.duration ?? propsWithDefaults.duration;
},
get ["class"]() {
return propsWithDefaults.toastOptions?.class;
return toastClassName();
},
get classes() {
return propsWithDefaults.toastOptions?.classes;
get descriptionClassName() {
return toastDescriptionClassName();
},
get cancelButtonStyle() {
return propsWithDefaults.toastOptions?.cancelButtonStyle;
},
get actionButtonStyle() {
return propsWithDefaults.toastOptions?.actionButtonStyle;
},
get descriptionClass() {
return propsWithDefaults.toastOptions?.descriptionClass;
},
get invert() {

@@ -783,3 +1052,3 @@ return Boolean(propsWithDefaults.invert);

get closeButton() {
return Boolean(propsWithDefaults.closeButton);
return toastOptions()?.closeButton ?? propsWithDefaults.closeButton ?? false;
},

@@ -789,17 +1058,27 @@ get interacting() {

},
get position() {
return propsWithDefaults.position;
},
position,
get style() {
return propsWithDefaults.toastOptions?.style;
return toastOptions()?.style;
},
get unstyled() {
return propsWithDefaults.toastOptions?.unstyled;
return toastOptions()?.unstyled;
},
get classNames() {
return toastClassNames();
},
get cancelButtonStyle() {
return toastOptions()?.cancelButtonStyle;
},
get actionButtonStyle() {
return toastOptions()?.actionButtonStyle;
},
get closeButtonAriaLabel() {
return toastOptions()?.closeButtonAriaLabel;
},
removeToast,
get toasts() {
return toastsStore.toasts;
return toastsByPosition();
},
get heights() {
return heights();
return heightsByPosition();
},

@@ -816,2 +1095,5 @@ setHeights,

},
get swipeDirections() {
return propsWithDefaults.swipeDirections;
},
get pauseWhenPageIsHidden() {

@@ -823,14 +1105,12 @@ return propsWithDefaults.pauseWhenPageIsHidden;

effect((_p$) => {
var _v$24 = propsWithDefaults.dir === "auto" ? getDocumentDirection() : propsWithDefaults.dir, _v$25 = propsWithDefaults.class, _v$26 = actualTheme(), _v$27 = propsWithDefaults.richColors, _v$28 = {
"--front-toast-height": `${heights()[0]?.height}px`,
"--offset": typeof propsWithDefaults.offset === "number" ? `${propsWithDefaults.offset}px` : propsWithDefaults.offset || VIEWPORT_OFFSET,
"--width": `${TOAST_WIDTH}px`,
"--gap": `${GAP}px`,
...propsWithDefaults.style
var _v$31 = propsWithDefaults.dir === "auto" ? getDocumentDirection() : propsWithDefaults.dir, _v$32 = className$1(), _v$33 = actualTheme(), _v$34 = {
"--front-toast-height": `${heightsByPosition()[0]?.height ?? 0}px`,
"--gap": `${propsWithDefaults.gap}px`,
...propsWithDefaults.style,
...assignOffset(propsWithDefaults.offset, propsWithDefaults.mobileOffset)
};
_v$24 !== _p$.e && setAttribute(_el$11, "dir", _p$.e = _v$24);
_v$25 !== _p$.t && className(_el$11, _p$.t = _v$25);
_v$26 !== _p$.a && setAttribute(_el$11, "data-theme", _p$.a = _v$26);
_v$27 !== _p$.o && setAttribute(_el$11, "data-rich-colors", _p$.o = _v$27);
_p$.i = style(_el$11, _v$28, _p$.i);
_v$31 !== _p$.e && setAttribute(_el$1, "dir", _p$.e = _v$31);
_v$32 !== _p$.t && className(_el$1, _p$.t = _v$32);
_v$33 !== _p$.a && setAttribute(_el$1, "data-sonner-theme", _p$.a = _v$33);
_p$.o = style(_el$1, _v$34, _p$.o);
return _p$;

@@ -841,14 +1121,13 @@ }, {

a: void 0,
o: void 0,
i: void 0
o: void 0
});
return _el$11;
})();
}
}));
effect(() => setAttribute(_el$10, "aria-label", `Notifications ${hotkeyLabel()}`));
return _el$10;
}
});
};
return _el$1;
}
});
}
}));
effect(() => setAttribute(_el$0, "aria-label", propsWithDefaults.customAriaLabel ?? `${propsWithDefaults.containerAriaLabel} ${hotkeyLabel()}`));
return _el$0;
})();
}
delegateEvents(["pointerdown", "pointerup", "pointermove", "click", "mousemove"]);

@@ -863,2 +1142,2 @@ /*!

export { Toaster, toast };
export { Toaster, toast, useSonner };
+623
-337

@@ -24,6 +24,6 @@ // #style-inject:#style-inject

// src/styles.css
styleInject(':where(html[dir=ltr]),\n:where([data-sonner-toaster][dir=ltr]) {\n --toast-icon-margin-start: -3px;\n --toast-icon-margin-end: 4px;\n --toast-svg-margin-start: -1px;\n --toast-svg-margin-end: 0px;\n --toast-button-margin-start: auto;\n --toast-button-margin-end: 0;\n --toast-close-button-start: 0;\n --toast-close-button-end: unset;\n --toast-close-button-transform: translate(-35%, -35%);\n}\n:where(html[dir=rtl]),\n:where([data-sonner-toaster][dir=rtl]) {\n --toast-icon-margin-start: 4px;\n --toast-icon-margin-end: -3px;\n --toast-svg-margin-start: 0px;\n --toast-svg-margin-end: -1px;\n --toast-button-margin-start: 0;\n --toast-button-margin-end: auto;\n --toast-close-button-start: unset;\n --toast-close-button-end: 0;\n --toast-close-button-transform: translate(35%, -35%);\n}\n:where([data-sonner-toaster]) {\n position: fixed;\n width: var(--width);\n font-family:\n ui-sans-serif,\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n Segoe UI,\n Roboto,\n Helvetica Neue,\n Arial,\n Noto Sans,\n sans-serif,\n Apple Color Emoji,\n Segoe UI Emoji,\n Segoe UI Symbol,\n Noto Color Emoji;\n --gray1: hsl(0, 0%, 99%);\n --gray2: hsl(0, 0%, 97.3%);\n --gray3: hsl(0, 0%, 95.1%);\n --gray4: hsl(0, 0%, 93%);\n --gray5: hsl(0, 0%, 90.9%);\n --gray6: hsl(0, 0%, 88.7%);\n --gray7: hsl(0, 0%, 85.8%);\n --gray8: hsl(0, 0%, 78%);\n --gray9: hsl(0, 0%, 56.1%);\n --gray10: hsl(0, 0%, 52.3%);\n --gray11: hsl(0, 0%, 43.5%);\n --gray12: hsl(0, 0%, 9%);\n --border-radius: 8px;\n box-sizing: border-box;\n padding: 0;\n margin: 0;\n list-style: none;\n outline: none;\n z-index: 999999999;\n}\n:where([data-sonner-toaster][data-x-position=right]) {\n right: max(var(--offset), env(safe-area-inset-right));\n}\n:where([data-sonner-toaster][data-x-position=left]) {\n left: max(var(--offset), env(safe-area-inset-left));\n}\n:where([data-sonner-toaster][data-x-position=center]) {\n left: 50%;\n transform: translateX(-50%);\n}\n:where([data-sonner-toaster][data-y-position=top]) {\n top: max(var(--offset), env(safe-area-inset-top));\n}\n:where([data-sonner-toaster][data-y-position=bottom]) {\n bottom: max(var(--offset), env(safe-area-inset-bottom));\n}\n:where([data-sonner-toast]) {\n --y: translateY(100%);\n --lift-amount: calc(var(--lift) * var(--gap));\n z-index: var(--z-index);\n position: absolute;\n opacity: 0;\n transform: var(--y);\n filter: blur(0);\n touch-action: none;\n transition:\n transform 400ms,\n opacity 400ms,\n height 400ms,\n box-shadow 200ms;\n box-sizing: border-box;\n outline: none;\n overflow-wrap: anywhere;\n}\n:where([data-sonner-toast][data-styled=true]) {\n padding: 16px;\n background: var(--normal-bg);\n border: 1px solid var(--normal-border);\n color: var(--normal-text);\n border-radius: var(--border-radius);\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1);\n width: var(--width);\n font-size: 13px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n:where([data-sonner-toast]:focus-visible) {\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1), 0 0 0 2px rgba(0, 0, 0, 0.2);\n}\n:where([data-sonner-toast][data-y-position=top]) {\n top: 0;\n --y: translateY(-100%);\n --lift: 1;\n --lift-amount: calc(1 * var(--gap));\n}\n:where([data-sonner-toast][data-y-position=bottom]) {\n bottom: 0;\n --y: translateY(100%);\n --lift: -1;\n --lift-amount: calc(var(--lift) * var(--gap));\n}\n:where([data-sonner-toast]) :where([data-description]) {\n font-weight: 400;\n line-height: 1.4;\n color: inherit;\n}\n:where([data-sonner-toast]) :where([data-title]) {\n font-weight: 500;\n line-height: 1.5;\n color: inherit;\n}\n:where([data-sonner-toast]) :where([data-icon]) {\n display: flex;\n height: 16px;\n width: 16px;\n position: relative;\n justify-content: flex-start;\n align-items: center;\n flex-shrink: 0;\n margin-left: var(--toast-icon-margin-start);\n margin-right: var(--toast-icon-margin-end);\n}\n:where([data-sonner-toast][data-promise=true]) :where([data-icon]) > svg {\n opacity: 0;\n transform: scale(0.8);\n transform-origin: center;\n animation: sonner-fade-in 300ms ease forwards;\n}\n:where([data-sonner-toast]) :where([data-icon]) > * {\n flex-shrink: 0;\n}\n:where([data-sonner-toast]) :where([data-icon]) svg {\n margin-left: var(--toast-svg-margin-start);\n margin-right: var(--toast-svg-margin-end);\n}\n:where([data-sonner-toast]) :where([data-content]) {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n[data-sonner-toast][data-styled=true] [data-button] {\n border-radius: 4px;\n padding-left: 8px;\n padding-right: 8px;\n height: 24px;\n font-size: 12px;\n color: var(--normal-bg);\n background: var(--normal-text);\n margin-left: var(--toast-button-margin-start);\n margin-right: var(--toast-button-margin-end);\n border: none;\n cursor: pointer;\n outline: none;\n display: flex;\n align-items: center;\n flex-shrink: 0;\n transition: opacity 400ms, box-shadow 200ms;\n}\n:where([data-sonner-toast]) :where([data-button]):focus-visible {\n box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.4);\n}\n:where([data-sonner-toast]) :where([data-button]):first-of-type {\n margin-left: var(--toast-button-margin-start);\n margin-right: var(--toast-button-margin-end);\n}\n:where([data-sonner-toast]) :where([data-cancel]) {\n color: var(--normal-text);\n background: rgba(0, 0, 0, 0.08);\n}\n:where([data-sonner-toast][data-theme=dark]) :where([data-cancel]) {\n background: rgba(255, 255, 255, 0.3);\n}\n:where([data-sonner-toast]) :where([data-close-button]) {\n position: absolute;\n left: var(--toast-close-button-start);\n right: var(--toast-close-button-end);\n top: 0;\n height: 20px;\n width: 20px;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 0;\n background: var(--gray1);\n color: var(--gray12);\n border: 1px solid var(--gray4);\n transform: var(--toast-close-button-transform);\n border-radius: 50%;\n cursor: pointer;\n z-index: 1;\n transition:\n opacity 100ms,\n background 200ms,\n border-color 200ms;\n}\n:where([data-sonner-toast]) :where([data-close-button]):focus-visible {\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1), 0 0 0 2px rgba(0, 0, 0, 0.2);\n}\n:where([data-sonner-toast]) :where([data-disabled=true]) {\n cursor: not-allowed;\n}\n:where([data-sonner-toast]):hover :where([data-close-button]):hover {\n background: var(--gray2);\n border-color: var(--gray5);\n}\n:where([data-sonner-toast][data-swiping=true])::before {\n content: "";\n position: absolute;\n left: 0;\n right: 0;\n height: 100%;\n z-index: -1;\n}\n:where([data-sonner-toast][data-y-position=top][data-swiping=true])::before {\n bottom: 50%;\n transform: scaleY(3) translateY(50%);\n}\n:where([data-sonner-toast][data-y-position=bottom][data-swiping=true])::before {\n top: 50%;\n transform: scaleY(3) translateY(-50%);\n}\n:where([data-sonner-toast][data-swiping=false][data-removed=true])::before {\n content: "";\n position: absolute;\n inset: 0;\n transform: scaleY(2);\n}\n:where([data-sonner-toast])::after {\n content: "";\n position: absolute;\n left: 0;\n height: calc(var(--gap) + 1px);\n bottom: 100%;\n width: 100%;\n}\n:where([data-sonner-toast][data-mounted=true]) {\n --y: translateY(0);\n opacity: 1;\n}\n:where([data-sonner-toast][data-expanded=false][data-front=false]) {\n --scale: var(--toasts-before) * 0.05 + 1;\n --y: translateY(calc(var(--lift-amount) * var(--toasts-before))) scale(calc(-1 * var(--scale)));\n height: var(--front-toast-height);\n}\n:where([data-sonner-toast]) > * {\n transition: opacity 400ms;\n}\n:where([data-sonner-toast][data-expanded=false][data-front=false][data-styled=true]) > * {\n opacity: 0;\n}\n:where([data-sonner-toast][data-visible=false]) {\n opacity: 0;\n pointer-events: none;\n}\n:where([data-sonner-toast][data-mounted=true][data-expanded=true]) {\n --y: translateY(calc(var(--lift) * var(--offset)));\n height: var(--initial-height);\n}\n:where([data-sonner-toast][data-removed=true][data-front=true][data-swipe-out=false]) {\n --y: translateY(calc(var(--lift) * -100%));\n opacity: 0;\n}\n:where([data-sonner-toast][data-removed=true][data-front=false][data-swipe-out=false][data-expanded=true]) {\n --y: translateY(calc(var(--lift) * var(--offset) + var(--lift) * -100%));\n opacity: 0;\n}\n:where([data-sonner-toast][data-removed=true][data-front=false][data-swipe-out=false][data-expanded=false]) {\n --y: translateY(40%);\n opacity: 0;\n transition: transform 500ms, opacity 200ms;\n}\n:where([data-sonner-toast][data-removed=true][data-front=false])::before {\n height: calc(var(--initial-height) + 20%);\n}\n[data-sonner-toast][data-swiping=true] {\n transform: var(--y) translateY(var(--swipe-amount, 0px));\n transition: none;\n}\n[data-sonner-toast][data-swipe-out=true][data-y-position=bottom],\n[data-sonner-toast][data-swipe-out=true][data-y-position=top] {\n animation: swipe-out 200ms ease-out forwards;\n}\n@keyframes swipe-out {\n from {\n transform: translateY(calc(var(--lift) * var(--offset) + var(--swipe-amount)));\n opacity: 1;\n }\n to {\n transform: translateY(calc(var(--lift) * var(--offset) + var(--swipe-amount) + var(--lift) * -100%));\n opacity: 0;\n }\n}\n@media (max-width: 600px) {\n [data-sonner-toaster] {\n position: fixed;\n --mobile-offset: 16px;\n right: var(--mobile-offset);\n left: var(--mobile-offset);\n width: 100%;\n }\n [data-sonner-toaster] [data-sonner-toast] {\n left: 0;\n right: 0;\n width: calc(100% - var(--mobile-offset) * 2);\n }\n [data-sonner-toaster][data-x-position=left] {\n left: var(--mobile-offset);\n }\n [data-sonner-toaster][data-y-position=bottom] {\n bottom: 20px;\n }\n [data-sonner-toaster][data-y-position=top] {\n top: 20px;\n }\n [data-sonner-toaster][data-x-position=center] {\n left: var(--mobile-offset);\n right: var(--mobile-offset);\n transform: none;\n }\n}\n[data-sonner-toaster][data-theme=light] {\n --normal-bg: #fff;\n --normal-border: var(--gray4);\n --normal-text: var(--gray12);\n --success-bg: hsl(143, 85%, 96%);\n --success-border: hsl(145, 92%, 91%);\n --success-text: hsl(140, 100%, 27%);\n --info-bg: hsl(208, 100%, 97%);\n --info-border: hsl(221, 91%, 91%);\n --info-text: hsl(210, 92%, 45%);\n --warning-bg: hsl(49, 100%, 97%);\n --warning-border: hsl(49, 91%, 91%);\n --warning-text: hsl(31, 92%, 45%);\n --error-bg: hsl(359, 100%, 97%);\n --error-border: hsl(359, 100%, 94%);\n --error-text: hsl(360, 100%, 45%);\n}\n[data-sonner-toaster][data-theme=light] [data-sonner-toast][data-invert=true] {\n --normal-bg: #000;\n --normal-border: hsl(0, 0%, 20%);\n --normal-text: var(--gray1);\n}\n[data-sonner-toaster][data-theme=dark] [data-sonner-toast][data-invert=true] {\n --normal-bg: #fff;\n --normal-border: var(--gray3);\n --normal-text: var(--gray12);\n}\n[data-sonner-toaster][data-theme=dark] {\n --normal-bg: #000;\n --normal-border: hsl(0, 0%, 20%);\n --normal-text: var(--gray1);\n --success-bg: hsl(150, 100%, 6%);\n --success-border: hsl(147, 100%, 12%);\n --success-text: hsl(150, 86%, 65%);\n --info-bg: hsl(215, 100%, 6%);\n --info-border: hsl(223, 100%, 12%);\n --info-text: hsl(216, 87%, 65%);\n --warning-bg: hsl(64, 100%, 6%);\n --warning-border: hsl(60, 100%, 12%);\n --warning-text: hsl(46, 87%, 65%);\n --error-bg: hsl(358, 76%, 10%);\n --error-border: hsl(357, 89%, 16%);\n --error-text: hsl(358, 100%, 81%);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=success] {\n background: var(--success-bg);\n border-color: var(--success-border);\n color: var(--success-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=success] [data-close-button] {\n background: var(--success-bg);\n border-color: var(--success-border);\n color: var(--success-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=info] {\n background: var(--info-bg);\n border-color: var(--info-border);\n color: var(--info-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=info] [data-close-button] {\n background: var(--info-bg);\n border-color: var(--info-border);\n color: var(--info-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=warning] {\n background: var(--warning-bg);\n border-color: var(--warning-border);\n color: var(--warning-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=warning] [data-close-button] {\n background: var(--warning-bg);\n border-color: var(--warning-border);\n color: var(--warning-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=error] {\n background: var(--error-bg);\n border-color: var(--error-border);\n color: var(--error-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=error] [data-close-button] {\n background: var(--error-bg);\n border-color: var(--error-border);\n color: var(--error-text);\n}\n.sonner-loading-wrapper {\n --size: 16px;\n height: var(--size);\n width: var(--size);\n position: absolute;\n inset: 0;\n z-index: 10;\n}\n.sonner-loading-wrapper[data-visible=false] {\n transform-origin: center;\n animation: sonner-fade-out 0.2s ease forwards;\n}\n.sonner-spinner {\n position: relative;\n top: 50%;\n left: 50%;\n height: var(--size);\n width: var(--size);\n}\n.sonner-loading-bar {\n animation: sonner-spin 1.2s linear infinite;\n background: var(--gray11);\n border-radius: 6px;\n height: 8%;\n left: -10%;\n position: absolute;\n top: -3.9%;\n width: 24%;\n}\n.sonner-loading-bar:nth-child(1) {\n animation-delay: -1.2s;\n transform: rotate(0.0001deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(2) {\n animation-delay: -1.1s;\n transform: rotate(30deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(3) {\n animation-delay: -1s;\n transform: rotate(60deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(4) {\n animation-delay: -0.9s;\n transform: rotate(90deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(5) {\n animation-delay: -0.8s;\n transform: rotate(120deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(6) {\n animation-delay: -0.7s;\n transform: rotate(150deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(7) {\n animation-delay: -0.6s;\n transform: rotate(180deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(8) {\n animation-delay: -0.5s;\n transform: rotate(210deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(9) {\n animation-delay: -0.4s;\n transform: rotate(240deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(10) {\n animation-delay: -0.3s;\n transform: rotate(270deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(11) {\n animation-delay: -0.2s;\n transform: rotate(300deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(12) {\n animation-delay: -0.1s;\n transform: rotate(330deg) translate(146%);\n}\n@keyframes sonner-fade-in {\n 0% {\n opacity: 0;\n transform: scale(0.8);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n}\n@keyframes sonner-fade-out {\n 0% {\n opacity: 1;\n transform: scale(1);\n }\n 100% {\n opacity: 0;\n transform: scale(0.8);\n }\n}\n@keyframes sonner-spin {\n 0% {\n opacity: 1;\n }\n 100% {\n opacity: 0.15;\n }\n}\n@media (prefers-reduced-motion) {\n [data-sonner-toast],\n [data-sonner-toast] > *,\n .sonner-loading-bar {\n transition: none !important;\n animation: none !important;\n }\n}\n.sonner-loader {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n transform-origin: center;\n transition: opacity 200ms, transform 200ms;\n}\n.sonner-loader[data-visible=false] {\n opacity: 0;\n transform: scale(0.8) translate(-50%, -50%);\n}\n');
styleInject('html[dir=ltr],\n[data-sonner-toaster][dir=ltr] {\n --toast-icon-margin-start: -3px;\n --toast-icon-margin-end: 4px;\n --toast-svg-margin-start: -1px;\n --toast-svg-margin-end: 0px;\n --toast-button-margin-start: auto;\n --toast-button-margin-end: 0;\n --toast-close-button-start: 0;\n --toast-close-button-end: unset;\n --toast-close-button-transform: translate(-35%, -35%);\n}\nhtml[dir=rtl],\n[data-sonner-toaster][dir=rtl] {\n --toast-icon-margin-start: 4px;\n --toast-icon-margin-end: -3px;\n --toast-svg-margin-start: 0px;\n --toast-svg-margin-end: -1px;\n --toast-button-margin-start: 0;\n --toast-button-margin-end: auto;\n --toast-close-button-start: unset;\n --toast-close-button-end: 0;\n --toast-close-button-transform: translate(35%, -35%);\n}\n[data-sonner-toaster] {\n position: fixed;\n width: var(--width);\n font-family:\n ui-sans-serif,\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n Segoe UI,\n Roboto,\n Helvetica Neue,\n Arial,\n Noto Sans,\n sans-serif,\n Apple Color Emoji,\n Segoe UI Emoji,\n Segoe UI Symbol,\n Noto Color Emoji;\n --gray1: hsl(0, 0%, 99%);\n --gray2: hsl(0, 0%, 97.3%);\n --gray3: hsl(0, 0%, 95.1%);\n --gray4: hsl(0, 0%, 93%);\n --gray5: hsl(0, 0%, 90.9%);\n --gray6: hsl(0, 0%, 88.7%);\n --gray7: hsl(0, 0%, 85.8%);\n --gray8: hsl(0, 0%, 78%);\n --gray9: hsl(0, 0%, 56.1%);\n --gray10: hsl(0, 0%, 52.3%);\n --gray11: hsl(0, 0%, 43.5%);\n --gray12: hsl(0, 0%, 9%);\n --border-radius: 8px;\n box-sizing: border-box;\n padding: 0;\n margin: 0;\n list-style: none;\n outline: none;\n z-index: 999999999;\n transition: transform 400ms ease;\n}\n@media (hover: none) and (pointer: coarse) {\n [data-sonner-toaster][data-lifted=true] {\n transform: none;\n }\n}\n[data-sonner-toaster][data-x-position=right] {\n right: var(--offset-right);\n}\n[data-sonner-toaster][data-x-position=left] {\n left: var(--offset-left);\n}\n[data-sonner-toaster][data-x-position=center] {\n left: 50%;\n transform: translateX(-50%);\n}\n[data-sonner-toaster][data-y-position=top] {\n top: var(--offset-top);\n}\n[data-sonner-toaster][data-y-position=bottom] {\n bottom: var(--offset-bottom);\n}\n[data-sonner-toast] {\n --y: translateY(100%);\n --lift-amount: calc(var(--lift) * var(--gap));\n z-index: var(--z-index);\n position: absolute;\n opacity: 0;\n transform: var(--y);\n touch-action: none;\n transition:\n transform 400ms,\n opacity 400ms,\n height 400ms,\n box-shadow 200ms;\n box-sizing: border-box;\n outline: none;\n overflow-wrap: anywhere;\n}\n[data-sonner-toast][data-styled=true] {\n padding: 16px;\n background: var(--normal-bg);\n border: 1px solid var(--normal-border);\n color: var(--normal-text);\n border-radius: var(--border-radius);\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1);\n width: var(--width);\n font-size: 13px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n[data-sonner-toast]:focus-visible {\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1), 0 0 0 2px rgba(0, 0, 0, 0.2);\n}\n[data-sonner-toast][data-y-position=top] {\n top: 0;\n --y: translateY(-100%);\n --lift: 1;\n --lift-amount: calc(1 * var(--gap));\n}\n[data-sonner-toast][data-y-position=bottom] {\n bottom: 0;\n --y: translateY(100%);\n --lift: -1;\n --lift-amount: calc(var(--lift) * var(--gap));\n}\n[data-sonner-toast][data-styled=true] [data-description] {\n font-weight: 400;\n line-height: 1.4;\n color: #3f3f3f;\n}\n[data-rich-colors=true][data-sonner-toast][data-styled=true] [data-description] {\n color: inherit;\n}\n[data-sonner-toaster][data-sonner-theme=dark] [data-description] {\n color: hsl(0, 0%, 91%);\n}\n[data-sonner-toast][data-styled=true] [data-title] {\n font-weight: 500;\n line-height: 1.5;\n color: inherit;\n}\n[data-sonner-toast][data-styled=true] [data-icon] {\n display: flex;\n height: 16px;\n width: 16px;\n position: relative;\n justify-content: flex-start;\n align-items: center;\n flex-shrink: 0;\n margin-left: var(--toast-icon-margin-start);\n margin-right: var(--toast-icon-margin-end);\n}\n[data-sonner-toast][data-promise=true] [data-icon] > svg {\n opacity: 0;\n transform: scale(0.8);\n transform-origin: center;\n animation: sonner-fade-in 300ms ease forwards;\n}\n[data-sonner-toast][data-styled=true] [data-icon] > * {\n flex-shrink: 0;\n}\n[data-sonner-toast][data-styled=true] [data-icon] svg {\n margin-left: var(--toast-svg-margin-start);\n margin-right: var(--toast-svg-margin-end);\n}\n[data-sonner-toast][data-styled=true] [data-content] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n[data-sonner-toast][data-styled=true] [data-button] {\n border-radius: 4px;\n padding-left: 8px;\n padding-right: 8px;\n height: 24px;\n font-size: 12px;\n color: var(--normal-bg);\n background: var(--normal-text);\n margin-left: var(--toast-button-margin-start);\n margin-right: var(--toast-button-margin-end);\n border: none;\n font-weight: 500;\n cursor: pointer;\n outline: none;\n display: flex;\n align-items: center;\n flex-shrink: 0;\n transition: opacity 400ms, box-shadow 200ms;\n}\n[data-sonner-toast][data-styled=true] [data-button]:focus-visible {\n box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.4);\n}\n[data-sonner-toast][data-styled=true] [data-button]:first-of-type {\n margin-left: var(--toast-button-margin-start);\n margin-right: var(--toast-button-margin-end);\n}\n[data-sonner-toast][data-styled=true] [data-cancel] {\n color: var(--normal-text);\n background: rgba(0, 0, 0, 0.08);\n}\n[data-sonner-toaster][data-sonner-theme=dark] [data-sonner-toast][data-styled=true] [data-cancel] {\n background: rgba(255, 255, 255, 0.3);\n}\n[data-sonner-toast][data-styled=true] [data-close-button] {\n position: absolute;\n left: var(--toast-close-button-start);\n right: var(--toast-close-button-end);\n top: 0;\n height: 20px;\n width: 20px;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 0;\n color: var(--normal-text);\n background: var(--normal-bg);\n border: 1px solid var(--normal-border);\n transform: var(--toast-close-button-transform);\n border-radius: 50%;\n cursor: pointer;\n z-index: 1;\n transition:\n opacity 100ms,\n background 200ms,\n border-color 200ms;\n}\n[data-sonner-toast][data-styled=true] [data-close-button]:focus-visible {\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1), 0 0 0 2px rgba(0, 0, 0, 0.2);\n}\n[data-sonner-toast][data-styled=true] [data-disabled=true] {\n cursor: not-allowed;\n}\n[data-sonner-toast][data-styled=true]:hover [data-close-button]:hover {\n background: var(--gray2);\n border-color: var(--gray5);\n}\n[data-sonner-toast][data-swiping=true]::before {\n content: "";\n position: absolute;\n left: -100%;\n right: -100%;\n height: 100%;\n z-index: -1;\n}\n[data-sonner-toast][data-y-position=top][data-swiping=true]::before {\n bottom: 50%;\n transform: scaleY(3) translateY(50%);\n}\n[data-sonner-toast][data-y-position=bottom][data-swiping=true]::before {\n top: 50%;\n transform: scaleY(3) translateY(-50%);\n}\n[data-sonner-toast][data-swiping=false][data-removed=true]::before {\n content: "";\n position: absolute;\n inset: 0;\n transform: scaleY(2);\n}\n[data-sonner-toast][data-expanded=true]::after {\n content: "";\n position: absolute;\n left: 0;\n height: calc(var(--gap) + 1px);\n bottom: 100%;\n width: 100%;\n}\n[data-sonner-toast][data-mounted=true] {\n --y: translateY(0);\n opacity: 1;\n}\n[data-sonner-toast][data-expanded=false][data-front=false] {\n --scale: var(--toasts-before) * 0.05 + 1;\n --y: translateY(calc(var(--lift-amount) * var(--toasts-before))) scale(calc(-1 * var(--scale)));\n height: var(--front-toast-height);\n}\n[data-sonner-toast] > * {\n transition: opacity 400ms;\n}\n[data-sonner-toast][data-x-position=right] {\n right: 0;\n}\n[data-sonner-toast][data-x-position=left] {\n left: 0;\n}\n[data-sonner-toast][data-expanded=false][data-front=false][data-styled=true] > * {\n opacity: 0;\n}\n[data-sonner-toast][data-visible=false] {\n opacity: 0;\n pointer-events: none;\n}\n[data-sonner-toast][data-mounted=true][data-expanded=true] {\n --y: translateY(calc(var(--lift) * var(--offset)));\n height: var(--initial-height);\n}\n[data-sonner-toast][data-removed=true][data-front=true][data-swipe-out=false] {\n --y: translateY(calc(var(--lift) * -100%));\n opacity: 0;\n}\n[data-sonner-toast][data-removed=true][data-front=false][data-swipe-out=false][data-expanded=true] {\n --y: translateY(calc(var(--lift) * var(--offset) + var(--lift) * -100%));\n opacity: 0;\n}\n[data-sonner-toast][data-removed=true][data-front=false][data-swipe-out=false][data-expanded=false] {\n --y: translateY(40%);\n opacity: 0;\n transition: transform 500ms, opacity 200ms;\n}\n[data-sonner-toast][data-removed=true][data-front=false]::before {\n height: calc(var(--initial-height) + 20%);\n}\n[data-sonner-toast][data-swiping=true] {\n transform: var(--y) translateY(var(--swipe-amount-y, 0px)) translateX(var(--swipe-amount-x, 0px));\n transition: none;\n}\n[data-sonner-toast][data-swiped=true] {\n -webkit-user-select: none;\n user-select: none;\n}\n[data-sonner-toast][data-swipe-out=true][data-y-position=bottom],\n[data-sonner-toast][data-swipe-out=true][data-y-position=top] {\n animation-duration: 200ms;\n animation-timing-function: ease-out;\n animation-fill-mode: forwards;\n}\n[data-sonner-toast][data-swipe-out=true][data-swipe-direction=left] {\n animation-name: swipe-out-left;\n}\n[data-sonner-toast][data-swipe-out=true][data-swipe-direction=right] {\n animation-name: swipe-out-right;\n}\n[data-sonner-toast][data-swipe-out=true][data-swipe-direction=up] {\n animation-name: swipe-out-up;\n}\n[data-sonner-toast][data-swipe-out=true][data-swipe-direction=down] {\n animation-name: swipe-out-down;\n}\n@keyframes swipe-out-left {\n from {\n transform: var(--y) translateX(var(--swipe-amount-x));\n opacity: 1;\n }\n to {\n transform: var(--y) translateX(calc(var(--swipe-amount-x) - 100%));\n opacity: 0;\n }\n}\n@keyframes swipe-out-right {\n from {\n transform: var(--y) translateX(var(--swipe-amount-x));\n opacity: 1;\n }\n to {\n transform: var(--y) translateX(calc(var(--swipe-amount-x) + 100%));\n opacity: 0;\n }\n}\n@keyframes swipe-out-up {\n from {\n transform: var(--y) translateY(var(--swipe-amount-y));\n opacity: 1;\n }\n to {\n transform: var(--y) translateY(calc(var(--swipe-amount-y) - 100%));\n opacity: 0;\n }\n}\n@keyframes swipe-out-down {\n from {\n transform: var(--y) translateY(var(--swipe-amount-y));\n opacity: 1;\n }\n to {\n transform: var(--y) translateY(calc(var(--swipe-amount-y) + 100%));\n opacity: 0;\n }\n}\n@media (max-width: 600px) {\n [data-sonner-toaster] {\n position: fixed;\n right: var(--mobile-offset-right);\n left: var(--mobile-offset-left);\n width: 100%;\n }\n [data-sonner-toaster][dir=rtl] {\n left: calc(var(--mobile-offset-left) * -1);\n }\n [data-sonner-toaster] [data-sonner-toast] {\n left: 0;\n right: 0;\n width: calc(100% - var(--mobile-offset-left) * 2);\n }\n [data-sonner-toaster][data-x-position=left] {\n left: var(--mobile-offset-left);\n }\n [data-sonner-toaster][data-y-position=bottom] {\n bottom: var(--mobile-offset-bottom);\n }\n [data-sonner-toaster][data-y-position=top] {\n top: var(--mobile-offset-top);\n }\n [data-sonner-toaster][data-x-position=center] {\n left: var(--mobile-offset-left);\n right: var(--mobile-offset-right);\n transform: none;\n }\n}\n[data-sonner-toaster][data-sonner-theme=light] {\n --normal-bg: #fff;\n --normal-border: var(--gray4);\n --normal-text: var(--gray12);\n --success-bg: hsl(143, 85%, 96%);\n --success-border: hsl(145, 92%, 87%);\n --success-text: hsl(140, 100%, 27%);\n --info-bg: hsl(208, 100%, 97%);\n --info-border: hsl(221, 91%, 93%);\n --info-text: hsl(210, 92%, 45%);\n --warning-bg: hsl(49, 100%, 97%);\n --warning-border: hsl(49, 91%, 84%);\n --warning-text: hsl(31, 92%, 45%);\n --error-bg: hsl(359, 100%, 97%);\n --error-border: hsl(359, 100%, 94%);\n --error-text: hsl(360, 100%, 45%);\n}\n[data-sonner-toaster][data-sonner-theme=light] [data-sonner-toast][data-invert=true] {\n --normal-bg: #000;\n --normal-border: hsl(0, 0%, 20%);\n --normal-text: var(--gray1);\n}\n[data-sonner-toaster][data-sonner-theme=dark] [data-sonner-toast][data-invert=true] {\n --normal-bg: #fff;\n --normal-border: var(--gray3);\n --normal-text: var(--gray12);\n}\n[data-sonner-toaster][data-sonner-theme=dark] {\n --normal-bg: #000;\n --normal-bg-hover: hsl(0, 0%, 12%);\n --normal-border: hsl(0, 0%, 20%);\n --normal-border-hover: hsl(0, 0%, 25%);\n --normal-text: var(--gray1);\n --success-bg: hsl(150, 100%, 6%);\n --success-border: hsl(147, 100%, 12%);\n --success-text: hsl(150, 86%, 65%);\n --info-bg: hsl(215, 100%, 6%);\n --info-border: hsl(223, 43%, 17%);\n --info-text: hsl(216, 87%, 65%);\n --warning-bg: hsl(64, 100%, 6%);\n --warning-border: hsl(60, 100%, 9%);\n --warning-text: hsl(46, 87%, 65%);\n --error-bg: hsl(358, 76%, 10%);\n --error-border: hsl(357, 89%, 16%);\n --error-text: hsl(358, 100%, 81%);\n}\n[data-sonner-toaster][data-sonner-theme=dark] [data-sonner-toast] [data-close-button] {\n background: var(--normal-bg);\n border-color: var(--normal-border);\n color: var(--normal-text);\n}\n[data-sonner-toaster][data-sonner-theme=dark] [data-sonner-toast] [data-close-button]:hover {\n background: var(--normal-bg-hover);\n border-color: var(--normal-border-hover);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=success] {\n background: var(--success-bg);\n border-color: var(--success-border);\n color: var(--success-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=success] [data-close-button] {\n background: var(--success-bg);\n border-color: var(--success-border);\n color: var(--success-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=info] {\n background: var(--info-bg);\n border-color: var(--info-border);\n color: var(--info-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=info] [data-close-button] {\n background: var(--info-bg);\n border-color: var(--info-border);\n color: var(--info-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=warning] {\n background: var(--warning-bg);\n border-color: var(--warning-border);\n color: var(--warning-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=warning] [data-close-button] {\n background: var(--warning-bg);\n border-color: var(--warning-border);\n color: var(--warning-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=error] {\n background: var(--error-bg);\n border-color: var(--error-border);\n color: var(--error-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=error] [data-close-button] {\n background: var(--error-bg);\n border-color: var(--error-border);\n color: var(--error-text);\n}\n.sonner-loading-wrapper {\n --size: 16px;\n height: var(--size);\n width: var(--size);\n position: absolute;\n inset: 0;\n z-index: 10;\n}\n.sonner-loading-wrapper[data-visible=false] {\n transform-origin: center;\n animation: sonner-fade-out 0.2s ease forwards;\n}\n.sonner-spinner {\n position: relative;\n top: 50%;\n left: 50%;\n height: var(--size);\n width: var(--size);\n}\n.sonner-loading-bar {\n animation: sonner-spin 1.2s linear infinite;\n background: var(--gray11);\n border-radius: 6px;\n height: 8%;\n left: -10%;\n position: absolute;\n top: -3.9%;\n width: 24%;\n}\n.sonner-loading-bar:nth-child(1) {\n animation-delay: -1.2s;\n transform: rotate(0.0001deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(2) {\n animation-delay: -1.1s;\n transform: rotate(30deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(3) {\n animation-delay: -1s;\n transform: rotate(60deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(4) {\n animation-delay: -0.9s;\n transform: rotate(90deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(5) {\n animation-delay: -0.8s;\n transform: rotate(120deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(6) {\n animation-delay: -0.7s;\n transform: rotate(150deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(7) {\n animation-delay: -0.6s;\n transform: rotate(180deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(8) {\n animation-delay: -0.5s;\n transform: rotate(210deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(9) {\n animation-delay: -0.4s;\n transform: rotate(240deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(10) {\n animation-delay: -0.3s;\n transform: rotate(270deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(11) {\n animation-delay: -0.2s;\n transform: rotate(300deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(12) {\n animation-delay: -0.1s;\n transform: rotate(330deg) translate(146%);\n}\n@keyframes sonner-fade-in {\n 0% {\n opacity: 0;\n transform: scale(0.8);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n}\n@keyframes sonner-fade-out {\n 0% {\n opacity: 1;\n transform: scale(1);\n }\n 100% {\n opacity: 0;\n transform: scale(0.8);\n }\n}\n@keyframes sonner-spin {\n 0% {\n opacity: 1;\n }\n 100% {\n opacity: 0.15;\n }\n}\n@media (prefers-reduced-motion) {\n [data-sonner-toast],\n [data-sonner-toast] > *,\n .sonner-loading-bar {\n transition: none !important;\n animation: none !important;\n }\n}\n.sonner-loader {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n transform-origin: center;\n transition: opacity 200ms, transform 200ms;\n}\n.sonner-loader[data-visible=false] {\n opacity: 0;\n transform: scale(0.8) translate(-50%, -50%);\n}\n');
// src/index.tsx
import { For as For2, Show, createEffect, createSignal as createSignal2, mergeProps, on, onCleanup as onCleanup2, onMount as onMount2 } from "solid-js";
import { For as For2, Show, createEffect, createMemo, createSignal as createSignal2, mergeProps, on, onCleanup as onCleanup2, onMount as onMount2 } from "solid-js";
import { createStore, produce, reconcile } from "solid-js/store";

@@ -35,31 +35,43 @@

function Loader(props) {
return <div class="sonner-loading-wrapper" data-visible={props.visible}><div class="sonner-spinner"><For each={bars}>{() => <div class="sonner-loading-bar" />}</For></div></div>;
return <div class={["sonner-loading-wrapper", props.class ?? props.className].filter(Boolean).join(" ")} data-visible={props.visible}>
<div class="sonner-spinner">
<For each={bars}>{(_, i) => <div class="sonner-loading-bar" data-index={i()} />}</For>
</div>
</div>;
}
function SuccessIcon() {
return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" height="20" width="20"><path
return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" height="20" width="20">
<path
fill-rule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
clip-rule="evenodd"
/></svg>;
/>
</svg>;
}
function WarningIcon() {
return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" height="20" width="20"><path
return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" height="20" width="20">
<path
fill-rule="evenodd"
d="M9.401 3.003c1.155-2 4.043-2 5.197 0l7.355 12.748c1.154 2-.29 4.5-2.599 4.5H4.645c-2.309 0-3.752-2.5-2.598-4.5L9.4 3.003zM12 8.25a.75.75 0 01.75.75v3.75a.75.75 0 01-1.5 0V9a.75.75 0 01.75-.75zm0 8.25a.75.75 0 100-1.5.75.75 0 000 1.5z"
clip-rule="evenodd"
/></svg>;
/>
</svg>;
}
function InfoIcon() {
return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" height="20" width="20"><path
return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" height="20" width="20">
<path
fill-rule="evenodd"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z"
clip-rule="evenodd"
/></svg>;
/>
</svg>;
}
function ErrorIcon() {
return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" height="20" width="20"><path
return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" height="20" width="20">
<path
fill-rule="evenodd"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-5a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 5zm0 10a1 1 0 100-2 1 1 0 000 2z"
clip-rule="evenodd"
/></svg>;
/>
</svg>;
}

@@ -69,9 +81,9 @@ function getAsset(type) {

case "success":
return SuccessIcon;
return <SuccessIcon />;
case "info":
return InfoIcon;
return <InfoIcon />;
case "warning":
return WarningIcon;
return <WarningIcon />;
case "error":
return ErrorIcon;
return <ErrorIcon />;
default:

@@ -81,13 +93,46 @@ return null;

}
function CloseIcon() {
return <svg
xmlns="http://www.w3.org/2000/svg"
width="12"
height="12"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
>
<line x1="18" y1="6" x2="6" y2="18" />
<line x1="6" y1="6" x2="18" y2="18" />
</svg>;
}
// src/primitives.ts
import { createSignal, onCleanup, onMount } from "solid-js";
function useIsDocumentHidden() {
const [isDocumentHidden, setIsDocumentHidden] = createSignal(typeof document !== "undefined" ? document.hidden : false);
onMount(() => {
const callback = () => {
setIsDocumentHidden(document.hidden);
};
document.addEventListener("visibilitychange", callback);
onCleanup(() => {
document.removeEventListener("visibilitychange", callback);
});
});
return isDocumentHidden;
}
// src/state.ts
var toastsCounter = 0;
var toastsCounter = 1;
var Observer = class {
subscribers;
toasts;
dismissedToasts;
constructor() {
this.subscribers = [];
this.toasts = [];
this.dismissedToasts = /* @__PURE__ */ new Set();
}
// We use arrow functions to maintain the correct `this` reference
subscribe = (subscriber) => {

@@ -109,11 +154,21 @@ this.subscribers.push(subscriber);

const { message, ...rest } = data;
const id = typeof data?.id === "number" || data.id && data.id?.length > 0 ? data.id : toastsCounter++;
const hasStringId = typeof data.id === "string" && data.id.length > 0;
const id = typeof data.id === "number" || hasStringId ? data.id : toastsCounter++;
const alreadyExists = this.toasts.find((toast2) => {
return toast2.id === id;
});
const dismissible = data.dismissible === void 0 ? true : data.dismissible;
if (this.dismissedToasts.has(id))
this.dismissedToasts.delete(id);
if (alreadyExists) {
this.toasts = this.toasts.map((toast2) => {
if (toast2.id === id) {
this.publish({ ...toast2, ...data, id, title: message });
return { ...toast2, ...data, id, title: message };
this.publish({ ...toast2, ...data, id, title: message, dismissible });
return {
...toast2,
...data,
id,
dismissible,
title: message
};
}

@@ -123,3 +178,3 @@ return toast2;

} else {
this.addToast({ title: message, ...rest, id });
this.addToast({ title: message, ...rest, dismissible, id });
}

@@ -129,8 +184,13 @@ return id;

dismiss = (id) => {
if (!id) {
if (id) {
this.dismissedToasts.add(id);
requestAnimationFrame(() => {
this.subscribers.forEach((subscriber) => subscriber({ id, dismiss: true }));
});
} else {
this.toasts.forEach((toast2) => {
this.dismissedToasts.add(toast2.id);
this.subscribers.forEach((subscriber) => subscriber({ id: toast2.id, dismiss: true }));
});
}
this.subscribers.forEach((subscriber) => subscriber({ id, dismiss: true }));
return id;

@@ -153,6 +213,8 @@ };

};
loading = (message, data) => {
return this.create({ ...data, type: "loading", message });
};
promise = (promise, data) => {
if (!data) {
if (!data)
return;
}
let id;

@@ -164,22 +226,41 @@ if (data.loading !== void 0) {

type: "loading",
message: data.loading
message: data.loading,
description: typeof data.description !== "function" ? data.description : void 0
});
}
const p = promise instanceof Promise ? promise : promise();
const p = Promise.resolve(typeof promise === "function" ? promise() : promise);
let shouldDismiss = id !== void 0;
p.then((response) => {
if (response && typeof response.ok === "boolean" && !response.ok) {
let result;
const originalPromise = p.then(async (response) => {
result = ["resolve", response];
if (isValidElement(response)) {
shouldDismiss = false;
const message = typeof data.error === "function" ? data.error(`HTTP error! status: ${response.status}`) : data.error;
this.create({ id, type: "error", message });
this.create({ id, type: "default", message: response });
} else if (isHttpResponse(response) && !response.ok) {
shouldDismiss = false;
const promiseData = typeof data.error === "function" ? await data.error(`HTTP error! status: ${response.status}`) : data.error;
const description = typeof data.description === "function" ? await data.description(`HTTP error! status: ${response.status}`) : data.description;
const toastSettings = isExtendedResult(promiseData) ? promiseData : { message: promiseData };
this.create({ id, type: "error", description, ...toastSettings });
} else if (response instanceof Error) {
shouldDismiss = false;
const promiseData = typeof data.error === "function" ? await data.error(response) : data.error;
const description = typeof data.description === "function" ? await data.description(response) : data.description;
const toastSettings = isExtendedResult(promiseData) ? promiseData : { message: promiseData };
this.create({ id, type: "error", description, ...toastSettings });
} else if (data.success !== void 0) {
shouldDismiss = false;
const message = typeof data.success === "function" ? data.success(response) : data.success;
this.create({ id, type: "success", message });
const promiseData = typeof data.success === "function" ? await data.success(response) : data.success;
const description = typeof data.description === "function" ? await data.description(response) : data.description;
const toastSettings = isExtendedResult(promiseData) ? promiseData : { message: promiseData };
this.create({ id, type: "success", description, ...toastSettings });
}
}).catch((error) => {
}).catch(async (error) => {
result = ["reject", error];
if (data.error !== void 0) {
shouldDismiss = false;
const message = typeof data.error === "function" ? data.error(error) : data.error;
this.create({ id, type: "error", message });
const promiseData = typeof data.error === "function" ? await data.error(error) : data.error;
const description = typeof data.description === "function" ? await data.description(error) : data.description;
const toastSettings = isExtendedResult(promiseData) ? promiseData : { message: promiseData };
this.create({ id, type: "error", description, ...toastSettings });
}

@@ -193,14 +274,32 @@ }).finally(() => {

});
return id;
const unwrap = () => new Promise((resolve, reject) => {
originalPromise.then(() => {
if (result[0] === "reject")
reject(result[1]);
else
resolve(result[1]);
}).catch(reject);
});
if (typeof id !== "string" && typeof id !== "number")
return { unwrap };
return Object.assign(id, { unwrap });
};
loading = (message, data) => {
return this.create({ ...data, type: "loading", message });
};
// We can't provide the toast we just created as a prop as we didn't create it yet, so we can create a default toast object, I just don't know how to use function in argument when calling()?
custom = (jsx, data) => {
const id = data?.id || toastsCounter++;
this.publish({ jsx: jsx(id), id, ...data });
this.create({ jsx: jsx(id), ...data, id });
return id;
};
getActiveToasts = () => {
return this.toasts.filter((toast2) => !this.dismissedToasts.has(toast2.id));
};
};
function isHttpResponse(data) {
return data && typeof data === "object" && "ok" in data && typeof data.ok === "boolean" && "status" in data && typeof data.status === "number";
}
function isExtendedResult(value) {
return typeof value === "object" && value !== null && "message" in value;
}
function isValidElement(value) {
return typeof Node !== "undefined" && value instanceof Node;
}
var ToastState = new Observer();

@@ -217,28 +316,26 @@ function toastFunction(message, data) {

var basicToast = toastFunction;
var toast = Object.assign(basicToast, {
success: ToastState.success,
info: ToastState.info,
warning: ToastState.warning,
error: ToastState.error,
custom: ToastState.custom,
message: ToastState.message,
promise: ToastState.promise,
dismiss: ToastState.dismiss,
loading: ToastState.loading
});
var getHistory = () => ToastState.toasts;
var getToasts = () => ToastState.getActiveToasts();
var toast = Object.assign(
basicToast,
{
success: ToastState.success,
info: ToastState.info,
warning: ToastState.warning,
error: ToastState.error,
custom: ToastState.custom,
message: ToastState.message,
promise: ToastState.promise,
dismiss: ToastState.dismiss,
loading: ToastState.loading
},
{
getHistory,
getToasts
}
);
// src/primitives.ts
import { createSignal, onCleanup, onMount } from "solid-js";
function useIsDocumentHidden() {
const [isDocumentHidden, setIsDocumentHidden] = createSignal(false);
onMount(() => {
const callback = () => {
setIsDocumentHidden(document.hidden);
};
document.addEventListener("visibilitychange", callback);
onCleanup(() => {
window.removeEventListener("visibilitychange", callback);
});
});
return isDocumentHidden;
// src/types.ts
function isAction(action) {
return typeof action === "object" && action !== null && "label" in action;
}

@@ -248,12 +345,99 @@

var VISIBLE_TOASTS_AMOUNT = 3;
var VIEWPORT_OFFSET = "32px";
var VIEWPORT_OFFSET = "24px";
var MOBILE_VIEWPORT_OFFSET = "16px";
var TOAST_LIFETIME = 4e3;
var TOAST_WIDTH = 356;
var GAP = 14;
var SWIPE_TRESHOLD = 20;
var SWIPE_THRESHOLD = 45;
var TIME_BEFORE_UNMOUNT = 200;
function _cn(...classes) {
function cn(...classes) {
return classes.filter(Boolean).join(" ");
}
var Toast = (props) => {
function resolveContent(content) {
return typeof content === "function" ? content() : content;
}
function getDefaultSwipeDirections(position) {
const [y, x] = position.split("-");
const directions = [];
if (y)
directions.push(y);
if (x)
directions.push(x);
return directions;
}
function getDocumentDirection() {
if (typeof window === "undefined" || typeof document === "undefined")
return "ltr";
const dirAttribute = document.documentElement.getAttribute("dir");
if (dirAttribute === "auto" || !dirAttribute)
return window.getComputedStyle(document.documentElement).direction;
return dirAttribute;
}
function assignOffset(defaultOffset, mobileOffset) {
const styles = {};
[defaultOffset, mobileOffset].forEach((offset, index) => {
const isMobile = index === 1;
const prefix = isMobile ? "--mobile-offset" : "--offset";
const defaultValue = isMobile ? MOBILE_VIEWPORT_OFFSET : VIEWPORT_OFFSET;
const assignAll = (value) => {
for (const key of ["top", "right", "bottom", "left"])
styles[`${prefix}-${key}`] = typeof value === "number" ? `${value}px` : value;
};
if (typeof offset === "number" || typeof offset === "string") {
assignAll(offset);
return;
}
if (typeof offset === "object" && offset !== null) {
for (const key of ["top", "right", "bottom", "left"]) {
const value = offset[key];
styles[`${prefix}-${key}`] = value === void 0 ? defaultValue : typeof value === "number" ? `${value}px` : value;
}
return;
}
assignAll(defaultValue);
});
return styles;
}
function mergeClassNames(classNames, legacy) {
return classNames ?? legacy;
}
function mergeDescriptionClassName(descriptionClassName, legacy) {
return descriptionClassName ?? legacy ?? "";
}
function mergeClassName(className, legacy) {
return className ?? legacy ?? "";
}
function useSonner() {
const [activeToasts, setActiveToasts] = createSignal2(toast.getToasts());
onMount2(() => {
const unsubscribe = ToastState.subscribe((toastItem) => {
if (toastItem.dismiss) {
requestAnimationFrame(() => {
setActiveToasts((toasts) => toasts.filter((t) => t.id !== toastItem.id));
});
return;
}
const nextToast = toastItem;
setActiveToasts((toasts) => {
const indexOfExistingToast = toasts.findIndex((t) => t.id === nextToast.id);
if (indexOfExistingToast !== -1) {
return [
...toasts.slice(0, indexOfExistingToast),
{ ...toasts[indexOfExistingToast], ...nextToast },
...toasts.slice(indexOfExistingToast + 1)
];
}
return [nextToast, ...toasts];
});
});
onCleanup2(unsubscribe);
});
return {
toasts: activeToasts
};
}
function createToastTheme(theme) {
return theme !== "system" ? theme : typeof window !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
}
function Toast(props) {
const [mounted, setMounted] = createSignal2(false);

@@ -263,20 +447,32 @@ const [removed, setRemoved] = createSignal2(false);

const [swipeOut, setSwipeOut] = createSignal2(false);
const [isSwiped, setIsSwiped] = createSignal2(false);
const [swipeDirection, setSwipeDirection] = createSignal2(null);
const [swipeOutDirection, setSwipeOutDirection] = createSignal2(null);
const [offsetBeforeRemove, setOffsetBeforeRemove] = createSignal2(0);
const [initialHeight, setInitialHeight] = createSignal2(0);
let toastRef;
let dragStartTime = null;
let closeTimerStartTimeRef = 0;
let lastCloseTimerStartTimeRef = 0;
let remainingTime = TOAST_LIFETIME;
const [pointerStartRef, setPointerStartRef] = createSignal2(null);
const isFront = () => props.index === 0;
const isVisible = () => props.index + 1 <= props.visibleToasts;
const toastType = () => props.toast.type;
const toastClassname = () => props.toast.class || "";
const toastDescriptionClassname = () => props.toast.descriptionClass || "";
const propsWithDefaults = mergeProps({
gap: GAP
}, props);
const heightIndex = () => props.heights.findIndex((height) => height.toastId === props.toast.id) || 0;
const duration = () => props.toast.duration || props.duration || TOAST_LIFETIME;
let closeTimerStartTimeRef = 0;
let lastCloseTimerStartTimeRef = 0;
const [pointerStartRef, setPointerStartRef] = createSignal2(null);
const coords = () => props.position.split("-");
const toastsHeightBefore = () => {
const dismissible = () => props.toast.dismissible !== false;
const classNames = () => mergeClassNames(props.classNames, props.classes);
const className = () => mergeClassName(props.className, props.class);
const descriptionClassName = () => mergeDescriptionClassName(props.descriptionClassName, props.descriptionClass);
const toastClassName = () => mergeClassName(props.toast.className, props.toast.class);
const toastDescriptionClassName = () => mergeDescriptionClassName(props.toast.descriptionClassName, props.toast.descriptionClass);
const toastClassNames = () => mergeClassNames(props.toast.classNames, props.toast.classes);
const closeButton = () => props.toast.closeButton ?? props.closeButton;
const duration = () => props.toast.duration ?? props.duration ?? TOAST_LIFETIME;
const invert = () => props.toast.invert ?? props.invert;
const disabled = () => toastType() === "loading";
const swipeDirections = () => props.swipeDirections ?? getDefaultSwipeDirections(props.position);
const y = createMemo(() => props.position.split("-")[0]);
const x = createMemo(() => props.position.split("-")[1]);
const heightIndex = createMemo(() => Math.max(0, props.heights.findIndex((height) => height.toastId === props.toast.id)));
const toastsHeightBefore = createMemo(() => {
return props.heights.reduce((prev, curr, reducerIndex) => {

@@ -287,56 +483,58 @@ if (reducerIndex >= heightIndex())

}, 0);
};
});
const offset = createMemo(() => heightIndex() * (props.gap ?? GAP) + toastsHeightBefore());
const isDocumentHidden = useIsDocumentHidden();
const invert = () => props.toast.invert || props.invert;
const disabled = () => toastType() === "loading";
const offset = () => heightIndex() * propsWithDefaults.gap + toastsHeightBefore();
createEffect(() => {
remainingTime = duration();
});
function deleteToast() {
setRemoved(true);
setOffsetBeforeRemove(offset());
props.setHeights((heights) => heights.filter((height) => height.toastId !== props.toast.id));
window.setTimeout(() => {
props.removeToast(props.toast);
}, TIME_BEFORE_UNMOUNT);
}
function getLoadingIcon() {
if (props.icons?.loading) {
return <div class="sonner-loader" data-visible={toastType() === "loading"}>{props.icons.loading}</div>;
return <div class={cn(classNames()?.loader, toastClassNames()?.loader, "sonner-loader")} data-visible={toastType() === "loading"}>
{props.icons.loading}
</div>;
}
return <Loader visible={toastType() === "loading"} />;
return <Loader class={cn(classNames()?.loader, toastClassNames()?.loader)} visible={toastType() === "loading"} />;
}
const icon = () => props.toast.icon ?? props.icons?.[toastType()] ?? getAsset(toastType());
onMount2(() => {
setMounted(true);
if (!toastRef)
return;
const height = toastRef.getBoundingClientRect().height;
setInitialHeight(height);
props.setHeights((h) => [{ toastId: props.toast.id, toasterId: props.toast.toasterId, height, position: props.toast.position }, ...h]);
onCleanup2(() => {
props.setHeights((h) => h.filter((height2) => height2.toastId !== props.toast.id));
});
});
onMount2(() => {
const toastNode = toastRef;
const originalHeight = toastNode.style.height;
toastNode.style.height = "auto";
const newHeight = toastNode.getBoundingClientRect().height;
toastNode.style.height = originalHeight;
setInitialHeight(newHeight);
createEffect(() => {
props.setHeights((heights) => {
const alreadyExists = heights.find((height) => height.toastId === props.toast.id);
if (!alreadyExists)
return [{ toastId: props.toast.id, height: newHeight, position: props.toast.position }, ...heights];
else
return heights.map((height) => height.toastId === props.toast.id ? { ...height, height: newHeight } : height);
});
createEffect(() => {
if (!mounted() || !toastRef)
return;
resolveContent(props.toast.title);
resolveContent(props.toast.description);
const originalHeight = toastRef.style.height;
toastRef.style.height = "auto";
const nextHeight = toastRef.getBoundingClientRect().height;
toastRef.style.height = originalHeight;
setInitialHeight(nextHeight);
props.setHeights((heights) => {
const alreadyExists = heights.find((height) => height.toastId === props.toast.id);
if (!alreadyExists)
return [{ toastId: props.toast.id, toasterId: props.toast.toasterId, height: nextHeight, position: props.toast.position }, ...heights];
return heights.map((height) => height.toastId === props.toast.id ? { ...height, height: nextHeight } : height);
});
});
const deleteToast = () => {
setRemoved(true);
setOffsetBeforeRemove(offset());
props.setHeights((h) => h.filter((height) => height.toastId !== props.toast.id));
setTimeout(() => {
props.removeToast(props.toast);
}, TIME_BEFORE_UNMOUNT);
};
let remainingTime = duration();
createEffect(
on(
() => [
props.expanded,
props.interacting,
props.toast,
duration(),
props.toast.promise,
toastType(),
props.pauseWhenPageIsHidden,
isDocumentHidden()
],
([expanded, interacting, toast2, duration2, promise, toastType2, pauseWhenPageIsHidden, isDocumentHidden2]) => {
if (promise && toastType2 === "loading" || duration2 === Number.POSITIVE_INFINITY)
() => [props.expanded, props.interacting, props.toast, toastType(), isDocumentHidden(), duration()],
([expanded, interacting, currentToast, currentType]) => {
if (currentToast.promise && currentType === "loading" || currentToast.duration === Number.POSITIVE_INFINITY || currentType === "loading")
return;

@@ -347,3 +545,3 @@ let timeoutId;

const elapsedTime = (/* @__PURE__ */ new Date()).getTime() - closeTimerStartTimeRef;
remainingTime = remainingTime - elapsedTime;
remainingTime -= elapsedTime;
}

@@ -353,9 +551,12 @@ lastCloseTimerStartTimeRef = (/* @__PURE__ */ new Date()).getTime();

const startTimer = () => {
if (remainingTime === Number.POSITIVE_INFINITY)
return;
closeTimerStartTimeRef = (/* @__PURE__ */ new Date()).getTime();
timeoutId = setTimeout(() => {
toast2.onAutoClose?.(toast2);
currentToast.onAutoClose?.(currentToast);
deleteToast();
}, remainingTime);
};
if (expanded || interacting || pauseWhenPageIsHidden && isDocumentHidden2)
const shouldPause = expanded || interacting || (props.pauseWhenPageIsHidden ?? true) && isDocumentHidden();
if (shouldPause)
pauseTimer();

@@ -365,3 +566,4 @@ else

onCleanup2(() => {
clearTimeout(timeoutId);
if (timeoutId)
clearTimeout(timeoutId);
});

@@ -373,22 +575,8 @@ }

on(
() => props.toast.id,
(toastId) => {
const toastNode = toastRef;
if (toastNode) {
const height = toastNode.getBoundingClientRect().height;
setInitialHeight(height);
props.setHeights((h) => [{ toastId, height, position: props.toast.position }, ...h]);
onCleanup2(() => {
props.setHeights((h) => h.filter((height2) => height2.toastId !== toastId));
});
}
}
)
);
createEffect(
on(
() => props.toast.delete,
(d) => {
if (d)
(shouldDelete) => {
if (shouldDelete) {
deleteToast();
props.toast.onDismiss?.(props.toast);
}
}

@@ -398,31 +586,33 @@ )

return <li
aria-live={props.toast.important ? "assertive" : "polite"}
aria-atomic="true"
role="status"
tabIndex={0}
ref={toastRef}
class={_cn(
props.class,
toastClassname(),
props.classes?.toast,
props.toast?.classes?.toast,
props.classes?.default,
props.classes?.[toastType()],
props.toast?.classes?.[toastType()]
class={cn(
className(),
toastClassName(),
classNames()?.toast,
toastClassNames()?.toast,
classNames()?.default,
classNames()?.[toastType()],
toastClassNames()?.[toastType()]
)}
data-sonner-toast=""
data-rich-colors={props.toast.richColors ?? props.defaultRichColors}
data-styled={!(props.toast.jsx || props.toast.unstyled || props.unstyled)}
data-mounted={mounted()}
data-promise={Boolean(props.toast.promise)}
data-swiped={isSwiped()}
data-removed={removed()}
data-visible={isVisible()}
data-y-position={coords()[0]}
data-x-position={coords()[1]}
data-y-position={y()}
data-x-position={x()}
data-index={props.index}
data-front={isFront()}
data-swiping={swiping()}
data-dismissible={dismissible()}
data-type={toastType()}
data-invert={invert()}
data-swipe-out={swipeOut()}
data-swipe-direction={swipeOutDirection()}
data-expanded={Boolean(props.expanded || props.expandByDefault && mounted())}
data-testid={props.toast.testId}
style={{

@@ -437,7 +627,15 @@ "--index": props.index,

}}
onDragEnd={() => {
setSwiping(false);
setSwipeDirection(null);
setPointerStartRef(null);
}}
onPointerDown={(event) => {
if (disabled())
if (event.button === 2)
return;
if (disabled() || !dismissible())
return;
dragStartTime = /* @__PURE__ */ new Date();
setOffsetBeforeRemove(offset());
event.target.setPointerCapture(event.pointerId);
event.currentTarget.setPointerCapture(event.pointerId);
if (event.target.tagName === "BUTTON")

@@ -449,9 +647,17 @@ return;

onPointerUp={() => {
if (swipeOut())
if (swipeOut() || !dismissible())
return;
setPointerStartRef(null);
const swipeAmount = Number(toastRef?.style.getPropertyValue("--swipe-amount").replace("px", "") || 0);
if (Math.abs(swipeAmount) >= SWIPE_TRESHOLD) {
const swipeAmountX = Number(toastRef?.style.getPropertyValue("--swipe-amount-x").replace("px", "") || 0);
const swipeAmountY = Number(toastRef?.style.getPropertyValue("--swipe-amount-y").replace("px", "") || 0);
const timeTaken = Math.max(1, (/* @__PURE__ */ new Date()).getTime() - (dragStartTime?.getTime() ?? 0));
const swipeAmount = swipeDirection() === "x" ? swipeAmountX : swipeAmountY;
const velocity = Math.abs(swipeAmount) / timeTaken;
if (Math.abs(swipeAmount) >= SWIPE_THRESHOLD || velocity > 0.11) {
setOffsetBeforeRemove(offset());
props.toast.onDismiss?.(props.toast);
if (swipeDirection() === "x")
setSwipeOutDirection(swipeAmountX > 0 ? "right" : "left");
else
setSwipeOutDirection(swipeAmountY > 0 ? "down" : "up");
deleteToast();

@@ -461,83 +667,128 @@ setSwipeOut(true);

}
toastRef?.style.setProperty("--swipe-amount", "0px");
toastRef?.style.setProperty("--swipe-amount-x", "0px");
toastRef?.style.setProperty("--swipe-amount-y", "0px");
setIsSwiped(false);
setSwiping(false);
setSwipeDirection(null);
}}
onPointerMove={(event) => {
if (!pointerStartRef())
if (!pointerStartRef() || !dismissible())
return;
const yPosition = event.clientY - pointerStartRef().y;
const xPosition = event.clientX - pointerStartRef().x;
const clamp = coords()[0] === "top" ? Math.min : Math.max;
const clampedY = clamp(0, yPosition);
const swipeStartThreshold = event.pointerType === "touch" ? 10 : 2;
const isAllowedToSwipe = Math.abs(clampedY) > swipeStartThreshold;
if (isAllowedToSwipe) {
toastRef?.style.setProperty("--swipe-amount", `${yPosition}px`);
} else if (Math.abs(xPosition) > swipeStartThreshold) {
setPointerStartRef(null);
if ((window.getSelection()?.toString().length ?? 0) > 0)
return;
const yDelta = event.clientY - pointerStartRef().y;
const xDelta = event.clientX - pointerStartRef().x;
if (!swipeDirection() && (Math.abs(xDelta) > 1 || Math.abs(yDelta) > 1))
setSwipeDirection(Math.abs(xDelta) > Math.abs(yDelta) ? "x" : "y");
const swipeAmount = { x: 0, y: 0 };
const getDampening = (delta) => {
const factor = Math.abs(delta) / 20;
return 1 / (1.5 + factor);
};
if (swipeDirection() === "y") {
if (swipeDirections().includes("top") || swipeDirections().includes("bottom")) {
if (swipeDirections().includes("top") && yDelta < 0 || swipeDirections().includes("bottom") && yDelta > 0)
swipeAmount.y = yDelta;
else
swipeAmount.y = yDelta * getDampening(yDelta);
}
} else if (swipeDirection() === "x") {
if (swipeDirections().includes("left") || swipeDirections().includes("right")) {
if (swipeDirections().includes("left") && xDelta < 0 || swipeDirections().includes("right") && xDelta > 0)
swipeAmount.x = xDelta;
else
swipeAmount.x = xDelta * getDampening(xDelta);
}
}
if (Math.abs(swipeAmount.x) > 0 || Math.abs(swipeAmount.y) > 0)
setIsSwiped(true);
toastRef?.style.setProperty("--swipe-amount-x", `${swipeAmount.x}px`);
toastRef?.style.setProperty("--swipe-amount-y", `${swipeAmount.y}px`);
}}
><Show when={props.closeButton && !props.toast.jsx}><button
aria-label="Close toast"
>
<Show when={closeButton() && !props.toast.jsx && toastType() !== "loading"}>
<button
aria-label={props.closeButtonAriaLabel ?? "Close toast"}
data-disabled={disabled()}
data-close-button
onClick={disabled() ? void 0 : () => {
onClick={() => {
if (disabled() || !dismissible())
return;
deleteToast();
props.toast.onDismiss?.(props.toast);
}}
class={_cn(props.classes?.closeButton, props.toast?.classes?.closeButton)}
><svg
xmlns="http://www.w3.org/2000/svg"
width="12"
height="12"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
><line x1="18" y1="6" x2="6" y2="18" /><line x1="6" y1="6" x2="18" y2="18" /></svg></button></Show><Show
when={props.toast.jsx || props.toast.title instanceof Element}
fallback={<><Show when={toastType() || props.toast.icon || props.toast.promise}><div data-icon="">{props.toast.promise || props.toast.type === "loading" && !props.toast.icon ? props.toast.icon || getLoadingIcon() : null}{props.toast.type !== "loading" ? props.toast.icon || props.icons?.[toastType()] || getAsset(toastType())() : null}</div></Show><div data-content=""><div data-title="" class={_cn(props.classes?.title, props.toast?.classes?.title)}>{props.toast.title}</div><Show when={props.toast.description}><div
data-description=""
class={_cn(
props.descriptionClass,
toastDescriptionClassname(),
props.classes?.description,
props.toast?.classes?.description
)}
>{props.toast.description}</div></Show></div><Show when={props.toast.cancel}><button
data-button
data-cancel
style={props.toast.cancelButtonStyle || props.cancelButtonStyle}
onClick={() => {
deleteToast();
if (props.toast.cancel?.onClick)
props.toast.cancel.onClick();
}}
class={_cn(props.classes?.cancelButton, props.toast?.classes?.cancelButton)}
>{props.toast.cancel.label}</button></Show><Show when={props.toast.action}><button
data-button=""
style={props.toast.actionButtonStyle || props.actionButtonStyle}
onClick={(event) => {
props.toast.action?.onClick(event);
if (event.defaultPrevented)
return;
deleteToast();
}}
class={_cn(props.classes?.actionButton, props.toast?.classes?.actionButton)}
>{props.toast.action.label}</button></Show></>}
>{props.toast.jsx || props.toast.title}</Show></li>;
};
function getDocumentDirection() {
if (typeof window === "undefined")
return "ltr";
if (typeof document === "undefined")
return "ltr";
const dirAttribute = document.documentElement.getAttribute("dir");
if (dirAttribute === "auto" || !dirAttribute)
return window.getComputedStyle(document.documentElement).direction;
return dirAttribute;
class={cn(classNames()?.closeButton, toastClassNames()?.closeButton)}
>
{props.icons?.close ?? <CloseIcon />}
</button>
</Show>
<Show when={(toastType() || props.toast.icon || props.toast.promise) && props.toast.icon !== null && (props.icons?.[toastType()] !== null || props.toast.icon)}>
<div data-icon="" class={cn(classNames()?.icon, toastClassNames()?.icon)}>
{props.toast.promise || props.toast.type === "loading" && !props.toast.icon ? props.toast.icon || getLoadingIcon() : null}
{props.toast.type !== "loading" ? icon() : null}
</div>
</Show>
<div data-content="" class={cn(classNames()?.content, toastClassNames()?.content)}>
<div data-title="" class={cn(classNames()?.title, toastClassNames()?.title)}>
{props.toast.jsx ? props.toast.jsx : resolveContent(props.toast.title)}
</div>
<Show when={props.toast.description}>
<div
data-description=""
class={cn(
descriptionClassName(),
toastDescriptionClassName(),
classNames()?.description,
toastClassNames()?.description
)}
>
{resolveContent(props.toast.description)}
</div>
</Show>
</div>
<Show when={props.toast.cancel}>
{(cancel) => <Show when={!isAction(cancel())} fallback={<button
data-button
data-cancel
style={props.toast.cancelButtonStyle ?? props.cancelButtonStyle}
onClick={(event) => {
const currentCancel = cancel();
if (!dismissible())
return;
currentCancel.onClick?.(event);
deleteToast();
}}
class={cn(classNames()?.cancelButton, toastClassNames()?.cancelButton)}
>
{cancel().label}
</button>}>
{cancel()}
</Show>}
</Show>
<Show when={props.toast.action}>
{(action) => <Show when={!isAction(action())} fallback={<button
data-button
data-action
style={props.toast.actionButtonStyle ?? props.actionButtonStyle}
onClick={(event) => {
const currentAction = action();
currentAction.onClick?.(event);
if (event.defaultPrevented)
return;
deleteToast();
}}
class={cn(classNames()?.actionButton, toastClassNames()?.actionButton)}
>
{action().label}
</button>}>
{action()}
</Show>}
</Show>
</li>;
}
var Toaster = (props) => {
function Toaster(props) {
const propsWithDefaults = mergeProps({

@@ -547,67 +798,86 @@ position: "bottom-right",

theme: "light",
gap: GAP,
visibleToasts: VISIBLE_TOASTS_AMOUNT,
dir: getDocumentDirection()
dir: getDocumentDirection(),
containerAriaLabel: "Notifications"
}, props);
const initialTheme = createToastTheme(propsWithDefaults.theme);
const [toastsStore, setToastsStore] = createStore({ toasts: [] });
const possiblePositions = () => {
return Array.from(
new Set([propsWithDefaults.position].concat(toastsStore.toasts.filter((toast2) => toast2.position).map((toast2) => toast2.position)))
);
};
const filteredToasts = createMemo(() => {
const toasts = toastsStore.toasts;
if (propsWithDefaults.id)
return toasts.filter((toast2) => toast2.toasterId === propsWithDefaults.id);
return toasts.filter((toast2) => !toast2.toasterId);
});
const possiblePositions = createMemo(() => {
return Array.from(/* @__PURE__ */ new Set([propsWithDefaults.position, ...filteredToasts().filter((toast2) => toast2.position).map((toast2) => toast2.position)]));
});
const [heights, setHeights] = createSignal2([]);
const [expanded, setExpanded] = createSignal2(false);
const [interacting, setInteracting] = createSignal2(false);
const [actualTheme, setActualTheme] = createSignal2(initialTheme);
const [lastFocusedElementRef, setLastFocusedElementRef] = createSignal2(null);
const [isFocusWithinRef, setIsFocusWithinRef] = createSignal2(false);
let listRef;
const hotkeyLabel = () => propsWithDefaults.hotkey.join("+").replace(/Key/g, "").replace(/Digit/g, "");
const [lastFocusedElementRef, setLastFocusedElementRef] = createSignal2(null);
const [isFocusedWithinRef, setIsFocusedWithinRef] = createSignal2(false);
const [actualTheme, setActualTheme] = createSignal2(
propsWithDefaults.theme !== "system" ? propsWithDefaults.theme : typeof window !== "undefined" ? window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : "light"
);
const removeToast = (toast2) => setToastsStore("toasts", (toasts) => toasts.filter(({ id }) => id !== toast2.id));
const className = () => mergeClassName(propsWithDefaults.className, propsWithDefaults.class);
const toastOptions = () => propsWithDefaults.toastOptions;
const toastClassNames = () => mergeClassNames(toastOptions()?.classNames, toastOptions()?.classes);
const toastDescriptionClassName = () => mergeDescriptionClassName(toastOptions()?.descriptionClassName, toastOptions()?.descriptionClass);
const toastClassName = () => mergeClassName(toastOptions()?.className, toastOptions()?.class);
const removeToast = (toastToRemove) => {
setToastsStore("toasts", (toasts) => {
if (!toasts.find((toast2) => toast2.id === toastToRemove.id)?.delete)
ToastState.dismiss(toastToRemove.id);
return toasts.filter(({ id }) => id !== toastToRemove.id);
});
};
onMount2(() => {
const unsub = ToastState.subscribe((toast2) => {
if (toast2.dismiss) {
setToastsStore("toasts", produce((_toasts) => {
_toasts.forEach((t) => {
if (t.id === toast2.id)
t.delete = true;
});
}));
const unsubscribe = ToastState.subscribe((toastItem) => {
if (toastItem.dismiss) {
requestAnimationFrame(() => {
setToastsStore("toasts", produce((toasts) => {
toasts.forEach((toast2) => {
if (toast2.id === toastItem.id)
toast2.delete = true;
});
}));
});
return;
}
const changedIndex = toastsStore.toasts.findIndex((t) => t.id === toast2.id);
if (changedIndex !== -1) {
setToastsStore("toasts", [changedIndex], reconcile(toast2));
const nextToast = toastItem;
const indexOfExistingToast = toastsStore.toasts.findIndex((t) => t.id === nextToast.id);
if (indexOfExistingToast !== -1) {
setToastsStore("toasts", indexOfExistingToast, reconcile(nextToast));
return;
}
setToastsStore("toasts", produce((_toasts) => {
_toasts.unshift(toast2);
setToastsStore("toasts", produce((toasts) => {
toasts.unshift(nextToast);
}));
});
onCleanup2(() => {
unsub();
});
onCleanup2(unsubscribe);
});
createEffect(
on(
() => propsWithDefaults.theme,
(theme) => {
if (theme !== "system") {
setActualTheme(theme);
return;
}
if (typeof window === "undefined")
return;
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", ({ matches }) => {
if (matches)
setActualTheme("dark");
else
setActualTheme("light");
});
}
)
);
createEffect(() => {
if (toastsStore.toasts.length <= 1)
const theme = propsWithDefaults.theme;
if (theme !== "system") {
setActualTheme(theme);
return;
}
if (typeof window === "undefined")
return;
const darkMediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
const updateTheme = ({ matches }) => {
setActualTheme(matches ? "dark" : "light");
};
updateTheme(darkMediaQuery);
try {
darkMediaQuery.addEventListener("change", updateTheme);
onCleanup2(() => darkMediaQuery.removeEventListener("change", updateTheme));
} catch {
darkMediaQuery.addListener(updateTheme);
onCleanup2(() => darkMediaQuery.removeListener(updateTheme));
}
});
createEffect(() => {
if (filteredToasts().length <= 1)
setExpanded(false);

@@ -617,3 +887,3 @@ });

const handleKeyDown = (event) => {
const isHotkeyPressed = propsWithDefaults.hotkey.every((key) => event[key] || event.code === key);
const isHotkeyPressed = propsWithDefaults.hotkey.length > 0 && propsWithDefaults.hotkey.every((key) => event[key] || event.code === key);
if (isHotkeyPressed) {

@@ -627,46 +897,44 @@ setExpanded(true);

document.addEventListener("keydown", handleKeyDown);
onCleanup2(() => {
document.removeEventListener("keydown", handleKeyDown);
});
onCleanup2(() => document.removeEventListener("keydown", handleKeyDown));
});
createEffect(
on(
() => listRef,
(ref) => {
if (ref) {
onCleanup2(() => {
if (lastFocusedElementRef()) {
lastFocusedElementRef()?.focus({ preventScroll: true });
setLastFocusedElementRef(null);
setIsFocusedWithinRef(false);
}
});
}
}
)
);
return <Show when={toastsStore.toasts.length > 0}>{
/* Remove item from normal navigation flow, only available via hotkey */
}<section aria-label={`Notifications ${hotkeyLabel()}`} tabIndex={-1}><For2 each={possiblePositions()}>{(position, index) => {
onCleanup2(() => {
if (lastFocusedElementRef()) {
lastFocusedElementRef()?.focus({ preventScroll: true });
setLastFocusedElementRef(null);
setIsFocusWithinRef(false);
}
});
return <section
aria-label={propsWithDefaults.customAriaLabel ?? `${propsWithDefaults.containerAriaLabel} ${hotkeyLabel()}`}
tabIndex={-1}
aria-live="polite"
aria-relevant="additions text"
aria-atomic="false"
data-react-aria-top-layer
>
<For2 each={possiblePositions()}>
{(position, index) => {
const [y, x] = position.split("-");
return <ol
const toastsByPosition = createMemo(() => filteredToasts().filter((toast2) => !toast2.position && index() === 0 || toast2.position === position));
const heightsByPosition = createMemo(() => heights().filter((height) => index() === 0 && !height.position || height.position === position));
return <Show when={filteredToasts().length > 0}>
<ol
tabIndex={-1}
ref={listRef}
dir={propsWithDefaults.dir === "auto" ? getDocumentDirection() : propsWithDefaults.dir}
class={propsWithDefaults.class}
class={className()}
data-sonner-toaster
data-theme={actualTheme()}
data-rich-colors={propsWithDefaults.richColors}
data-sonner-theme={actualTheme()}
data-y-position={y}
data-x-position={x}
style={{
"--front-toast-height": `${heights()[0]?.height}px`,
"--offset": typeof propsWithDefaults.offset === "number" ? `${propsWithDefaults.offset}px` : propsWithDefaults.offset || VIEWPORT_OFFSET,
"--front-toast-height": `${heightsByPosition()[0]?.height ?? 0}px`,
"--width": `${TOAST_WIDTH}px`,
"--gap": `${GAP}px`,
...propsWithDefaults.style
"--gap": `${propsWithDefaults.gap}px`,
...propsWithDefaults.style,
...assignOffset(propsWithDefaults.offset, propsWithDefaults.mobileOffset)
}}
onBlur={(event) => {
if (isFocusedWithinRef() && !event.currentTarget.contains(event.relatedTarget)) {
setIsFocusedWithinRef(false);
if (isFocusWithinRef() && !event.currentTarget.contains(event.relatedTarget)) {
setIsFocusWithinRef(false);
if (lastFocusedElementRef()) {

@@ -679,4 +947,7 @@ lastFocusedElementRef()?.focus({ preventScroll: true });

onFocus={(event) => {
if (!isFocusedWithinRef()) {
setIsFocusedWithinRef(true);
const isNotDismissible = event.target instanceof HTMLElement && event.target.dataset.dismissible === "false";
if (isNotDismissible)
return;
if (!isFocusWithinRef()) {
setIsFocusWithinRef(true);
setLastFocusedElementRef(event.relatedTarget);

@@ -691,26 +962,34 @@ }

}}
onPointerDown={() => {
onDragEnd={() => setExpanded(false)}
onPointerDown={(event) => {
const isNotDismissible = event.target instanceof HTMLElement && event.target.dataset.dismissible === "false";
if (isNotDismissible)
return;
setInteracting(true);
}}
onPointerUp={() => setInteracting(false)}
><For2 each={toastsStore.toasts.filter((toast2) => !toast2.position && index() === 0 || toast2.position === position)}>{(toast2, index2) => <Toast
index={index2()}
>
<For2 each={toastsByPosition()}>
{(toastItem, toastIndex) => <Toast
icons={propsWithDefaults.icons}
toast={toast2}
duration={propsWithDefaults.toastOptions?.duration ?? props.duration}
class={propsWithDefaults.toastOptions?.class}
classes={propsWithDefaults.toastOptions?.classes}
cancelButtonStyle={propsWithDefaults.toastOptions?.cancelButtonStyle}
actionButtonStyle={propsWithDefaults.toastOptions?.actionButtonStyle}
descriptionClass={propsWithDefaults.toastOptions?.descriptionClass}
index={toastIndex()}
toast={toastItem}
defaultRichColors={propsWithDefaults.richColors}
duration={toastOptions()?.duration ?? propsWithDefaults.duration}
class={toastClassName()}
descriptionClassName={toastDescriptionClassName()}
invert={Boolean(propsWithDefaults.invert)}
visibleToasts={propsWithDefaults.visibleToasts}
closeButton={Boolean(propsWithDefaults.closeButton)}
closeButton={toastOptions()?.closeButton ?? propsWithDefaults.closeButton ?? false}
interacting={interacting()}
position={propsWithDefaults.position}
style={propsWithDefaults.toastOptions?.style}
unstyled={propsWithDefaults.toastOptions?.unstyled}
position={position}
style={toastOptions()?.style}
unstyled={toastOptions()?.unstyled}
classNames={toastClassNames()}
cancelButtonStyle={toastOptions()?.cancelButtonStyle}
actionButtonStyle={toastOptions()?.actionButtonStyle}
closeButtonAriaLabel={toastOptions()?.closeButtonAriaLabel}
removeToast={removeToast}
toasts={toastsStore.toasts}
heights={heights()}
toasts={toastsByPosition()}
heights={heightsByPosition()}
setHeights={setHeights}

@@ -720,9 +999,16 @@ expandByDefault={Boolean(propsWithDefaults.expand)}

expanded={expanded()}
swipeDirections={propsWithDefaults.swipeDirections}
pauseWhenPageIsHidden={propsWithDefaults.pauseWhenPageIsHidden}
/>}</For2></ol>;
}}</For2></section></Show>;
};
/>}
</For2>
</ol>
</Show>;
}}
</For2>
</section>;
}
export {
Toaster,
toast
toast,
useSonner
};

@@ -729,0 +1015,0 @@ /*!

@@ -1,12 +0,21 @@

import { JSX, Component } from 'solid-js';
import * as solid_js from 'solid-js';
import { JSX } from 'solid-js';
type ToastTypes = 'normal' | 'action' | 'success' | 'info' | 'warning' | 'error' | 'loading' | 'default';
type PromiseT<Data = any> = Promise<Data> | (() => Promise<Data>);
type PromiseData<ToastData = any> = ExternalToast & {
loading: string | JSX.Element;
success: string | JSX.Element | ((data: ToastData) => JSX.Element | string);
error: string | JSX.Element | ((error: any) => JSX.Element | string);
type ToastContent = (() => JSX.Element) | JSX.Element;
interface PromiseIExtendedResult extends ExternalToast {
message: JSX.Element | string;
}
type PromiseTExtendedResult<Data = any> = PromiseIExtendedResult | ((data: Data) => PromiseIExtendedResult | Promise<PromiseIExtendedResult>);
type PromiseTResult<Data = any> = string | JSX.Element | ((data: Data) => JSX.Element | string | Promise<JSX.Element | string>);
type PromiseExternalToast = Omit<ExternalToast, 'description'>;
type PromiseData<ToastData = any> = PromiseExternalToast & {
loading?: string | JSX.Element;
success?: PromiseTResult<ToastData> | PromiseTExtendedResult<ToastData>;
error?: PromiseTResult | PromiseTExtendedResult;
description?: PromiseTResult;
finally?: () => void | Promise<void>;
};
interface ToastClasses {
interface ToastClassnames {
toast?: string;

@@ -25,30 +34,34 @@ title?: string;

default?: string;
content?: string;
icon?: string;
}
interface ToastIcons {
success?: JSX.Element;
info?: JSX.Element;
warning?: JSX.Element;
error?: JSX.Element;
loading?: JSX.Element;
success?: JSX.Element | null;
info?: JSX.Element | null;
warning?: JSX.Element | null;
error?: JSX.Element | null;
loading?: JSX.Element | null;
close?: JSX.Element | null;
}
interface Action {
label: JSX.Element;
onClick: (event: MouseEvent) => void;
actionButtonStyle?: JSX.CSSProperties;
}
interface ToastT {
id: number | string;
title?: string | JSX.Element;
toasterId?: string;
title?: ToastContent;
type?: ToastTypes;
icon?: JSX.Element;
icon?: JSX.Element | null;
jsx?: JSX.Element;
richColors?: boolean;
invert?: boolean;
closeButton?: boolean;
description?: JSX.Element;
dismissible?: boolean;
description?: ToastContent;
duration?: number;
delete?: boolean;
important?: boolean;
action?: {
label: string;
onClick: (event: MouseEvent) => void;
};
cancel?: {
label: string;
onClick?: () => void;
};
action?: Action | JSX.Element;
cancel?: Action | JSX.Element;
onDismiss?: (toast: ToastT) => void;

@@ -61,12 +74,16 @@ onAutoClose?: (toast: ToastT) => void;

unstyled?: boolean;
className?: string;
classNames?: ToastClassnames;
descriptionClassName?: string;
position?: Position;
testId?: string;
class?: string;
classes?: ToastClasses;
classes?: ToastClassnames;
descriptionClass?: string;
position?: Position;
}
type Position = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'top-center' | 'bottom-center';
interface ToastOptions {
class?: string;
className?: string;
closeButton?: boolean;
descriptionClass?: string;
descriptionClassName?: string;
style?: JSX.CSSProperties;

@@ -77,5 +94,18 @@ cancelButtonStyle?: JSX.CSSProperties;

unstyled?: boolean;
classes?: ToastClasses;
classNames?: ToastClassnames;
closeButtonAriaLabel?: string;
toasterId?: string;
class?: string;
classes?: ToastClassnames;
descriptionClass?: string;
}
type Offset = {
top?: string | number;
right?: string | number;
bottom?: string | number;
left?: string | number;
} | string | number;
type SwipeDirection = 'top' | 'right' | 'bottom' | 'left';
interface ToasterProps {
id?: string;
invert?: boolean;

@@ -92,36 +122,46 @@ theme?: 'light' | 'dark' | 'system';

toastOptions?: ToastOptions;
class?: string;
className?: string;
style?: JSX.CSSProperties;
offset?: string | number;
offset?: Offset;
mobileOffset?: Offset;
dir?: 'rtl' | 'ltr' | 'auto';
swipeDirections?: SwipeDirection[];
icons?: ToastIcons;
dir?: 'rtl' | 'ltr' | 'auto';
customAriaLabel?: string;
containerAriaLabel?: string;
pauseWhenPageIsHidden?: boolean;
class?: string;
}
type ExternalToast = Omit<ToastT, 'id' | 'type' | 'title' | 'delete' | 'promise'> & {
interface ToastToDismiss {
id: number | string;
dismiss: boolean;
}
type ExternalToast = Omit<ToastT, 'id' | 'type' | 'title' | 'jsx' | 'delete' | 'promise'> & {
id?: number | string;
toasterId?: string;
};
declare function toastFunction(message: string | JSX.Element, data?: ExternalToast): string | number;
declare function toastFunction(message: ToastContent, data?: ExternalToast): string | number;
declare const toast: typeof toastFunction & {
success: (message: string | JSX.Element, data?: ExternalToast) => string | number;
info: (message: string | JSX.Element, data?: ExternalToast) => string | number;
warning: (message: string | JSX.Element, data?: ExternalToast) => string | number;
error: (message: string | JSX.Element, data?: ExternalToast) => string | number;
success: (message: ToastContent, data?: ExternalToast) => string | number;
info: (message: ToastContent, data?: ExternalToast) => string | number;
warning: (message: ToastContent, data?: ExternalToast) => string | number;
error: (message: ToastContent, data?: ExternalToast) => string | number;
custom: (jsx: (id: number | string) => JSX.Element, data?: ExternalToast) => string | number;
message: (message: string | JSX.Element, data?: ExternalToast) => string | number;
promise: <ToastData>(promise: PromiseT<ToastData>, data?: PromiseData<ToastData> | undefined) => string | number | undefined;
message: (message: ToastContent, data?: ExternalToast) => string | number;
promise: <ToastData>(promise: PromiseT<ToastData>, data?: PromiseData<ToastData> | undefined) => {
unwrap: () => Promise<ToastData>;
} | undefined;
dismiss: (id?: number | string) => string | number | undefined;
loading: (message: string | JSX.Element, data?: ExternalToast) => string | number;
loading: (message: ToastContent, data?: ExternalToast) => string | number;
} & {
getHistory: () => (ToastT | ToastToDismiss)[];
getToasts: () => ToastT[];
};
/*!
* Original code by Emil Kowalski
* MIT Licensed, Copyright 2023 Emil Kowalski, see https://github.com/emilkowalski/sonner/blob/main/LICENSE.md for details
*
* Credits:
* https://github.com/emilkowalski/sonner/blob/main/src/index.tsx
*/
declare function useSonner(): {
toasts: solid_js.Accessor<ToastT[]>;
};
declare function Toaster(props: ToasterProps): JSX.Element;
declare const Toaster: Component<ToasterProps>;
export { type ExternalToast, type ToastT, Toaster, toast };
export { type Action, type ExternalToast, type ToastClassnames, type ToastT, type ToastToDismiss, Toaster, type ToasterProps, toast, useSonner };

@@ -1,3 +0,3 @@

import { delegateEvents, createComponent, insert, use, setAttribute, effect, className, style, template, addEventListener, memo } from 'solid-js/web';
import { mergeProps, createSignal, onMount, onCleanup, createEffect, on, Show, For } from 'solid-js';
import { delegateEvents, insert, createComponent, use, setAttribute, effect, className, style, memo, template } from 'solid-js/web';
import { createSignal, onMount, onCleanup, mergeProps, createMemo, createEffect, For, Show, on } from 'solid-js';
import { createStore, produce, reconcile } from 'solid-js/store';

@@ -30,4 +30,4 @@

// src/styles.css
styleInject(':where(html[dir=ltr]),\n:where([data-sonner-toaster][dir=ltr]) {\n --toast-icon-margin-start: -3px;\n --toast-icon-margin-end: 4px;\n --toast-svg-margin-start: -1px;\n --toast-svg-margin-end: 0px;\n --toast-button-margin-start: auto;\n --toast-button-margin-end: 0;\n --toast-close-button-start: 0;\n --toast-close-button-end: unset;\n --toast-close-button-transform: translate(-35%, -35%);\n}\n:where(html[dir=rtl]),\n:where([data-sonner-toaster][dir=rtl]) {\n --toast-icon-margin-start: 4px;\n --toast-icon-margin-end: -3px;\n --toast-svg-margin-start: 0px;\n --toast-svg-margin-end: -1px;\n --toast-button-margin-start: 0;\n --toast-button-margin-end: auto;\n --toast-close-button-start: unset;\n --toast-close-button-end: 0;\n --toast-close-button-transform: translate(35%, -35%);\n}\n:where([data-sonner-toaster]) {\n position: fixed;\n width: var(--width);\n font-family:\n ui-sans-serif,\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n Segoe UI,\n Roboto,\n Helvetica Neue,\n Arial,\n Noto Sans,\n sans-serif,\n Apple Color Emoji,\n Segoe UI Emoji,\n Segoe UI Symbol,\n Noto Color Emoji;\n --gray1: hsl(0, 0%, 99%);\n --gray2: hsl(0, 0%, 97.3%);\n --gray3: hsl(0, 0%, 95.1%);\n --gray4: hsl(0, 0%, 93%);\n --gray5: hsl(0, 0%, 90.9%);\n --gray6: hsl(0, 0%, 88.7%);\n --gray7: hsl(0, 0%, 85.8%);\n --gray8: hsl(0, 0%, 78%);\n --gray9: hsl(0, 0%, 56.1%);\n --gray10: hsl(0, 0%, 52.3%);\n --gray11: hsl(0, 0%, 43.5%);\n --gray12: hsl(0, 0%, 9%);\n --border-radius: 8px;\n box-sizing: border-box;\n padding: 0;\n margin: 0;\n list-style: none;\n outline: none;\n z-index: 999999999;\n}\n:where([data-sonner-toaster][data-x-position=right]) {\n right: max(var(--offset), env(safe-area-inset-right));\n}\n:where([data-sonner-toaster][data-x-position=left]) {\n left: max(var(--offset), env(safe-area-inset-left));\n}\n:where([data-sonner-toaster][data-x-position=center]) {\n left: 50%;\n transform: translateX(-50%);\n}\n:where([data-sonner-toaster][data-y-position=top]) {\n top: max(var(--offset), env(safe-area-inset-top));\n}\n:where([data-sonner-toaster][data-y-position=bottom]) {\n bottom: max(var(--offset), env(safe-area-inset-bottom));\n}\n:where([data-sonner-toast]) {\n --y: translateY(100%);\n --lift-amount: calc(var(--lift) * var(--gap));\n z-index: var(--z-index);\n position: absolute;\n opacity: 0;\n transform: var(--y);\n filter: blur(0);\n touch-action: none;\n transition:\n transform 400ms,\n opacity 400ms,\n height 400ms,\n box-shadow 200ms;\n box-sizing: border-box;\n outline: none;\n overflow-wrap: anywhere;\n}\n:where([data-sonner-toast][data-styled=true]) {\n padding: 16px;\n background: var(--normal-bg);\n border: 1px solid var(--normal-border);\n color: var(--normal-text);\n border-radius: var(--border-radius);\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1);\n width: var(--width);\n font-size: 13px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n:where([data-sonner-toast]:focus-visible) {\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1), 0 0 0 2px rgba(0, 0, 0, 0.2);\n}\n:where([data-sonner-toast][data-y-position=top]) {\n top: 0;\n --y: translateY(-100%);\n --lift: 1;\n --lift-amount: calc(1 * var(--gap));\n}\n:where([data-sonner-toast][data-y-position=bottom]) {\n bottom: 0;\n --y: translateY(100%);\n --lift: -1;\n --lift-amount: calc(var(--lift) * var(--gap));\n}\n:where([data-sonner-toast]) :where([data-description]) {\n font-weight: 400;\n line-height: 1.4;\n color: inherit;\n}\n:where([data-sonner-toast]) :where([data-title]) {\n font-weight: 500;\n line-height: 1.5;\n color: inherit;\n}\n:where([data-sonner-toast]) :where([data-icon]) {\n display: flex;\n height: 16px;\n width: 16px;\n position: relative;\n justify-content: flex-start;\n align-items: center;\n flex-shrink: 0;\n margin-left: var(--toast-icon-margin-start);\n margin-right: var(--toast-icon-margin-end);\n}\n:where([data-sonner-toast][data-promise=true]) :where([data-icon]) > svg {\n opacity: 0;\n transform: scale(0.8);\n transform-origin: center;\n animation: sonner-fade-in 300ms ease forwards;\n}\n:where([data-sonner-toast]) :where([data-icon]) > * {\n flex-shrink: 0;\n}\n:where([data-sonner-toast]) :where([data-icon]) svg {\n margin-left: var(--toast-svg-margin-start);\n margin-right: var(--toast-svg-margin-end);\n}\n:where([data-sonner-toast]) :where([data-content]) {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n[data-sonner-toast][data-styled=true] [data-button] {\n border-radius: 4px;\n padding-left: 8px;\n padding-right: 8px;\n height: 24px;\n font-size: 12px;\n color: var(--normal-bg);\n background: var(--normal-text);\n margin-left: var(--toast-button-margin-start);\n margin-right: var(--toast-button-margin-end);\n border: none;\n cursor: pointer;\n outline: none;\n display: flex;\n align-items: center;\n flex-shrink: 0;\n transition: opacity 400ms, box-shadow 200ms;\n}\n:where([data-sonner-toast]) :where([data-button]):focus-visible {\n box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.4);\n}\n:where([data-sonner-toast]) :where([data-button]):first-of-type {\n margin-left: var(--toast-button-margin-start);\n margin-right: var(--toast-button-margin-end);\n}\n:where([data-sonner-toast]) :where([data-cancel]) {\n color: var(--normal-text);\n background: rgba(0, 0, 0, 0.08);\n}\n:where([data-sonner-toast][data-theme=dark]) :where([data-cancel]) {\n background: rgba(255, 255, 255, 0.3);\n}\n:where([data-sonner-toast]) :where([data-close-button]) {\n position: absolute;\n left: var(--toast-close-button-start);\n right: var(--toast-close-button-end);\n top: 0;\n height: 20px;\n width: 20px;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 0;\n background: var(--gray1);\n color: var(--gray12);\n border: 1px solid var(--gray4);\n transform: var(--toast-close-button-transform);\n border-radius: 50%;\n cursor: pointer;\n z-index: 1;\n transition:\n opacity 100ms,\n background 200ms,\n border-color 200ms;\n}\n:where([data-sonner-toast]) :where([data-close-button]):focus-visible {\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1), 0 0 0 2px rgba(0, 0, 0, 0.2);\n}\n:where([data-sonner-toast]) :where([data-disabled=true]) {\n cursor: not-allowed;\n}\n:where([data-sonner-toast]):hover :where([data-close-button]):hover {\n background: var(--gray2);\n border-color: var(--gray5);\n}\n:where([data-sonner-toast][data-swiping=true])::before {\n content: "";\n position: absolute;\n left: 0;\n right: 0;\n height: 100%;\n z-index: -1;\n}\n:where([data-sonner-toast][data-y-position=top][data-swiping=true])::before {\n bottom: 50%;\n transform: scaleY(3) translateY(50%);\n}\n:where([data-sonner-toast][data-y-position=bottom][data-swiping=true])::before {\n top: 50%;\n transform: scaleY(3) translateY(-50%);\n}\n:where([data-sonner-toast][data-swiping=false][data-removed=true])::before {\n content: "";\n position: absolute;\n inset: 0;\n transform: scaleY(2);\n}\n:where([data-sonner-toast])::after {\n content: "";\n position: absolute;\n left: 0;\n height: calc(var(--gap) + 1px);\n bottom: 100%;\n width: 100%;\n}\n:where([data-sonner-toast][data-mounted=true]) {\n --y: translateY(0);\n opacity: 1;\n}\n:where([data-sonner-toast][data-expanded=false][data-front=false]) {\n --scale: var(--toasts-before) * 0.05 + 1;\n --y: translateY(calc(var(--lift-amount) * var(--toasts-before))) scale(calc(-1 * var(--scale)));\n height: var(--front-toast-height);\n}\n:where([data-sonner-toast]) > * {\n transition: opacity 400ms;\n}\n:where([data-sonner-toast][data-expanded=false][data-front=false][data-styled=true]) > * {\n opacity: 0;\n}\n:where([data-sonner-toast][data-visible=false]) {\n opacity: 0;\n pointer-events: none;\n}\n:where([data-sonner-toast][data-mounted=true][data-expanded=true]) {\n --y: translateY(calc(var(--lift) * var(--offset)));\n height: var(--initial-height);\n}\n:where([data-sonner-toast][data-removed=true][data-front=true][data-swipe-out=false]) {\n --y: translateY(calc(var(--lift) * -100%));\n opacity: 0;\n}\n:where([data-sonner-toast][data-removed=true][data-front=false][data-swipe-out=false][data-expanded=true]) {\n --y: translateY(calc(var(--lift) * var(--offset) + var(--lift) * -100%));\n opacity: 0;\n}\n:where([data-sonner-toast][data-removed=true][data-front=false][data-swipe-out=false][data-expanded=false]) {\n --y: translateY(40%);\n opacity: 0;\n transition: transform 500ms, opacity 200ms;\n}\n:where([data-sonner-toast][data-removed=true][data-front=false])::before {\n height: calc(var(--initial-height) + 20%);\n}\n[data-sonner-toast][data-swiping=true] {\n transform: var(--y) translateY(var(--swipe-amount, 0px));\n transition: none;\n}\n[data-sonner-toast][data-swipe-out=true][data-y-position=bottom],\n[data-sonner-toast][data-swipe-out=true][data-y-position=top] {\n animation: swipe-out 200ms ease-out forwards;\n}\n@keyframes swipe-out {\n from {\n transform: translateY(calc(var(--lift) * var(--offset) + var(--swipe-amount)));\n opacity: 1;\n }\n to {\n transform: translateY(calc(var(--lift) * var(--offset) + var(--swipe-amount) + var(--lift) * -100%));\n opacity: 0;\n }\n}\n@media (max-width: 600px) {\n [data-sonner-toaster] {\n position: fixed;\n --mobile-offset: 16px;\n right: var(--mobile-offset);\n left: var(--mobile-offset);\n width: 100%;\n }\n [data-sonner-toaster] [data-sonner-toast] {\n left: 0;\n right: 0;\n width: calc(100% - var(--mobile-offset) * 2);\n }\n [data-sonner-toaster][data-x-position=left] {\n left: var(--mobile-offset);\n }\n [data-sonner-toaster][data-y-position=bottom] {\n bottom: 20px;\n }\n [data-sonner-toaster][data-y-position=top] {\n top: 20px;\n }\n [data-sonner-toaster][data-x-position=center] {\n left: var(--mobile-offset);\n right: var(--mobile-offset);\n transform: none;\n }\n}\n[data-sonner-toaster][data-theme=light] {\n --normal-bg: #fff;\n --normal-border: var(--gray4);\n --normal-text: var(--gray12);\n --success-bg: hsl(143, 85%, 96%);\n --success-border: hsl(145, 92%, 91%);\n --success-text: hsl(140, 100%, 27%);\n --info-bg: hsl(208, 100%, 97%);\n --info-border: hsl(221, 91%, 91%);\n --info-text: hsl(210, 92%, 45%);\n --warning-bg: hsl(49, 100%, 97%);\n --warning-border: hsl(49, 91%, 91%);\n --warning-text: hsl(31, 92%, 45%);\n --error-bg: hsl(359, 100%, 97%);\n --error-border: hsl(359, 100%, 94%);\n --error-text: hsl(360, 100%, 45%);\n}\n[data-sonner-toaster][data-theme=light] [data-sonner-toast][data-invert=true] {\n --normal-bg: #000;\n --normal-border: hsl(0, 0%, 20%);\n --normal-text: var(--gray1);\n}\n[data-sonner-toaster][data-theme=dark] [data-sonner-toast][data-invert=true] {\n --normal-bg: #fff;\n --normal-border: var(--gray3);\n --normal-text: var(--gray12);\n}\n[data-sonner-toaster][data-theme=dark] {\n --normal-bg: #000;\n --normal-border: hsl(0, 0%, 20%);\n --normal-text: var(--gray1);\n --success-bg: hsl(150, 100%, 6%);\n --success-border: hsl(147, 100%, 12%);\n --success-text: hsl(150, 86%, 65%);\n --info-bg: hsl(215, 100%, 6%);\n --info-border: hsl(223, 100%, 12%);\n --info-text: hsl(216, 87%, 65%);\n --warning-bg: hsl(64, 100%, 6%);\n --warning-border: hsl(60, 100%, 12%);\n --warning-text: hsl(46, 87%, 65%);\n --error-bg: hsl(358, 76%, 10%);\n --error-border: hsl(357, 89%, 16%);\n --error-text: hsl(358, 100%, 81%);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=success] {\n background: var(--success-bg);\n border-color: var(--success-border);\n color: var(--success-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=success] [data-close-button] {\n background: var(--success-bg);\n border-color: var(--success-border);\n color: var(--success-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=info] {\n background: var(--info-bg);\n border-color: var(--info-border);\n color: var(--info-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=info] [data-close-button] {\n background: var(--info-bg);\n border-color: var(--info-border);\n color: var(--info-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=warning] {\n background: var(--warning-bg);\n border-color: var(--warning-border);\n color: var(--warning-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=warning] [data-close-button] {\n background: var(--warning-bg);\n border-color: var(--warning-border);\n color: var(--warning-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=error] {\n background: var(--error-bg);\n border-color: var(--error-border);\n color: var(--error-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=error] [data-close-button] {\n background: var(--error-bg);\n border-color: var(--error-border);\n color: var(--error-text);\n}\n.sonner-loading-wrapper {\n --size: 16px;\n height: var(--size);\n width: var(--size);\n position: absolute;\n inset: 0;\n z-index: 10;\n}\n.sonner-loading-wrapper[data-visible=false] {\n transform-origin: center;\n animation: sonner-fade-out 0.2s ease forwards;\n}\n.sonner-spinner {\n position: relative;\n top: 50%;\n left: 50%;\n height: var(--size);\n width: var(--size);\n}\n.sonner-loading-bar {\n animation: sonner-spin 1.2s linear infinite;\n background: var(--gray11);\n border-radius: 6px;\n height: 8%;\n left: -10%;\n position: absolute;\n top: -3.9%;\n width: 24%;\n}\n.sonner-loading-bar:nth-child(1) {\n animation-delay: -1.2s;\n transform: rotate(0.0001deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(2) {\n animation-delay: -1.1s;\n transform: rotate(30deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(3) {\n animation-delay: -1s;\n transform: rotate(60deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(4) {\n animation-delay: -0.9s;\n transform: rotate(90deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(5) {\n animation-delay: -0.8s;\n transform: rotate(120deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(6) {\n animation-delay: -0.7s;\n transform: rotate(150deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(7) {\n animation-delay: -0.6s;\n transform: rotate(180deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(8) {\n animation-delay: -0.5s;\n transform: rotate(210deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(9) {\n animation-delay: -0.4s;\n transform: rotate(240deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(10) {\n animation-delay: -0.3s;\n transform: rotate(270deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(11) {\n animation-delay: -0.2s;\n transform: rotate(300deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(12) {\n animation-delay: -0.1s;\n transform: rotate(330deg) translate(146%);\n}\n@keyframes sonner-fade-in {\n 0% {\n opacity: 0;\n transform: scale(0.8);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n}\n@keyframes sonner-fade-out {\n 0% {\n opacity: 1;\n transform: scale(1);\n }\n 100% {\n opacity: 0;\n transform: scale(0.8);\n }\n}\n@keyframes sonner-spin {\n 0% {\n opacity: 1;\n }\n 100% {\n opacity: 0.15;\n }\n}\n@media (prefers-reduced-motion) {\n [data-sonner-toast],\n [data-sonner-toast] > *,\n .sonner-loading-bar {\n transition: none !important;\n animation: none !important;\n }\n}\n.sonner-loader {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n transform-origin: center;\n transition: opacity 200ms, transform 200ms;\n}\n.sonner-loader[data-visible=false] {\n opacity: 0;\n transform: scale(0.8) translate(-50%, -50%);\n}\n');
var _tmpl$ = /* @__PURE__ */ template(`<div class=sonner-loading-wrapper><div class=sonner-spinner>`);
styleInject('html[dir=ltr],\n[data-sonner-toaster][dir=ltr] {\n --toast-icon-margin-start: -3px;\n --toast-icon-margin-end: 4px;\n --toast-svg-margin-start: -1px;\n --toast-svg-margin-end: 0px;\n --toast-button-margin-start: auto;\n --toast-button-margin-end: 0;\n --toast-close-button-start: 0;\n --toast-close-button-end: unset;\n --toast-close-button-transform: translate(-35%, -35%);\n}\nhtml[dir=rtl],\n[data-sonner-toaster][dir=rtl] {\n --toast-icon-margin-start: 4px;\n --toast-icon-margin-end: -3px;\n --toast-svg-margin-start: 0px;\n --toast-svg-margin-end: -1px;\n --toast-button-margin-start: 0;\n --toast-button-margin-end: auto;\n --toast-close-button-start: unset;\n --toast-close-button-end: 0;\n --toast-close-button-transform: translate(35%, -35%);\n}\n[data-sonner-toaster] {\n position: fixed;\n width: var(--width);\n font-family:\n ui-sans-serif,\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n Segoe UI,\n Roboto,\n Helvetica Neue,\n Arial,\n Noto Sans,\n sans-serif,\n Apple Color Emoji,\n Segoe UI Emoji,\n Segoe UI Symbol,\n Noto Color Emoji;\n --gray1: hsl(0, 0%, 99%);\n --gray2: hsl(0, 0%, 97.3%);\n --gray3: hsl(0, 0%, 95.1%);\n --gray4: hsl(0, 0%, 93%);\n --gray5: hsl(0, 0%, 90.9%);\n --gray6: hsl(0, 0%, 88.7%);\n --gray7: hsl(0, 0%, 85.8%);\n --gray8: hsl(0, 0%, 78%);\n --gray9: hsl(0, 0%, 56.1%);\n --gray10: hsl(0, 0%, 52.3%);\n --gray11: hsl(0, 0%, 43.5%);\n --gray12: hsl(0, 0%, 9%);\n --border-radius: 8px;\n box-sizing: border-box;\n padding: 0;\n margin: 0;\n list-style: none;\n outline: none;\n z-index: 999999999;\n transition: transform 400ms ease;\n}\n@media (hover: none) and (pointer: coarse) {\n [data-sonner-toaster][data-lifted=true] {\n transform: none;\n }\n}\n[data-sonner-toaster][data-x-position=right] {\n right: var(--offset-right);\n}\n[data-sonner-toaster][data-x-position=left] {\n left: var(--offset-left);\n}\n[data-sonner-toaster][data-x-position=center] {\n left: 50%;\n transform: translateX(-50%);\n}\n[data-sonner-toaster][data-y-position=top] {\n top: var(--offset-top);\n}\n[data-sonner-toaster][data-y-position=bottom] {\n bottom: var(--offset-bottom);\n}\n[data-sonner-toast] {\n --y: translateY(100%);\n --lift-amount: calc(var(--lift) * var(--gap));\n z-index: var(--z-index);\n position: absolute;\n opacity: 0;\n transform: var(--y);\n touch-action: none;\n transition:\n transform 400ms,\n opacity 400ms,\n height 400ms,\n box-shadow 200ms;\n box-sizing: border-box;\n outline: none;\n overflow-wrap: anywhere;\n}\n[data-sonner-toast][data-styled=true] {\n padding: 16px;\n background: var(--normal-bg);\n border: 1px solid var(--normal-border);\n color: var(--normal-text);\n border-radius: var(--border-radius);\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1);\n width: var(--width);\n font-size: 13px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n[data-sonner-toast]:focus-visible {\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1), 0 0 0 2px rgba(0, 0, 0, 0.2);\n}\n[data-sonner-toast][data-y-position=top] {\n top: 0;\n --y: translateY(-100%);\n --lift: 1;\n --lift-amount: calc(1 * var(--gap));\n}\n[data-sonner-toast][data-y-position=bottom] {\n bottom: 0;\n --y: translateY(100%);\n --lift: -1;\n --lift-amount: calc(var(--lift) * var(--gap));\n}\n[data-sonner-toast][data-styled=true] [data-description] {\n font-weight: 400;\n line-height: 1.4;\n color: #3f3f3f;\n}\n[data-rich-colors=true][data-sonner-toast][data-styled=true] [data-description] {\n color: inherit;\n}\n[data-sonner-toaster][data-sonner-theme=dark] [data-description] {\n color: hsl(0, 0%, 91%);\n}\n[data-sonner-toast][data-styled=true] [data-title] {\n font-weight: 500;\n line-height: 1.5;\n color: inherit;\n}\n[data-sonner-toast][data-styled=true] [data-icon] {\n display: flex;\n height: 16px;\n width: 16px;\n position: relative;\n justify-content: flex-start;\n align-items: center;\n flex-shrink: 0;\n margin-left: var(--toast-icon-margin-start);\n margin-right: var(--toast-icon-margin-end);\n}\n[data-sonner-toast][data-promise=true] [data-icon] > svg {\n opacity: 0;\n transform: scale(0.8);\n transform-origin: center;\n animation: sonner-fade-in 300ms ease forwards;\n}\n[data-sonner-toast][data-styled=true] [data-icon] > * {\n flex-shrink: 0;\n}\n[data-sonner-toast][data-styled=true] [data-icon] svg {\n margin-left: var(--toast-svg-margin-start);\n margin-right: var(--toast-svg-margin-end);\n}\n[data-sonner-toast][data-styled=true] [data-content] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n[data-sonner-toast][data-styled=true] [data-button] {\n border-radius: 4px;\n padding-left: 8px;\n padding-right: 8px;\n height: 24px;\n font-size: 12px;\n color: var(--normal-bg);\n background: var(--normal-text);\n margin-left: var(--toast-button-margin-start);\n margin-right: var(--toast-button-margin-end);\n border: none;\n font-weight: 500;\n cursor: pointer;\n outline: none;\n display: flex;\n align-items: center;\n flex-shrink: 0;\n transition: opacity 400ms, box-shadow 200ms;\n}\n[data-sonner-toast][data-styled=true] [data-button]:focus-visible {\n box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.4);\n}\n[data-sonner-toast][data-styled=true] [data-button]:first-of-type {\n margin-left: var(--toast-button-margin-start);\n margin-right: var(--toast-button-margin-end);\n}\n[data-sonner-toast][data-styled=true] [data-cancel] {\n color: var(--normal-text);\n background: rgba(0, 0, 0, 0.08);\n}\n[data-sonner-toaster][data-sonner-theme=dark] [data-sonner-toast][data-styled=true] [data-cancel] {\n background: rgba(255, 255, 255, 0.3);\n}\n[data-sonner-toast][data-styled=true] [data-close-button] {\n position: absolute;\n left: var(--toast-close-button-start);\n right: var(--toast-close-button-end);\n top: 0;\n height: 20px;\n width: 20px;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 0;\n color: var(--normal-text);\n background: var(--normal-bg);\n border: 1px solid var(--normal-border);\n transform: var(--toast-close-button-transform);\n border-radius: 50%;\n cursor: pointer;\n z-index: 1;\n transition:\n opacity 100ms,\n background 200ms,\n border-color 200ms;\n}\n[data-sonner-toast][data-styled=true] [data-close-button]:focus-visible {\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1), 0 0 0 2px rgba(0, 0, 0, 0.2);\n}\n[data-sonner-toast][data-styled=true] [data-disabled=true] {\n cursor: not-allowed;\n}\n[data-sonner-toast][data-styled=true]:hover [data-close-button]:hover {\n background: var(--gray2);\n border-color: var(--gray5);\n}\n[data-sonner-toast][data-swiping=true]::before {\n content: "";\n position: absolute;\n left: -100%;\n right: -100%;\n height: 100%;\n z-index: -1;\n}\n[data-sonner-toast][data-y-position=top][data-swiping=true]::before {\n bottom: 50%;\n transform: scaleY(3) translateY(50%);\n}\n[data-sonner-toast][data-y-position=bottom][data-swiping=true]::before {\n top: 50%;\n transform: scaleY(3) translateY(-50%);\n}\n[data-sonner-toast][data-swiping=false][data-removed=true]::before {\n content: "";\n position: absolute;\n inset: 0;\n transform: scaleY(2);\n}\n[data-sonner-toast][data-expanded=true]::after {\n content: "";\n position: absolute;\n left: 0;\n height: calc(var(--gap) + 1px);\n bottom: 100%;\n width: 100%;\n}\n[data-sonner-toast][data-mounted=true] {\n --y: translateY(0);\n opacity: 1;\n}\n[data-sonner-toast][data-expanded=false][data-front=false] {\n --scale: var(--toasts-before) * 0.05 + 1;\n --y: translateY(calc(var(--lift-amount) * var(--toasts-before))) scale(calc(-1 * var(--scale)));\n height: var(--front-toast-height);\n}\n[data-sonner-toast] > * {\n transition: opacity 400ms;\n}\n[data-sonner-toast][data-x-position=right] {\n right: 0;\n}\n[data-sonner-toast][data-x-position=left] {\n left: 0;\n}\n[data-sonner-toast][data-expanded=false][data-front=false][data-styled=true] > * {\n opacity: 0;\n}\n[data-sonner-toast][data-visible=false] {\n opacity: 0;\n pointer-events: none;\n}\n[data-sonner-toast][data-mounted=true][data-expanded=true] {\n --y: translateY(calc(var(--lift) * var(--offset)));\n height: var(--initial-height);\n}\n[data-sonner-toast][data-removed=true][data-front=true][data-swipe-out=false] {\n --y: translateY(calc(var(--lift) * -100%));\n opacity: 0;\n}\n[data-sonner-toast][data-removed=true][data-front=false][data-swipe-out=false][data-expanded=true] {\n --y: translateY(calc(var(--lift) * var(--offset) + var(--lift) * -100%));\n opacity: 0;\n}\n[data-sonner-toast][data-removed=true][data-front=false][data-swipe-out=false][data-expanded=false] {\n --y: translateY(40%);\n opacity: 0;\n transition: transform 500ms, opacity 200ms;\n}\n[data-sonner-toast][data-removed=true][data-front=false]::before {\n height: calc(var(--initial-height) + 20%);\n}\n[data-sonner-toast][data-swiping=true] {\n transform: var(--y) translateY(var(--swipe-amount-y, 0px)) translateX(var(--swipe-amount-x, 0px));\n transition: none;\n}\n[data-sonner-toast][data-swiped=true] {\n -webkit-user-select: none;\n user-select: none;\n}\n[data-sonner-toast][data-swipe-out=true][data-y-position=bottom],\n[data-sonner-toast][data-swipe-out=true][data-y-position=top] {\n animation-duration: 200ms;\n animation-timing-function: ease-out;\n animation-fill-mode: forwards;\n}\n[data-sonner-toast][data-swipe-out=true][data-swipe-direction=left] {\n animation-name: swipe-out-left;\n}\n[data-sonner-toast][data-swipe-out=true][data-swipe-direction=right] {\n animation-name: swipe-out-right;\n}\n[data-sonner-toast][data-swipe-out=true][data-swipe-direction=up] {\n animation-name: swipe-out-up;\n}\n[data-sonner-toast][data-swipe-out=true][data-swipe-direction=down] {\n animation-name: swipe-out-down;\n}\n@keyframes swipe-out-left {\n from {\n transform: var(--y) translateX(var(--swipe-amount-x));\n opacity: 1;\n }\n to {\n transform: var(--y) translateX(calc(var(--swipe-amount-x) - 100%));\n opacity: 0;\n }\n}\n@keyframes swipe-out-right {\n from {\n transform: var(--y) translateX(var(--swipe-amount-x));\n opacity: 1;\n }\n to {\n transform: var(--y) translateX(calc(var(--swipe-amount-x) + 100%));\n opacity: 0;\n }\n}\n@keyframes swipe-out-up {\n from {\n transform: var(--y) translateY(var(--swipe-amount-y));\n opacity: 1;\n }\n to {\n transform: var(--y) translateY(calc(var(--swipe-amount-y) - 100%));\n opacity: 0;\n }\n}\n@keyframes swipe-out-down {\n from {\n transform: var(--y) translateY(var(--swipe-amount-y));\n opacity: 1;\n }\n to {\n transform: var(--y) translateY(calc(var(--swipe-amount-y) + 100%));\n opacity: 0;\n }\n}\n@media (max-width: 600px) {\n [data-sonner-toaster] {\n position: fixed;\n right: var(--mobile-offset-right);\n left: var(--mobile-offset-left);\n width: 100%;\n }\n [data-sonner-toaster][dir=rtl] {\n left: calc(var(--mobile-offset-left) * -1);\n }\n [data-sonner-toaster] [data-sonner-toast] {\n left: 0;\n right: 0;\n width: calc(100% - var(--mobile-offset-left) * 2);\n }\n [data-sonner-toaster][data-x-position=left] {\n left: var(--mobile-offset-left);\n }\n [data-sonner-toaster][data-y-position=bottom] {\n bottom: var(--mobile-offset-bottom);\n }\n [data-sonner-toaster][data-y-position=top] {\n top: var(--mobile-offset-top);\n }\n [data-sonner-toaster][data-x-position=center] {\n left: var(--mobile-offset-left);\n right: var(--mobile-offset-right);\n transform: none;\n }\n}\n[data-sonner-toaster][data-sonner-theme=light] {\n --normal-bg: #fff;\n --normal-border: var(--gray4);\n --normal-text: var(--gray12);\n --success-bg: hsl(143, 85%, 96%);\n --success-border: hsl(145, 92%, 87%);\n --success-text: hsl(140, 100%, 27%);\n --info-bg: hsl(208, 100%, 97%);\n --info-border: hsl(221, 91%, 93%);\n --info-text: hsl(210, 92%, 45%);\n --warning-bg: hsl(49, 100%, 97%);\n --warning-border: hsl(49, 91%, 84%);\n --warning-text: hsl(31, 92%, 45%);\n --error-bg: hsl(359, 100%, 97%);\n --error-border: hsl(359, 100%, 94%);\n --error-text: hsl(360, 100%, 45%);\n}\n[data-sonner-toaster][data-sonner-theme=light] [data-sonner-toast][data-invert=true] {\n --normal-bg: #000;\n --normal-border: hsl(0, 0%, 20%);\n --normal-text: var(--gray1);\n}\n[data-sonner-toaster][data-sonner-theme=dark] [data-sonner-toast][data-invert=true] {\n --normal-bg: #fff;\n --normal-border: var(--gray3);\n --normal-text: var(--gray12);\n}\n[data-sonner-toaster][data-sonner-theme=dark] {\n --normal-bg: #000;\n --normal-bg-hover: hsl(0, 0%, 12%);\n --normal-border: hsl(0, 0%, 20%);\n --normal-border-hover: hsl(0, 0%, 25%);\n --normal-text: var(--gray1);\n --success-bg: hsl(150, 100%, 6%);\n --success-border: hsl(147, 100%, 12%);\n --success-text: hsl(150, 86%, 65%);\n --info-bg: hsl(215, 100%, 6%);\n --info-border: hsl(223, 43%, 17%);\n --info-text: hsl(216, 87%, 65%);\n --warning-bg: hsl(64, 100%, 6%);\n --warning-border: hsl(60, 100%, 9%);\n --warning-text: hsl(46, 87%, 65%);\n --error-bg: hsl(358, 76%, 10%);\n --error-border: hsl(357, 89%, 16%);\n --error-text: hsl(358, 100%, 81%);\n}\n[data-sonner-toaster][data-sonner-theme=dark] [data-sonner-toast] [data-close-button] {\n background: var(--normal-bg);\n border-color: var(--normal-border);\n color: var(--normal-text);\n}\n[data-sonner-toaster][data-sonner-theme=dark] [data-sonner-toast] [data-close-button]:hover {\n background: var(--normal-bg-hover);\n border-color: var(--normal-border-hover);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=success] {\n background: var(--success-bg);\n border-color: var(--success-border);\n color: var(--success-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=success] [data-close-button] {\n background: var(--success-bg);\n border-color: var(--success-border);\n color: var(--success-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=info] {\n background: var(--info-bg);\n border-color: var(--info-border);\n color: var(--info-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=info] [data-close-button] {\n background: var(--info-bg);\n border-color: var(--info-border);\n color: var(--info-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=warning] {\n background: var(--warning-bg);\n border-color: var(--warning-border);\n color: var(--warning-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=warning] [data-close-button] {\n background: var(--warning-bg);\n border-color: var(--warning-border);\n color: var(--warning-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=error] {\n background: var(--error-bg);\n border-color: var(--error-border);\n color: var(--error-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=error] [data-close-button] {\n background: var(--error-bg);\n border-color: var(--error-border);\n color: var(--error-text);\n}\n.sonner-loading-wrapper {\n --size: 16px;\n height: var(--size);\n width: var(--size);\n position: absolute;\n inset: 0;\n z-index: 10;\n}\n.sonner-loading-wrapper[data-visible=false] {\n transform-origin: center;\n animation: sonner-fade-out 0.2s ease forwards;\n}\n.sonner-spinner {\n position: relative;\n top: 50%;\n left: 50%;\n height: var(--size);\n width: var(--size);\n}\n.sonner-loading-bar {\n animation: sonner-spin 1.2s linear infinite;\n background: var(--gray11);\n border-radius: 6px;\n height: 8%;\n left: -10%;\n position: absolute;\n top: -3.9%;\n width: 24%;\n}\n.sonner-loading-bar:nth-child(1) {\n animation-delay: -1.2s;\n transform: rotate(0.0001deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(2) {\n animation-delay: -1.1s;\n transform: rotate(30deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(3) {\n animation-delay: -1s;\n transform: rotate(60deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(4) {\n animation-delay: -0.9s;\n transform: rotate(90deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(5) {\n animation-delay: -0.8s;\n transform: rotate(120deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(6) {\n animation-delay: -0.7s;\n transform: rotate(150deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(7) {\n animation-delay: -0.6s;\n transform: rotate(180deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(8) {\n animation-delay: -0.5s;\n transform: rotate(210deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(9) {\n animation-delay: -0.4s;\n transform: rotate(240deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(10) {\n animation-delay: -0.3s;\n transform: rotate(270deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(11) {\n animation-delay: -0.2s;\n transform: rotate(300deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(12) {\n animation-delay: -0.1s;\n transform: rotate(330deg) translate(146%);\n}\n@keyframes sonner-fade-in {\n 0% {\n opacity: 0;\n transform: scale(0.8);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n}\n@keyframes sonner-fade-out {\n 0% {\n opacity: 1;\n transform: scale(1);\n }\n 100% {\n opacity: 0;\n transform: scale(0.8);\n }\n}\n@keyframes sonner-spin {\n 0% {\n opacity: 1;\n }\n 100% {\n opacity: 0.15;\n }\n}\n@media (prefers-reduced-motion) {\n [data-sonner-toast],\n [data-sonner-toast] > *,\n .sonner-loading-bar {\n transition: none !important;\n animation: none !important;\n }\n}\n.sonner-loader {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n transform-origin: center;\n transition: opacity 200ms, transform 200ms;\n}\n.sonner-loader[data-visible=false] {\n opacity: 0;\n transform: scale(0.8) translate(-50%, -50%);\n}\n');
var _tmpl$ = /* @__PURE__ */ template(`<div><div class=sonner-spinner>`);
var _tmpl$2 = /* @__PURE__ */ template(`<div class=sonner-loading-bar>`);

@@ -38,2 +38,3 @@ var _tmpl$3 = /* @__PURE__ */ template(`<svg xmlns=http://www.w3.org/2000/svg viewBox="0 0 20 20"fill=currentColor height=20 width=20><path fill-rule=evenodd d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"clip-rule=evenodd>`);

var _tmpl$6 = /* @__PURE__ */ template(`<svg xmlns=http://www.w3.org/2000/svg viewBox="0 0 20 20"fill=currentColor height=20 width=20><path fill-rule=evenodd d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-5a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 5zm0 10a1 1 0 100-2 1 1 0 000 2z"clip-rule=evenodd>`);
var _tmpl$7 = /* @__PURE__ */ template(`<svg xmlns=http://www.w3.org/2000/svg width=12 height=12 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=1.5 stroke-linecap=round stroke-linejoin=round><line x1=18 y1=6 x2=6 y2=18></line><line x1=6 y1=6 x2=18 y2=18>`);
var bars = Array(12).fill(0);

@@ -45,5 +46,17 @@ function Loader(props) {

each: bars,
children: () => _tmpl$2()
children: (_, i) => (() => {
var _el$3 = _tmpl$2();
effect(() => setAttribute(_el$3, "data-index", i()));
return _el$3;
})()
}));
effect(() => setAttribute(_el$, "data-visible", props.visible));
effect((_p$) => {
var _v$ = ["sonner-loading-wrapper", props.class ?? props.className].filter(Boolean).join(" "), _v$2 = props.visible;
_v$ !== _p$.e && className(_el$, _p$.e = _v$);
_v$2 !== _p$.t && setAttribute(_el$, "data-visible", _p$.t = _v$2);
return _p$;
}, {
e: void 0,
t: void 0
});
return _el$;

@@ -67,9 +80,9 @@ })();

case "success":
return SuccessIcon;
return createComponent(SuccessIcon, {});
case "info":
return InfoIcon;
return createComponent(InfoIcon, {});
case "warning":
return WarningIcon;
return createComponent(WarningIcon, {});
case "error":
return ErrorIcon;
return createComponent(ErrorIcon, {});
default:

@@ -79,13 +92,30 @@ return null;

}
function CloseIcon() {
return _tmpl$7();
}
function useIsDocumentHidden() {
const [isDocumentHidden, setIsDocumentHidden] = createSignal(typeof document !== "undefined" ? document.hidden : false);
onMount(() => {
const callback = () => {
setIsDocumentHidden(document.hidden);
};
document.addEventListener("visibilitychange", callback);
onCleanup(() => {
document.removeEventListener("visibilitychange", callback);
});
});
return isDocumentHidden;
}
// src/state.ts
var toastsCounter = 0;
var toastsCounter = 1;
var Observer = class {
subscribers;
toasts;
dismissedToasts;
constructor() {
this.subscribers = [];
this.toasts = [];
this.dismissedToasts = /* @__PURE__ */ new Set();
}
// We use arrow functions to maintain the correct `this` reference
subscribe = (subscriber) => {

@@ -107,11 +137,21 @@ this.subscribers.push(subscriber);

const { message, ...rest } = data;
const id = typeof data?.id === "number" || data.id && data.id?.length > 0 ? data.id : toastsCounter++;
const hasStringId = typeof data.id === "string" && data.id.length > 0;
const id = typeof data.id === "number" || hasStringId ? data.id : toastsCounter++;
const alreadyExists = this.toasts.find((toast2) => {
return toast2.id === id;
});
const dismissible = data.dismissible === void 0 ? true : data.dismissible;
if (this.dismissedToasts.has(id))
this.dismissedToasts.delete(id);
if (alreadyExists) {
this.toasts = this.toasts.map((toast2) => {
if (toast2.id === id) {
this.publish({ ...toast2, ...data, id, title: message });
return { ...toast2, ...data, id, title: message };
this.publish({ ...toast2, ...data, id, title: message, dismissible });
return {
...toast2,
...data,
id,
dismissible,
title: message
};
}

@@ -121,3 +161,3 @@ return toast2;

} else {
this.addToast({ title: message, ...rest, id });
this.addToast({ title: message, ...rest, dismissible, id });
}

@@ -127,8 +167,13 @@ return id;

dismiss = (id) => {
if (!id) {
if (id) {
this.dismissedToasts.add(id);
requestAnimationFrame(() => {
this.subscribers.forEach((subscriber) => subscriber({ id, dismiss: true }));
});
} else {
this.toasts.forEach((toast2) => {
this.dismissedToasts.add(toast2.id);
this.subscribers.forEach((subscriber) => subscriber({ id: toast2.id, dismiss: true }));
});
}
this.subscribers.forEach((subscriber) => subscriber({ id, dismiss: true }));
return id;

@@ -151,6 +196,8 @@ };

};
loading = (message, data) => {
return this.create({ ...data, type: "loading", message });
};
promise = (promise, data) => {
if (!data) {
if (!data)
return;
}
let id;

@@ -162,22 +209,41 @@ if (data.loading !== void 0) {

type: "loading",
message: data.loading
message: data.loading,
description: typeof data.description !== "function" ? data.description : void 0
});
}
const p = promise instanceof Promise ? promise : promise();
const p = Promise.resolve(typeof promise === "function" ? promise() : promise);
let shouldDismiss = id !== void 0;
p.then((response) => {
if (response && typeof response.ok === "boolean" && !response.ok) {
let result;
const originalPromise = p.then(async (response) => {
result = ["resolve", response];
if (isValidElement(response)) {
shouldDismiss = false;
const message = typeof data.error === "function" ? data.error(`HTTP error! status: ${response.status}`) : data.error;
this.create({ id, type: "error", message });
this.create({ id, type: "default", message: response });
} else if (isHttpResponse(response) && !response.ok) {
shouldDismiss = false;
const promiseData = typeof data.error === "function" ? await data.error(`HTTP error! status: ${response.status}`) : data.error;
const description = typeof data.description === "function" ? await data.description(`HTTP error! status: ${response.status}`) : data.description;
const toastSettings = isExtendedResult(promiseData) ? promiseData : { message: promiseData };
this.create({ id, type: "error", description, ...toastSettings });
} else if (response instanceof Error) {
shouldDismiss = false;
const promiseData = typeof data.error === "function" ? await data.error(response) : data.error;
const description = typeof data.description === "function" ? await data.description(response) : data.description;
const toastSettings = isExtendedResult(promiseData) ? promiseData : { message: promiseData };
this.create({ id, type: "error", description, ...toastSettings });
} else if (data.success !== void 0) {
shouldDismiss = false;
const message = typeof data.success === "function" ? data.success(response) : data.success;
this.create({ id, type: "success", message });
const promiseData = typeof data.success === "function" ? await data.success(response) : data.success;
const description = typeof data.description === "function" ? await data.description(response) : data.description;
const toastSettings = isExtendedResult(promiseData) ? promiseData : { message: promiseData };
this.create({ id, type: "success", description, ...toastSettings });
}
}).catch((error) => {
}).catch(async (error) => {
result = ["reject", error];
if (data.error !== void 0) {
shouldDismiss = false;
const message = typeof data.error === "function" ? data.error(error) : data.error;
this.create({ id, type: "error", message });
const promiseData = typeof data.error === "function" ? await data.error(error) : data.error;
const description = typeof data.description === "function" ? await data.description(error) : data.description;
const toastSettings = isExtendedResult(promiseData) ? promiseData : { message: promiseData };
this.create({ id, type: "error", description, ...toastSettings });
}

@@ -191,14 +257,32 @@ }).finally(() => {

});
return id;
const unwrap = () => new Promise((resolve, reject) => {
originalPromise.then(() => {
if (result[0] === "reject")
reject(result[1]);
else
resolve(result[1]);
}).catch(reject);
});
if (typeof id !== "string" && typeof id !== "number")
return { unwrap };
return Object.assign(id, { unwrap });
};
loading = (message, data) => {
return this.create({ ...data, type: "loading", message });
};
// We can't provide the toast we just created as a prop as we didn't create it yet, so we can create a default toast object, I just don't know how to use function in argument when calling()?
custom = (jsx, data) => {
const id = data?.id || toastsCounter++;
this.publish({ jsx: jsx(id), id, ...data });
this.create({ jsx: jsx(id), ...data, id });
return id;
};
getActiveToasts = () => {
return this.toasts.filter((toast2) => !this.dismissedToasts.has(toast2.id));
};
};
function isHttpResponse(data) {
return data && typeof data === "object" && "ok" in data && typeof data.ok === "boolean" && "status" in data && typeof data.status === "number";
}
function isExtendedResult(value) {
return typeof value === "object" && value !== null && "message" in value;
}
function isValidElement(value) {
return typeof Node !== "undefined" && value instanceof Node;
}
var ToastState = new Observer();

@@ -215,49 +299,129 @@ function toastFunction(message, data) {

var basicToast = toastFunction;
var toast = Object.assign(basicToast, {
success: ToastState.success,
info: ToastState.info,
warning: ToastState.warning,
error: ToastState.error,
custom: ToastState.custom,
message: ToastState.message,
promise: ToastState.promise,
dismiss: ToastState.dismiss,
loading: ToastState.loading
});
function useIsDocumentHidden() {
const [isDocumentHidden, setIsDocumentHidden] = createSignal(false);
onMount(() => {
const callback = () => {
setIsDocumentHidden(document.hidden);
};
document.addEventListener("visibilitychange", callback);
onCleanup(() => {
window.removeEventListener("visibilitychange", callback);
});
});
return isDocumentHidden;
var getHistory = () => ToastState.toasts;
var getToasts = () => ToastState.getActiveToasts();
var toast = Object.assign(
basicToast,
{
success: ToastState.success,
info: ToastState.info,
warning: ToastState.warning,
error: ToastState.error,
custom: ToastState.custom,
message: ToastState.message,
promise: ToastState.promise,
dismiss: ToastState.dismiss,
loading: ToastState.loading
},
{
getHistory,
getToasts
}
);
// src/types.ts
function isAction(action) {
return typeof action === "object" && action !== null && "label" in action;
}
// src/index.tsx
var _tmpl$7 = /* @__PURE__ */ template(`<div class=sonner-loader>`);
var _tmpl$22 = /* @__PURE__ */ template(`<button aria-label="Close toast"data-close-button><svg xmlns=http://www.w3.org/2000/svg width=12 height=12 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=1.5 stroke-linecap=round stroke-linejoin=round><line x1=18 y1=6 x2=6 y2=18></line><line x1=6 y1=6 x2=18 y2=18>`);
var _tmpl$32 = /* @__PURE__ */ template(`<li aria-atomic=true role=status tabindex=0 data-sonner-toast="">`);
var _tmpl$42 = /* @__PURE__ */ template(`<div data-icon="">`);
var _tmpl$52 = /* @__PURE__ */ template(`<div data-description="">`);
var _tmpl$62 = /* @__PURE__ */ template(`<div data-content=""><div data-title="">`);
var _tmpl$72 = /* @__PURE__ */ template(`<button data-button data-cancel>`);
var _tmpl$8 = /* @__PURE__ */ template(`<button data-button="">`);
var _tmpl$9 = /* @__PURE__ */ template(`<section tabindex=-1>`);
var _tmpl$10 = /* @__PURE__ */ template(`<ol tabindex=-1 data-sonner-toaster>`);
var _tmpl$8 = /* @__PURE__ */ template(`<div>`);
var _tmpl$22 = /* @__PURE__ */ template(`<button data-close-button>`);
var _tmpl$32 = /* @__PURE__ */ template(`<div data-icon>`);
var _tmpl$42 = /* @__PURE__ */ template(`<div data-description>`);
var _tmpl$52 = /* @__PURE__ */ template(`<li tabindex=0 data-sonner-toast><div data-content><div data-title>`);
var _tmpl$62 = /* @__PURE__ */ template(`<button data-button data-cancel>`);
var _tmpl$72 = /* @__PURE__ */ template(`<button data-button data-action>`);
var _tmpl$82 = /* @__PURE__ */ template(`<section tabindex=-1 aria-live=polite aria-relevant="additions text"aria-atomic=false data-react-aria-top-layer>`);
var _tmpl$9 = /* @__PURE__ */ template(`<ol tabindex=-1 data-sonner-toaster style=--width:356px>`);
var VISIBLE_TOASTS_AMOUNT = 3;
var VIEWPORT_OFFSET = "32px";
var VIEWPORT_OFFSET = "24px";
var MOBILE_VIEWPORT_OFFSET = "16px";
var TOAST_LIFETIME = 4e3;
var TOAST_WIDTH = 356;
var GAP = 14;
var SWIPE_TRESHOLD = 20;
var SWIPE_THRESHOLD = 45;
var TIME_BEFORE_UNMOUNT = 200;
function _cn(...classes) {
function cn(...classes) {
return classes.filter(Boolean).join(" ");
}
var Toast = (props) => {
function resolveContent(content) {
return typeof content === "function" ? content() : content;
}
function getDefaultSwipeDirections(position) {
const [y, x] = position.split("-");
const directions = [];
if (y) directions.push(y);
if (x) directions.push(x);
return directions;
}
function getDocumentDirection() {
if (typeof window === "undefined" || typeof document === "undefined") return "ltr";
const dirAttribute = document.documentElement.getAttribute("dir");
if (dirAttribute === "auto" || !dirAttribute) return window.getComputedStyle(document.documentElement).direction;
return dirAttribute;
}
function assignOffset(defaultOffset, mobileOffset) {
const styles = {};
[defaultOffset, mobileOffset].forEach((offset, index) => {
const isMobile = index === 1;
const prefix = isMobile ? "--mobile-offset" : "--offset";
const defaultValue = isMobile ? MOBILE_VIEWPORT_OFFSET : VIEWPORT_OFFSET;
const assignAll = (value) => {
for (const key of ["top", "right", "bottom", "left"]) styles[`${prefix}-${key}`] = typeof value === "number" ? `${value}px` : value;
};
if (typeof offset === "number" || typeof offset === "string") {
assignAll(offset);
return;
}
if (typeof offset === "object" && offset !== null) {
for (const key of ["top", "right", "bottom", "left"]) {
const value = offset[key];
styles[`${prefix}-${key}`] = value === void 0 ? defaultValue : typeof value === "number" ? `${value}px` : value;
}
return;
}
assignAll(defaultValue);
});
return styles;
}
function mergeClassNames(classNames, legacy) {
return classNames ?? legacy;
}
function mergeDescriptionClassName(descriptionClassName, legacy) {
return descriptionClassName ?? legacy ?? "";
}
function mergeClassName(className, legacy) {
return className ?? legacy ?? "";
}
function useSonner() {
const [activeToasts, setActiveToasts] = createSignal(toast.getToasts());
onMount(() => {
const unsubscribe = ToastState.subscribe((toastItem) => {
if (toastItem.dismiss) {
requestAnimationFrame(() => {
setActiveToasts((toasts) => toasts.filter((t) => t.id !== toastItem.id));
});
return;
}
const nextToast = toastItem;
setActiveToasts((toasts) => {
const indexOfExistingToast = toasts.findIndex((t) => t.id === nextToast.id);
if (indexOfExistingToast !== -1) {
return [...toasts.slice(0, indexOfExistingToast), {
...toasts[indexOfExistingToast],
...nextToast
}, ...toasts.slice(indexOfExistingToast + 1)];
}
return [nextToast, ...toasts];
});
});
onCleanup(unsubscribe);
});
return {
toasts: activeToasts
};
}
function createToastTheme(theme) {
return theme !== "system" ? theme : typeof window !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
}
function Toast(props) {
const [mounted, setMounted] = createSignal(false);

@@ -267,20 +431,32 @@ const [removed, setRemoved] = createSignal(false);

const [swipeOut, setSwipeOut] = createSignal(false);
const [isSwiped, setIsSwiped] = createSignal(false);
const [swipeDirection, setSwipeDirection] = createSignal(null);
const [swipeOutDirection, setSwipeOutDirection] = createSignal(null);
const [offsetBeforeRemove, setOffsetBeforeRemove] = createSignal(0);
const [initialHeight, setInitialHeight] = createSignal(0);
let toastRef;
let dragStartTime = null;
let closeTimerStartTimeRef = 0;
let lastCloseTimerStartTimeRef = 0;
let remainingTime = TOAST_LIFETIME;
const [pointerStartRef, setPointerStartRef] = createSignal(null);
const isFront = () => props.index === 0;
const isVisible = () => props.index + 1 <= props.visibleToasts;
const toastType = () => props.toast.type;
const toastClassname = () => props.toast.class || "";
const toastDescriptionClassname = () => props.toast.descriptionClass || "";
const propsWithDefaults = mergeProps({
gap: GAP
}, props);
const heightIndex = () => props.heights.findIndex((height) => height.toastId === props.toast.id) || 0;
const duration = () => props.toast.duration || props.duration || TOAST_LIFETIME;
let closeTimerStartTimeRef = 0;
let lastCloseTimerStartTimeRef = 0;
const [pointerStartRef, setPointerStartRef] = createSignal(null);
const coords = () => props.position.split("-");
const toastsHeightBefore = () => {
const dismissible = () => props.toast.dismissible !== false;
const classNames = () => mergeClassNames(props.classNames, props.classes);
const className$1 = () => mergeClassName(props.className, props.class);
const descriptionClassName = () => mergeDescriptionClassName(props.descriptionClassName, props.descriptionClass);
const toastClassName = () => mergeClassName(props.toast.className, props.toast.class);
const toastDescriptionClassName = () => mergeDescriptionClassName(props.toast.descriptionClassName, props.toast.descriptionClass);
const toastClassNames = () => mergeClassNames(props.toast.classNames, props.toast.classes);
const closeButton = () => props.toast.closeButton ?? props.closeButton;
const duration = () => props.toast.duration ?? props.duration ?? TOAST_LIFETIME;
const invert = () => props.toast.invert ?? props.invert;
const disabled = () => toastType() === "loading";
const swipeDirections = () => props.swipeDirections ?? getDefaultSwipeDirections(props.position);
const y = createMemo(() => props.position.split("-")[0]);
const x = createMemo(() => props.position.split("-")[1]);
const heightIndex = createMemo(() => Math.max(0, props.heights.findIndex((height) => height.toastId === props.toast.id)));
const toastsHeightBefore = createMemo(() => {
return props.heights.reduce((prev, curr, reducerIndex) => {

@@ -290,13 +466,30 @@ if (reducerIndex >= heightIndex()) return prev;

}, 0);
};
});
const offset = createMemo(() => heightIndex() * (props.gap ?? GAP) + toastsHeightBefore());
const isDocumentHidden = useIsDocumentHidden();
const invert = () => props.toast.invert || props.invert;
const disabled = () => toastType() === "loading";
const offset = () => heightIndex() * propsWithDefaults.gap + toastsHeightBefore();
createEffect(() => {
remainingTime = duration();
});
function deleteToast() {
setRemoved(true);
setOffsetBeforeRemove(offset());
props.setHeights((heights) => heights.filter((height) => height.toastId !== props.toast.id));
window.setTimeout(() => {
props.removeToast(props.toast);
}, TIME_BEFORE_UNMOUNT);
}
function getLoadingIcon() {
if (props.icons?.loading) {
return (() => {
var _el$ = _tmpl$7();
var _el$ = _tmpl$8();
insert(_el$, () => props.icons.loading);
effect(() => setAttribute(_el$, "data-visible", toastType() === "loading"));
effect((_p$) => {
var _v$ = cn(classNames()?.loader, toastClassNames()?.loader, "sonner-loader"), _v$2 = toastType() === "loading";
_v$ !== _p$.e && className(_el$, _p$.e = _v$);
_v$2 !== _p$.t && setAttribute(_el$, "data-visible", _p$.t = _v$2);
return _p$;
}, {
e: void 0,
t: void 0
});
return _el$;

@@ -306,2 +499,5 @@ })();

return createComponent(Loader, {
get ["class"]() {
return cn(classNames()?.loader, toastClassNames()?.loader);
},
get visible() {

@@ -312,38 +508,43 @@ return toastType() === "loading";

}
const icon = () => props.toast.icon ?? props.icons?.[toastType()] ?? getAsset(toastType());
onMount(() => {
setMounted(true);
if (!toastRef) return;
const height = toastRef.getBoundingClientRect().height;
setInitialHeight(height);
props.setHeights((h) => [{
toastId: props.toast.id,
toasterId: props.toast.toasterId,
height,
position: props.toast.position
}, ...h]);
onCleanup(() => {
props.setHeights((h) => h.filter((height2) => height2.toastId !== props.toast.id));
});
});
onMount(() => {
const toastNode = toastRef;
const originalHeight = toastNode.style.height;
toastNode.style.height = "auto";
const newHeight = toastNode.getBoundingClientRect().height;
toastNode.style.height = originalHeight;
setInitialHeight(newHeight);
createEffect(() => {
props.setHeights((heights) => {
const alreadyExists = heights.find((height) => height.toastId === props.toast.id);
if (!alreadyExists) return [{
toastId: props.toast.id,
height: newHeight,
position: props.toast.position
}, ...heights];
else return heights.map((height) => height.toastId === props.toast.id ? {
...height,
height: newHeight
} : height);
});
createEffect(() => {
if (!mounted() || !toastRef) return;
resolveContent(props.toast.title);
resolveContent(props.toast.description);
const originalHeight = toastRef.style.height;
toastRef.style.height = "auto";
const nextHeight = toastRef.getBoundingClientRect().height;
toastRef.style.height = originalHeight;
setInitialHeight(nextHeight);
props.setHeights((heights) => {
const alreadyExists = heights.find((height) => height.toastId === props.toast.id);
if (!alreadyExists) return [{
toastId: props.toast.id,
toasterId: props.toast.toasterId,
height: nextHeight,
position: props.toast.position
}, ...heights];
return heights.map((height) => height.toastId === props.toast.id ? {
...height,
height: nextHeight
} : height);
});
});
const deleteToast = () => {
setRemoved(true);
setOffsetBeforeRemove(offset());
props.setHeights((h) => h.filter((height) => height.toastId !== props.toast.id));
setTimeout(() => {
props.removeToast(props.toast);
}, TIME_BEFORE_UNMOUNT);
};
let remainingTime = duration();
createEffect(on(() => [props.expanded, props.interacting, props.toast, duration(), props.toast.promise, toastType(), props.pauseWhenPageIsHidden, isDocumentHidden()], ([expanded, interacting, toast2, duration2, promise, toastType2, pauseWhenPageIsHidden, isDocumentHidden2]) => {
if (promise && toastType2 === "loading" || duration2 === Number.POSITIVE_INFINITY) return;
createEffect(on(() => [props.expanded, props.interacting, props.toast, toastType(), isDocumentHidden(), duration()], ([expanded, interacting, currentToast, currentType]) => {
if (currentToast.promise && currentType === "loading" || currentToast.duration === Number.POSITIVE_INFINITY || currentType === "loading") return;
let timeoutId;

@@ -353,3 +554,3 @@ const pauseTimer = () => {

const elapsedTime = (/* @__PURE__ */ new Date()).getTime() - closeTimerStartTimeRef;
remainingTime = remainingTime - elapsedTime;
remainingTime -= elapsedTime;
}

@@ -359,55 +560,66 @@ lastCloseTimerStartTimeRef = (/* @__PURE__ */ new Date()).getTime();

const startTimer = () => {
if (remainingTime === Number.POSITIVE_INFINITY) return;
closeTimerStartTimeRef = (/* @__PURE__ */ new Date()).getTime();
timeoutId = setTimeout(() => {
toast2.onAutoClose?.(toast2);
currentToast.onAutoClose?.(currentToast);
deleteToast();
}, remainingTime);
};
if (expanded || interacting || pauseWhenPageIsHidden && isDocumentHidden2) pauseTimer();
const shouldPause = expanded || interacting || (props.pauseWhenPageIsHidden ?? true) && isDocumentHidden();
if (shouldPause) pauseTimer();
else startTimer();
onCleanup(() => {
clearTimeout(timeoutId);
if (timeoutId) clearTimeout(timeoutId);
});
}));
createEffect(on(() => props.toast.id, (toastId) => {
const toastNode = toastRef;
if (toastNode) {
const height = toastNode.getBoundingClientRect().height;
setInitialHeight(height);
props.setHeights((h) => [{
toastId,
height,
position: props.toast.position
}, ...h]);
onCleanup(() => {
props.setHeights((h) => h.filter((height2) => height2.toastId !== toastId));
});
createEffect(on(() => props.toast.delete, (shouldDelete) => {
if (shouldDelete) {
deleteToast();
props.toast.onDismiss?.(props.toast);
}
}));
createEffect(on(() => props.toast.delete, (d) => {
if (d) deleteToast();
}));
return (() => {
var _el$2 = _tmpl$32();
var _el$2 = _tmpl$52(), _el$5 = _el$2.firstChild, _el$6 = _el$5.firstChild;
_el$2.$$pointermove = (event) => {
if (!pointerStartRef()) return;
const yPosition = event.clientY - pointerStartRef().y;
const xPosition = event.clientX - pointerStartRef().x;
const clamp = coords()[0] === "top" ? Math.min : Math.max;
const clampedY = clamp(0, yPosition);
const swipeStartThreshold = event.pointerType === "touch" ? 10 : 2;
const isAllowedToSwipe = Math.abs(clampedY) > swipeStartThreshold;
if (isAllowedToSwipe) {
toastRef?.style.setProperty("--swipe-amount", `${yPosition}px`);
} else if (Math.abs(xPosition) > swipeStartThreshold) {
setPointerStartRef(null);
if (!pointerStartRef() || !dismissible()) return;
if ((window.getSelection()?.toString().length ?? 0) > 0) return;
const yDelta = event.clientY - pointerStartRef().y;
const xDelta = event.clientX - pointerStartRef().x;
if (!swipeDirection() && (Math.abs(xDelta) > 1 || Math.abs(yDelta) > 1)) setSwipeDirection(Math.abs(xDelta) > Math.abs(yDelta) ? "x" : "y");
const swipeAmount = {
x: 0,
y: 0
};
const getDampening = (delta) => {
const factor = Math.abs(delta) / 20;
return 1 / (1.5 + factor);
};
if (swipeDirection() === "y") {
if (swipeDirections().includes("top") || swipeDirections().includes("bottom")) {
if (swipeDirections().includes("top") && yDelta < 0 || swipeDirections().includes("bottom") && yDelta > 0) swipeAmount.y = yDelta;
else swipeAmount.y = yDelta * getDampening(yDelta);
}
} else if (swipeDirection() === "x") {
if (swipeDirections().includes("left") || swipeDirections().includes("right")) {
if (swipeDirections().includes("left") && xDelta < 0 || swipeDirections().includes("right") && xDelta > 0) swipeAmount.x = xDelta;
else swipeAmount.x = xDelta * getDampening(xDelta);
}
}
if (Math.abs(swipeAmount.x) > 0 || Math.abs(swipeAmount.y) > 0) setIsSwiped(true);
toastRef?.style.setProperty("--swipe-amount-x", `${swipeAmount.x}px`);
toastRef?.style.setProperty("--swipe-amount-y", `${swipeAmount.y}px`);
};
_el$2.$$pointerup = () => {
if (swipeOut()) return;
if (swipeOut() || !dismissible()) return;
setPointerStartRef(null);
const swipeAmount = Number(toastRef?.style.getPropertyValue("--swipe-amount").replace("px", "") || 0);
if (Math.abs(swipeAmount) >= SWIPE_TRESHOLD) {
const swipeAmountX = Number(toastRef?.style.getPropertyValue("--swipe-amount-x").replace("px", "") || 0);
const swipeAmountY = Number(toastRef?.style.getPropertyValue("--swipe-amount-y").replace("px", "") || 0);
const timeTaken = Math.max(1, (/* @__PURE__ */ new Date()).getTime() - (dragStartTime?.getTime() ?? 0));
const swipeAmount = swipeDirection() === "x" ? swipeAmountX : swipeAmountY;
const velocity = Math.abs(swipeAmount) / timeTaken;
if (Math.abs(swipeAmount) >= SWIPE_THRESHOLD || velocity > 0.11) {
setOffsetBeforeRemove(offset());
props.toast.onDismiss?.(props.toast);
if (swipeDirection() === "x") setSwipeOutDirection(swipeAmountX > 0 ? "right" : "left");
else setSwipeOutDirection(swipeAmountY > 0 ? "down" : "up");
deleteToast();

@@ -417,9 +629,14 @@ setSwipeOut(true);

}
toastRef?.style.setProperty("--swipe-amount", "0px");
toastRef?.style.setProperty("--swipe-amount-x", "0px");
toastRef?.style.setProperty("--swipe-amount-y", "0px");
setIsSwiped(false);
setSwiping(false);
setSwipeDirection(null);
};
_el$2.$$pointerdown = (event) => {
if (disabled()) return;
if (event.button === 2) return;
if (disabled() || !dismissible()) return;
dragStartTime = /* @__PURE__ */ new Date();
setOffsetBeforeRemove(offset());
event.target.setPointerCapture(event.pointerId);
event.currentTarget.setPointerCapture(event.pointerId);
if (event.target.tagName === "BUTTON") return;

@@ -432,2 +649,7 @@ setSwiping(true);

};
_el$2.addEventListener("dragend", () => {
setSwiping(false);
setSwipeDirection(null);
setPointerStartRef(null);
});
var _ref$ = toastRef;

@@ -437,74 +659,81 @@ typeof _ref$ === "function" ? use(_ref$, _el$2) : toastRef = _el$2;

get when() {
return props.closeButton && !props.toast.jsx;
return memo(() => !!(closeButton() && !props.toast.jsx))() && toastType() !== "loading";
},
get children() {
var _el$3 = _tmpl$22();
addEventListener(_el$3, "click", disabled() ? void 0 : () => {
_el$3.$$click = () => {
if (disabled() || !dismissible()) return;
deleteToast();
props.toast.onDismiss?.(props.toast);
}, true);
};
insert(_el$3, () => props.icons?.close ?? createComponent(CloseIcon, {}));
effect((_p$) => {
var _v$ = disabled(), _v$2 = _cn(props.classes?.closeButton, props.toast?.classes?.closeButton);
_v$ !== _p$.e && setAttribute(_el$3, "data-disabled", _p$.e = _v$);
_v$2 !== _p$.t && className(_el$3, _p$.t = _v$2);
var _v$3 = props.closeButtonAriaLabel ?? "Close toast", _v$4 = disabled(), _v$5 = cn(classNames()?.closeButton, toastClassNames()?.closeButton);
_v$3 !== _p$.e && setAttribute(_el$3, "aria-label", _p$.e = _v$3);
_v$4 !== _p$.t && setAttribute(_el$3, "data-disabled", _p$.t = _v$4);
_v$5 !== _p$.a && className(_el$3, _p$.a = _v$5);
return _p$;
}, {
e: void 0,
t: void 0
t: void 0,
a: void 0
});
return _el$3;
}
}), _el$5);
insert(_el$2, createComponent(Show, {
get when() {
return memo(() => !!((toastType() || props.toast.icon || props.toast.promise) && props.toast.icon !== null))() && (props.icons?.[toastType()] !== null || props.toast.icon);
},
get children() {
var _el$4 = _tmpl$32();
insert(_el$4, (() => {
var _c$ = memo(() => !!(props.toast.promise || props.toast.type === "loading" && !props.toast.icon));
return () => _c$() ? props.toast.icon || getLoadingIcon() : null;
})(), null);
insert(_el$4, (() => {
var _c$2 = memo(() => props.toast.type !== "loading");
return () => _c$2() ? icon() : null;
})(), null);
effect(() => className(_el$4, cn(classNames()?.icon, toastClassNames()?.icon)));
return _el$4;
}
}), _el$5);
insert(_el$6, (() => {
var _c$3 = memo(() => !!props.toast.jsx);
return () => _c$3() ? props.toast.jsx : resolveContent(props.toast.title);
})());
insert(_el$5, createComponent(Show, {
get when() {
return props.toast.description;
},
get children() {
var _el$7 = _tmpl$42();
insert(_el$7, () => resolveContent(props.toast.description));
effect(() => className(_el$7, cn(descriptionClassName(), toastDescriptionClassName(), classNames()?.description, toastClassNames()?.description)));
return _el$7;
}
}), null);
insert(_el$2, createComponent(Show, {
get when() {
return props.toast.jsx || props.toast.title instanceof Element;
return props.toast.cancel;
},
get fallback() {
return [createComponent(Show, {
get when() {
return toastType() || props.toast.icon || props.toast.promise;
},
get children() {
var _el$4 = _tmpl$42();
insert(_el$4, (() => {
var _c$ = memo(() => !!(props.toast.promise || props.toast.type === "loading" && !props.toast.icon));
return () => _c$() ? props.toast.icon || getLoadingIcon() : null;
})(), null);
insert(_el$4, (() => {
var _c$2 = memo(() => props.toast.type !== "loading");
return () => _c$2() ? props.toast.icon || props.icons?.[toastType()] || getAsset(toastType())() : null;
})(), null);
return _el$4;
}
}), (() => {
var _el$5 = _tmpl$62(), _el$6 = _el$5.firstChild;
insert(_el$6, () => props.toast.title);
insert(_el$5, createComponent(Show, {
get when() {
return props.toast.description;
},
get children() {
var _el$7 = _tmpl$52();
insert(_el$7, () => props.toast.description);
effect(() => className(_el$7, _cn(props.descriptionClass, toastDescriptionClassname(), props.classes?.description, props.toast?.classes?.description)));
return _el$7;
}
}), null);
effect(() => className(_el$6, _cn(props.classes?.title, props.toast?.classes?.title)));
return _el$5;
})(), createComponent(Show, {
get when() {
return props.toast.cancel;
},
get children() {
var _el$8 = _tmpl$72();
_el$8.$$click = () => {
children: (cancel) => createComponent(Show, {
get when() {
return !isAction(cancel());
},
get fallback() {
return (() => {
var _el$8 = _tmpl$62();
_el$8.$$click = (event) => {
const currentCancel = cancel();
if (!dismissible()) return;
currentCancel.onClick?.(event);
deleteToast();
if (props.toast.cancel?.onClick) props.toast.cancel.onClick();
};
insert(_el$8, () => props.toast.cancel.label);
insert(_el$8, () => cancel().label);
effect((_p$) => {
var _v$20 = props.toast.cancelButtonStyle || props.cancelButtonStyle, _v$21 = _cn(props.classes?.cancelButton, props.toast?.classes?.cancelButton);
_p$.e = style(_el$8, _v$20, _p$.e);
_v$21 !== _p$.t && className(_el$8, _p$.t = _v$21);
var _v$27 = props.toast.cancelButtonStyle ?? props.cancelButtonStyle, _v$28 = cn(classNames()?.cancelButton, toastClassNames()?.cancelButton);
_p$.e = style(_el$8, _v$27, _p$.e);
_v$28 !== _p$.t && className(_el$8, _p$.t = _v$28);
return _p$;

@@ -516,19 +745,31 @@ }, {

return _el$8;
}
}), createComponent(Show, {
get when() {
return props.toast.action;
},
get children() {
var _el$9 = _tmpl$8();
})();
},
get children() {
return cancel();
}
})
}), null);
insert(_el$2, createComponent(Show, {
get when() {
return props.toast.action;
},
children: (action) => createComponent(Show, {
get when() {
return !isAction(action());
},
get fallback() {
return (() => {
var _el$9 = _tmpl$72();
_el$9.$$click = (event) => {
props.toast.action?.onClick(event);
const currentAction = action();
currentAction.onClick?.(event);
if (event.defaultPrevented) return;
deleteToast();
};
insert(_el$9, () => props.toast.action.label);
insert(_el$9, () => action().label);
effect((_p$) => {
var _v$22 = props.toast.actionButtonStyle || props.actionButtonStyle, _v$23 = _cn(props.classes?.actionButton, props.toast?.classes?.actionButton);
_p$.e = style(_el$9, _v$22, _p$.e);
_v$23 !== _p$.t && className(_el$9, _p$.t = _v$23);
var _v$29 = props.toast.actionButtonStyle ?? props.actionButtonStyle, _v$30 = cn(classNames()?.actionButton, toastClassNames()?.actionButton);
_p$.e = style(_el$9, _v$29, _p$.e);
_v$30 !== _p$.t && className(_el$9, _p$.t = _v$30);
return _p$;

@@ -540,11 +781,11 @@ }, {

return _el$9;
}
})];
},
get children() {
return props.toast.jsx || props.toast.title;
}
})();
},
get children() {
return action();
}
})
}), null);
effect((_p$) => {
var _v$3 = props.toast.important ? "assertive" : "polite", _v$4 = _cn(props.class, toastClassname(), props.classes?.toast, props.toast?.classes?.toast, props.classes?.default, props.classes?.[toastType()], props.toast?.classes?.[toastType()]), _v$5 = !(props.toast.jsx || props.toast.unstyled || props.unstyled), _v$6 = mounted(), _v$7 = Boolean(props.toast.promise), _v$8 = removed(), _v$9 = isVisible(), _v$10 = coords()[0], _v$11 = coords()[1], _v$12 = props.index, _v$13 = isFront(), _v$14 = swiping(), _v$15 = toastType(), _v$16 = invert(), _v$17 = swipeOut(), _v$18 = Boolean(props.expanded || props.expandByDefault && mounted()), _v$19 = {
var _v$6 = cn(className$1(), toastClassName(), classNames()?.toast, toastClassNames()?.toast, classNames()?.default, classNames()?.[toastType()], toastClassNames()?.[toastType()]), _v$7 = props.toast.richColors ?? props.defaultRichColors, _v$8 = !(props.toast.jsx || props.toast.unstyled || props.unstyled), _v$9 = mounted(), _v$0 = Boolean(props.toast.promise), _v$1 = isSwiped(), _v$10 = removed(), _v$11 = isVisible(), _v$12 = y(), _v$13 = x(), _v$14 = props.index, _v$15 = isFront(), _v$16 = swiping(), _v$17 = dismissible(), _v$18 = toastType(), _v$19 = invert(), _v$20 = swipeOut(), _v$21 = swipeOutDirection(), _v$22 = Boolean(props.expanded || props.expandByDefault && mounted()), _v$23 = props.toast.testId, _v$24 = {
"--index": props.index,

@@ -557,20 +798,26 @@ "--toasts-before": props.index,

...props.toast.style
};
_v$3 !== _p$.e && setAttribute(_el$2, "aria-live", _p$.e = _v$3);
_v$4 !== _p$.t && className(_el$2, _p$.t = _v$4);
_v$5 !== _p$.a && setAttribute(_el$2, "data-styled", _p$.a = _v$5);
_v$6 !== _p$.o && setAttribute(_el$2, "data-mounted", _p$.o = _v$6);
_v$7 !== _p$.i && setAttribute(_el$2, "data-promise", _p$.i = _v$7);
_v$8 !== _p$.n && setAttribute(_el$2, "data-removed", _p$.n = _v$8);
_v$9 !== _p$.s && setAttribute(_el$2, "data-visible", _p$.s = _v$9);
_v$10 !== _p$.h && setAttribute(_el$2, "data-y-position", _p$.h = _v$10);
_v$11 !== _p$.r && setAttribute(_el$2, "data-x-position", _p$.r = _v$11);
_v$12 !== _p$.d && setAttribute(_el$2, "data-index", _p$.d = _v$12);
_v$13 !== _p$.l && setAttribute(_el$2, "data-front", _p$.l = _v$13);
_v$14 !== _p$.u && setAttribute(_el$2, "data-swiping", _p$.u = _v$14);
_v$15 !== _p$.c && setAttribute(_el$2, "data-type", _p$.c = _v$15);
_v$16 !== _p$.w && setAttribute(_el$2, "data-invert", _p$.w = _v$16);
_v$17 !== _p$.m && setAttribute(_el$2, "data-swipe-out", _p$.m = _v$17);
_v$18 !== _p$.f && setAttribute(_el$2, "data-expanded", _p$.f = _v$18);
_p$.y = style(_el$2, _v$19, _p$.y);
}, _v$25 = cn(classNames()?.content, toastClassNames()?.content), _v$26 = cn(classNames()?.title, toastClassNames()?.title);
_v$6 !== _p$.e && className(_el$2, _p$.e = _v$6);
_v$7 !== _p$.t && setAttribute(_el$2, "data-rich-colors", _p$.t = _v$7);
_v$8 !== _p$.a && setAttribute(_el$2, "data-styled", _p$.a = _v$8);
_v$9 !== _p$.o && setAttribute(_el$2, "data-mounted", _p$.o = _v$9);
_v$0 !== _p$.i && setAttribute(_el$2, "data-promise", _p$.i = _v$0);
_v$1 !== _p$.n && setAttribute(_el$2, "data-swiped", _p$.n = _v$1);
_v$10 !== _p$.s && setAttribute(_el$2, "data-removed", _p$.s = _v$10);
_v$11 !== _p$.h && setAttribute(_el$2, "data-visible", _p$.h = _v$11);
_v$12 !== _p$.r && setAttribute(_el$2, "data-y-position", _p$.r = _v$12);
_v$13 !== _p$.d && setAttribute(_el$2, "data-x-position", _p$.d = _v$13);
_v$14 !== _p$.l && setAttribute(_el$2, "data-index", _p$.l = _v$14);
_v$15 !== _p$.u && setAttribute(_el$2, "data-front", _p$.u = _v$15);
_v$16 !== _p$.c && setAttribute(_el$2, "data-swiping", _p$.c = _v$16);
_v$17 !== _p$.w && setAttribute(_el$2, "data-dismissible", _p$.w = _v$17);
_v$18 !== _p$.m && setAttribute(_el$2, "data-type", _p$.m = _v$18);
_v$19 !== _p$.f && setAttribute(_el$2, "data-invert", _p$.f = _v$19);
_v$20 !== _p$.y && setAttribute(_el$2, "data-swipe-out", _p$.y = _v$20);
_v$21 !== _p$.g && setAttribute(_el$2, "data-swipe-direction", _p$.g = _v$21);
_v$22 !== _p$.p && setAttribute(_el$2, "data-expanded", _p$.p = _v$22);
_v$23 !== _p$.b && setAttribute(_el$2, "data-testid", _p$.b = _v$23);
_p$.T = style(_el$2, _v$24, _p$.T);
_v$25 !== _p$.A && className(_el$5, _p$.A = _v$25);
_v$26 !== _p$.O && className(_el$6, _p$.O = _v$26);
return _p$;

@@ -594,15 +841,14 @@ }, {

f: void 0,
y: void 0
y: void 0,
g: void 0,
p: void 0,
b: void 0,
T: void 0,
A: void 0,
O: void 0
});
return _el$2;
})();
};
function getDocumentDirection() {
if (typeof window === "undefined") return "ltr";
if (typeof document === "undefined") return "ltr";
const dirAttribute = document.documentElement.getAttribute("dir");
if (dirAttribute === "auto" || !dirAttribute) return window.getComputedStyle(document.documentElement).direction;
return dirAttribute;
}
var Toaster = (props) => {
function Toaster(props) {
const propsWithDefaults = mergeProps({

@@ -612,46 +858,66 @@ position: "bottom-right",

theme: "light",
gap: GAP,
visibleToasts: VISIBLE_TOASTS_AMOUNT,
dir: getDocumentDirection()
dir: getDocumentDirection(),
containerAriaLabel: "Notifications"
}, props);
const initialTheme = createToastTheme(propsWithDefaults.theme);
const [toastsStore, setToastsStore] = createStore({
toasts: []
});
const possiblePositions = () => {
return Array.from(new Set([propsWithDefaults.position].concat(toastsStore.toasts.filter((toast2) => toast2.position).map((toast2) => toast2.position))));
};
const filteredToasts = createMemo(() => {
const toasts = toastsStore.toasts;
if (propsWithDefaults.id) return toasts.filter((toast2) => toast2.toasterId === propsWithDefaults.id);
return toasts.filter((toast2) => !toast2.toasterId);
});
const possiblePositions = createMemo(() => {
return Array.from(/* @__PURE__ */ new Set([propsWithDefaults.position, ...filteredToasts().filter((toast2) => toast2.position).map((toast2) => toast2.position)]));
});
const [heights, setHeights] = createSignal([]);
const [expanded, setExpanded] = createSignal(false);
const [interacting, setInteracting] = createSignal(false);
const [actualTheme, setActualTheme] = createSignal(initialTheme);
const [lastFocusedElementRef, setLastFocusedElementRef] = createSignal(null);
const [isFocusWithinRef, setIsFocusWithinRef] = createSignal(false);
let listRef;
const hotkeyLabel = () => propsWithDefaults.hotkey.join("+").replace(/Key/g, "").replace(/Digit/g, "");
const [lastFocusedElementRef, setLastFocusedElementRef] = createSignal(null);
const [isFocusedWithinRef, setIsFocusedWithinRef] = createSignal(false);
const [actualTheme, setActualTheme] = createSignal(propsWithDefaults.theme !== "system" ? propsWithDefaults.theme : typeof window !== "undefined" ? window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : "light");
const removeToast = (toast2) => setToastsStore("toasts", (toasts) => toasts.filter(({
id
}) => id !== toast2.id));
const className$1 = () => mergeClassName(propsWithDefaults.className, propsWithDefaults.class);
const toastOptions = () => propsWithDefaults.toastOptions;
const toastClassNames = () => mergeClassNames(toastOptions()?.classNames, toastOptions()?.classes);
const toastDescriptionClassName = () => mergeDescriptionClassName(toastOptions()?.descriptionClassName, toastOptions()?.descriptionClass);
const toastClassName = () => mergeClassName(toastOptions()?.className, toastOptions()?.class);
const removeToast = (toastToRemove) => {
setToastsStore("toasts", (toasts) => {
if (!toasts.find((toast2) => toast2.id === toastToRemove.id)?.delete) ToastState.dismiss(toastToRemove.id);
return toasts.filter(({
id
}) => id !== toastToRemove.id);
});
};
onMount(() => {
const unsub = ToastState.subscribe((toast2) => {
if (toast2.dismiss) {
setToastsStore("toasts", produce((_toasts) => {
_toasts.forEach((t) => {
if (t.id === toast2.id) t.delete = true;
});
}));
const unsubscribe = ToastState.subscribe((toastItem) => {
if (toastItem.dismiss) {
requestAnimationFrame(() => {
setToastsStore("toasts", produce((toasts) => {
toasts.forEach((toast2) => {
if (toast2.id === toastItem.id) toast2.delete = true;
});
}));
});
return;
}
const changedIndex = toastsStore.toasts.findIndex((t) => t.id === toast2.id);
if (changedIndex !== -1) {
setToastsStore("toasts", [changedIndex], reconcile(toast2));
const nextToast = toastItem;
const indexOfExistingToast = toastsStore.toasts.findIndex((t) => t.id === nextToast.id);
if (indexOfExistingToast !== -1) {
setToastsStore("toasts", indexOfExistingToast, reconcile(nextToast));
return;
}
setToastsStore("toasts", produce((_toasts) => {
_toasts.unshift(toast2);
setToastsStore("toasts", produce((toasts) => {
toasts.unshift(nextToast);
}));
});
onCleanup(() => {
unsub();
});
onCleanup(unsubscribe);
});
createEffect(on(() => propsWithDefaults.theme, (theme) => {
createEffect(() => {
const theme = propsWithDefaults.theme;
if (theme !== "system") {

@@ -662,15 +928,23 @@ setActualTheme(theme);

if (typeof window === "undefined") return;
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", ({
const darkMediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
const updateTheme = ({
matches
}) => {
if (matches) setActualTheme("dark");
else setActualTheme("light");
});
}));
setActualTheme(matches ? "dark" : "light");
};
updateTheme(darkMediaQuery);
try {
darkMediaQuery.addEventListener("change", updateTheme);
onCleanup(() => darkMediaQuery.removeEventListener("change", updateTheme));
} catch {
darkMediaQuery.addListener(updateTheme);
onCleanup(() => darkMediaQuery.removeListener(updateTheme));
}
});
createEffect(() => {
if (toastsStore.toasts.length <= 1) setExpanded(false);
if (filteredToasts().length <= 1) setExpanded(false);
});
onMount(() => {
const handleKeyDown = (event) => {
const isHotkeyPressed = propsWithDefaults.hotkey.every((key) => event[key] || event.code === key);
const isHotkeyPressed = propsWithDefaults.hotkey.length > 0 && propsWithDefaults.hotkey.every((key) => event[key] || event.code === key);
if (isHotkeyPressed) {

@@ -683,51 +957,52 @@ setExpanded(true);

document.addEventListener("keydown", handleKeyDown);
onCleanup(() => {
document.removeEventListener("keydown", handleKeyDown);
});
onCleanup(() => document.removeEventListener("keydown", handleKeyDown));
});
createEffect(on(() => listRef, (ref) => {
if (ref) {
onCleanup(() => {
if (lastFocusedElementRef()) {
lastFocusedElementRef()?.focus({
preventScroll: true
});
setLastFocusedElementRef(null);
setIsFocusedWithinRef(false);
}
onCleanup(() => {
if (lastFocusedElementRef()) {
lastFocusedElementRef()?.focus({
preventScroll: true
});
setLastFocusedElementRef(null);
setIsFocusWithinRef(false);
}
}));
return createComponent(Show, {
get when() {
return toastsStore.toasts.length > 0;
},
get children() {
var _el$10 = _tmpl$9();
insert(_el$10, createComponent(For, {
get each() {
return possiblePositions();
},
children: (position, index) => {
const [y, x] = position.split("-");
return (() => {
var _el$11 = _tmpl$10();
_el$11.$$pointerup = () => setInteracting(false);
_el$11.$$pointerdown = () => {
});
return (() => {
var _el$0 = _tmpl$82();
insert(_el$0, createComponent(For, {
get each() {
return possiblePositions();
},
children: (position, index) => {
const [y, x] = position.split("-");
const toastsByPosition = createMemo(() => filteredToasts().filter((toast2) => !toast2.position && index() === 0 || toast2.position === position));
const heightsByPosition = createMemo(() => heights().filter((height) => index() === 0 && !height.position || height.position === position));
return createComponent(Show, {
get when() {
return filteredToasts().length > 0;
},
get children() {
var _el$1 = _tmpl$9();
_el$1.$$pointerup = () => setInteracting(false);
_el$1.$$pointerdown = (event) => {
const isNotDismissible = event.target instanceof HTMLElement && event.target.dataset.dismissible === "false";
if (isNotDismissible) return;
setInteracting(true);
};
_el$11.addEventListener("mouseleave", () => {
_el$1.addEventListener("dragend", () => setExpanded(false));
_el$1.addEventListener("mouseleave", () => {
if (!interacting()) setExpanded(false);
});
_el$11.$$mousemove = () => setExpanded(true);
_el$11.addEventListener("mouseenter", () => setExpanded(true));
_el$11.addEventListener("focus", (event) => {
if (!isFocusedWithinRef()) {
setIsFocusedWithinRef(true);
_el$1.$$mousemove = () => setExpanded(true);
_el$1.addEventListener("mouseenter", () => setExpanded(true));
_el$1.addEventListener("focus", (event) => {
const isNotDismissible = event.target instanceof HTMLElement && event.target.dataset.dismissible === "false";
if (isNotDismissible) return;
if (!isFocusWithinRef()) {
setIsFocusWithinRef(true);
setLastFocusedElementRef(event.relatedTarget);
}
});
_el$11.addEventListener("blur", (event) => {
if (isFocusedWithinRef() && !event.currentTarget.contains(event.relatedTarget)) {
setIsFocusedWithinRef(false);
_el$1.addEventListener("blur", (event) => {
if (isFocusWithinRef() && !event.currentTarget.contains(event.relatedTarget)) {
setIsFocusWithinRef(false);
if (lastFocusedElementRef()) {

@@ -742,35 +1017,29 @@ lastFocusedElementRef()?.focus({

var _ref$2 = listRef;
typeof _ref$2 === "function" ? use(_ref$2, _el$11) : listRef = _el$11;
setAttribute(_el$11, "data-y-position", y);
setAttribute(_el$11, "data-x-position", x);
insert(_el$11, createComponent(For, {
typeof _ref$2 === "function" ? use(_ref$2, _el$1) : listRef = _el$1;
setAttribute(_el$1, "data-y-position", y);
setAttribute(_el$1, "data-x-position", x);
insert(_el$1, createComponent(For, {
get each() {
return toastsStore.toasts.filter((toast2) => !toast2.position && index() === 0 || toast2.position === position);
return toastsByPosition();
},
children: (toast2, index2) => createComponent(Toast, {
get index() {
return index2();
},
children: (toastItem, toastIndex) => createComponent(Toast, {
get icons() {
return propsWithDefaults.icons;
},
toast: toast2,
get index() {
return toastIndex();
},
toast: toastItem,
get defaultRichColors() {
return propsWithDefaults.richColors;
},
get duration() {
return propsWithDefaults.toastOptions?.duration ?? props.duration;
return toastOptions()?.duration ?? propsWithDefaults.duration;
},
get ["class"]() {
return propsWithDefaults.toastOptions?.class;
return toastClassName();
},
get classes() {
return propsWithDefaults.toastOptions?.classes;
get descriptionClassName() {
return toastDescriptionClassName();
},
get cancelButtonStyle() {
return propsWithDefaults.toastOptions?.cancelButtonStyle;
},
get actionButtonStyle() {
return propsWithDefaults.toastOptions?.actionButtonStyle;
},
get descriptionClass() {
return propsWithDefaults.toastOptions?.descriptionClass;
},
get invert() {

@@ -783,3 +1052,3 @@ return Boolean(propsWithDefaults.invert);

get closeButton() {
return Boolean(propsWithDefaults.closeButton);
return toastOptions()?.closeButton ?? propsWithDefaults.closeButton ?? false;
},

@@ -789,17 +1058,27 @@ get interacting() {

},
get position() {
return propsWithDefaults.position;
},
position,
get style() {
return propsWithDefaults.toastOptions?.style;
return toastOptions()?.style;
},
get unstyled() {
return propsWithDefaults.toastOptions?.unstyled;
return toastOptions()?.unstyled;
},
get classNames() {
return toastClassNames();
},
get cancelButtonStyle() {
return toastOptions()?.cancelButtonStyle;
},
get actionButtonStyle() {
return toastOptions()?.actionButtonStyle;
},
get closeButtonAriaLabel() {
return toastOptions()?.closeButtonAriaLabel;
},
removeToast,
get toasts() {
return toastsStore.toasts;
return toastsByPosition();
},
get heights() {
return heights();
return heightsByPosition();
},

@@ -816,2 +1095,5 @@ setHeights,

},
get swipeDirections() {
return propsWithDefaults.swipeDirections;
},
get pauseWhenPageIsHidden() {

@@ -823,14 +1105,12 @@ return propsWithDefaults.pauseWhenPageIsHidden;

effect((_p$) => {
var _v$24 = propsWithDefaults.dir === "auto" ? getDocumentDirection() : propsWithDefaults.dir, _v$25 = propsWithDefaults.class, _v$26 = actualTheme(), _v$27 = propsWithDefaults.richColors, _v$28 = {
"--front-toast-height": `${heights()[0]?.height}px`,
"--offset": typeof propsWithDefaults.offset === "number" ? `${propsWithDefaults.offset}px` : propsWithDefaults.offset || VIEWPORT_OFFSET,
"--width": `${TOAST_WIDTH}px`,
"--gap": `${GAP}px`,
...propsWithDefaults.style
var _v$31 = propsWithDefaults.dir === "auto" ? getDocumentDirection() : propsWithDefaults.dir, _v$32 = className$1(), _v$33 = actualTheme(), _v$34 = {
"--front-toast-height": `${heightsByPosition()[0]?.height ?? 0}px`,
"--gap": `${propsWithDefaults.gap}px`,
...propsWithDefaults.style,
...assignOffset(propsWithDefaults.offset, propsWithDefaults.mobileOffset)
};
_v$24 !== _p$.e && setAttribute(_el$11, "dir", _p$.e = _v$24);
_v$25 !== _p$.t && className(_el$11, _p$.t = _v$25);
_v$26 !== _p$.a && setAttribute(_el$11, "data-theme", _p$.a = _v$26);
_v$27 !== _p$.o && setAttribute(_el$11, "data-rich-colors", _p$.o = _v$27);
_p$.i = style(_el$11, _v$28, _p$.i);
_v$31 !== _p$.e && setAttribute(_el$1, "dir", _p$.e = _v$31);
_v$32 !== _p$.t && className(_el$1, _p$.t = _v$32);
_v$33 !== _p$.a && setAttribute(_el$1, "data-sonner-theme", _p$.a = _v$33);
_p$.o = style(_el$1, _v$34, _p$.o);
return _p$;

@@ -841,14 +1121,13 @@ }, {

a: void 0,
o: void 0,
i: void 0
o: void 0
});
return _el$11;
})();
}
}));
effect(() => setAttribute(_el$10, "aria-label", `Notifications ${hotkeyLabel()}`));
return _el$10;
}
});
};
return _el$1;
}
});
}
}));
effect(() => setAttribute(_el$0, "aria-label", propsWithDefaults.customAriaLabel ?? `${propsWithDefaults.containerAriaLabel} ${hotkeyLabel()}`));
return _el$0;
})();
}
delegateEvents(["pointerdown", "pointerup", "pointermove", "click", "mousemove"]);

@@ -863,2 +1142,2 @@ /*!

export { Toaster, toast };
export { Toaster, toast, useSonner };

@@ -24,6 +24,6 @@ // #style-inject:#style-inject

// src/styles.css
styleInject(':where(html[dir=ltr]),\n:where([data-sonner-toaster][dir=ltr]) {\n --toast-icon-margin-start: -3px;\n --toast-icon-margin-end: 4px;\n --toast-svg-margin-start: -1px;\n --toast-svg-margin-end: 0px;\n --toast-button-margin-start: auto;\n --toast-button-margin-end: 0;\n --toast-close-button-start: 0;\n --toast-close-button-end: unset;\n --toast-close-button-transform: translate(-35%, -35%);\n}\n:where(html[dir=rtl]),\n:where([data-sonner-toaster][dir=rtl]) {\n --toast-icon-margin-start: 4px;\n --toast-icon-margin-end: -3px;\n --toast-svg-margin-start: 0px;\n --toast-svg-margin-end: -1px;\n --toast-button-margin-start: 0;\n --toast-button-margin-end: auto;\n --toast-close-button-start: unset;\n --toast-close-button-end: 0;\n --toast-close-button-transform: translate(35%, -35%);\n}\n:where([data-sonner-toaster]) {\n position: fixed;\n width: var(--width);\n font-family:\n ui-sans-serif,\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n Segoe UI,\n Roboto,\n Helvetica Neue,\n Arial,\n Noto Sans,\n sans-serif,\n Apple Color Emoji,\n Segoe UI Emoji,\n Segoe UI Symbol,\n Noto Color Emoji;\n --gray1: hsl(0, 0%, 99%);\n --gray2: hsl(0, 0%, 97.3%);\n --gray3: hsl(0, 0%, 95.1%);\n --gray4: hsl(0, 0%, 93%);\n --gray5: hsl(0, 0%, 90.9%);\n --gray6: hsl(0, 0%, 88.7%);\n --gray7: hsl(0, 0%, 85.8%);\n --gray8: hsl(0, 0%, 78%);\n --gray9: hsl(0, 0%, 56.1%);\n --gray10: hsl(0, 0%, 52.3%);\n --gray11: hsl(0, 0%, 43.5%);\n --gray12: hsl(0, 0%, 9%);\n --border-radius: 8px;\n box-sizing: border-box;\n padding: 0;\n margin: 0;\n list-style: none;\n outline: none;\n z-index: 999999999;\n}\n:where([data-sonner-toaster][data-x-position=right]) {\n right: max(var(--offset), env(safe-area-inset-right));\n}\n:where([data-sonner-toaster][data-x-position=left]) {\n left: max(var(--offset), env(safe-area-inset-left));\n}\n:where([data-sonner-toaster][data-x-position=center]) {\n left: 50%;\n transform: translateX(-50%);\n}\n:where([data-sonner-toaster][data-y-position=top]) {\n top: max(var(--offset), env(safe-area-inset-top));\n}\n:where([data-sonner-toaster][data-y-position=bottom]) {\n bottom: max(var(--offset), env(safe-area-inset-bottom));\n}\n:where([data-sonner-toast]) {\n --y: translateY(100%);\n --lift-amount: calc(var(--lift) * var(--gap));\n z-index: var(--z-index);\n position: absolute;\n opacity: 0;\n transform: var(--y);\n filter: blur(0);\n touch-action: none;\n transition:\n transform 400ms,\n opacity 400ms,\n height 400ms,\n box-shadow 200ms;\n box-sizing: border-box;\n outline: none;\n overflow-wrap: anywhere;\n}\n:where([data-sonner-toast][data-styled=true]) {\n padding: 16px;\n background: var(--normal-bg);\n border: 1px solid var(--normal-border);\n color: var(--normal-text);\n border-radius: var(--border-radius);\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1);\n width: var(--width);\n font-size: 13px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n:where([data-sonner-toast]:focus-visible) {\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1), 0 0 0 2px rgba(0, 0, 0, 0.2);\n}\n:where([data-sonner-toast][data-y-position=top]) {\n top: 0;\n --y: translateY(-100%);\n --lift: 1;\n --lift-amount: calc(1 * var(--gap));\n}\n:where([data-sonner-toast][data-y-position=bottom]) {\n bottom: 0;\n --y: translateY(100%);\n --lift: -1;\n --lift-amount: calc(var(--lift) * var(--gap));\n}\n:where([data-sonner-toast]) :where([data-description]) {\n font-weight: 400;\n line-height: 1.4;\n color: inherit;\n}\n:where([data-sonner-toast]) :where([data-title]) {\n font-weight: 500;\n line-height: 1.5;\n color: inherit;\n}\n:where([data-sonner-toast]) :where([data-icon]) {\n display: flex;\n height: 16px;\n width: 16px;\n position: relative;\n justify-content: flex-start;\n align-items: center;\n flex-shrink: 0;\n margin-left: var(--toast-icon-margin-start);\n margin-right: var(--toast-icon-margin-end);\n}\n:where([data-sonner-toast][data-promise=true]) :where([data-icon]) > svg {\n opacity: 0;\n transform: scale(0.8);\n transform-origin: center;\n animation: sonner-fade-in 300ms ease forwards;\n}\n:where([data-sonner-toast]) :where([data-icon]) > * {\n flex-shrink: 0;\n}\n:where([data-sonner-toast]) :where([data-icon]) svg {\n margin-left: var(--toast-svg-margin-start);\n margin-right: var(--toast-svg-margin-end);\n}\n:where([data-sonner-toast]) :where([data-content]) {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n[data-sonner-toast][data-styled=true] [data-button] {\n border-radius: 4px;\n padding-left: 8px;\n padding-right: 8px;\n height: 24px;\n font-size: 12px;\n color: var(--normal-bg);\n background: var(--normal-text);\n margin-left: var(--toast-button-margin-start);\n margin-right: var(--toast-button-margin-end);\n border: none;\n cursor: pointer;\n outline: none;\n display: flex;\n align-items: center;\n flex-shrink: 0;\n transition: opacity 400ms, box-shadow 200ms;\n}\n:where([data-sonner-toast]) :where([data-button]):focus-visible {\n box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.4);\n}\n:where([data-sonner-toast]) :where([data-button]):first-of-type {\n margin-left: var(--toast-button-margin-start);\n margin-right: var(--toast-button-margin-end);\n}\n:where([data-sonner-toast]) :where([data-cancel]) {\n color: var(--normal-text);\n background: rgba(0, 0, 0, 0.08);\n}\n:where([data-sonner-toast][data-theme=dark]) :where([data-cancel]) {\n background: rgba(255, 255, 255, 0.3);\n}\n:where([data-sonner-toast]) :where([data-close-button]) {\n position: absolute;\n left: var(--toast-close-button-start);\n right: var(--toast-close-button-end);\n top: 0;\n height: 20px;\n width: 20px;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 0;\n background: var(--gray1);\n color: var(--gray12);\n border: 1px solid var(--gray4);\n transform: var(--toast-close-button-transform);\n border-radius: 50%;\n cursor: pointer;\n z-index: 1;\n transition:\n opacity 100ms,\n background 200ms,\n border-color 200ms;\n}\n:where([data-sonner-toast]) :where([data-close-button]):focus-visible {\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1), 0 0 0 2px rgba(0, 0, 0, 0.2);\n}\n:where([data-sonner-toast]) :where([data-disabled=true]) {\n cursor: not-allowed;\n}\n:where([data-sonner-toast]):hover :where([data-close-button]):hover {\n background: var(--gray2);\n border-color: var(--gray5);\n}\n:where([data-sonner-toast][data-swiping=true])::before {\n content: "";\n position: absolute;\n left: 0;\n right: 0;\n height: 100%;\n z-index: -1;\n}\n:where([data-sonner-toast][data-y-position=top][data-swiping=true])::before {\n bottom: 50%;\n transform: scaleY(3) translateY(50%);\n}\n:where([data-sonner-toast][data-y-position=bottom][data-swiping=true])::before {\n top: 50%;\n transform: scaleY(3) translateY(-50%);\n}\n:where([data-sonner-toast][data-swiping=false][data-removed=true])::before {\n content: "";\n position: absolute;\n inset: 0;\n transform: scaleY(2);\n}\n:where([data-sonner-toast])::after {\n content: "";\n position: absolute;\n left: 0;\n height: calc(var(--gap) + 1px);\n bottom: 100%;\n width: 100%;\n}\n:where([data-sonner-toast][data-mounted=true]) {\n --y: translateY(0);\n opacity: 1;\n}\n:where([data-sonner-toast][data-expanded=false][data-front=false]) {\n --scale: var(--toasts-before) * 0.05 + 1;\n --y: translateY(calc(var(--lift-amount) * var(--toasts-before))) scale(calc(-1 * var(--scale)));\n height: var(--front-toast-height);\n}\n:where([data-sonner-toast]) > * {\n transition: opacity 400ms;\n}\n:where([data-sonner-toast][data-expanded=false][data-front=false][data-styled=true]) > * {\n opacity: 0;\n}\n:where([data-sonner-toast][data-visible=false]) {\n opacity: 0;\n pointer-events: none;\n}\n:where([data-sonner-toast][data-mounted=true][data-expanded=true]) {\n --y: translateY(calc(var(--lift) * var(--offset)));\n height: var(--initial-height);\n}\n:where([data-sonner-toast][data-removed=true][data-front=true][data-swipe-out=false]) {\n --y: translateY(calc(var(--lift) * -100%));\n opacity: 0;\n}\n:where([data-sonner-toast][data-removed=true][data-front=false][data-swipe-out=false][data-expanded=true]) {\n --y: translateY(calc(var(--lift) * var(--offset) + var(--lift) * -100%));\n opacity: 0;\n}\n:where([data-sonner-toast][data-removed=true][data-front=false][data-swipe-out=false][data-expanded=false]) {\n --y: translateY(40%);\n opacity: 0;\n transition: transform 500ms, opacity 200ms;\n}\n:where([data-sonner-toast][data-removed=true][data-front=false])::before {\n height: calc(var(--initial-height) + 20%);\n}\n[data-sonner-toast][data-swiping=true] {\n transform: var(--y) translateY(var(--swipe-amount, 0px));\n transition: none;\n}\n[data-sonner-toast][data-swipe-out=true][data-y-position=bottom],\n[data-sonner-toast][data-swipe-out=true][data-y-position=top] {\n animation: swipe-out 200ms ease-out forwards;\n}\n@keyframes swipe-out {\n from {\n transform: translateY(calc(var(--lift) * var(--offset) + var(--swipe-amount)));\n opacity: 1;\n }\n to {\n transform: translateY(calc(var(--lift) * var(--offset) + var(--swipe-amount) + var(--lift) * -100%));\n opacity: 0;\n }\n}\n@media (max-width: 600px) {\n [data-sonner-toaster] {\n position: fixed;\n --mobile-offset: 16px;\n right: var(--mobile-offset);\n left: var(--mobile-offset);\n width: 100%;\n }\n [data-sonner-toaster] [data-sonner-toast] {\n left: 0;\n right: 0;\n width: calc(100% - var(--mobile-offset) * 2);\n }\n [data-sonner-toaster][data-x-position=left] {\n left: var(--mobile-offset);\n }\n [data-sonner-toaster][data-y-position=bottom] {\n bottom: 20px;\n }\n [data-sonner-toaster][data-y-position=top] {\n top: 20px;\n }\n [data-sonner-toaster][data-x-position=center] {\n left: var(--mobile-offset);\n right: var(--mobile-offset);\n transform: none;\n }\n}\n[data-sonner-toaster][data-theme=light] {\n --normal-bg: #fff;\n --normal-border: var(--gray4);\n --normal-text: var(--gray12);\n --success-bg: hsl(143, 85%, 96%);\n --success-border: hsl(145, 92%, 91%);\n --success-text: hsl(140, 100%, 27%);\n --info-bg: hsl(208, 100%, 97%);\n --info-border: hsl(221, 91%, 91%);\n --info-text: hsl(210, 92%, 45%);\n --warning-bg: hsl(49, 100%, 97%);\n --warning-border: hsl(49, 91%, 91%);\n --warning-text: hsl(31, 92%, 45%);\n --error-bg: hsl(359, 100%, 97%);\n --error-border: hsl(359, 100%, 94%);\n --error-text: hsl(360, 100%, 45%);\n}\n[data-sonner-toaster][data-theme=light] [data-sonner-toast][data-invert=true] {\n --normal-bg: #000;\n --normal-border: hsl(0, 0%, 20%);\n --normal-text: var(--gray1);\n}\n[data-sonner-toaster][data-theme=dark] [data-sonner-toast][data-invert=true] {\n --normal-bg: #fff;\n --normal-border: var(--gray3);\n --normal-text: var(--gray12);\n}\n[data-sonner-toaster][data-theme=dark] {\n --normal-bg: #000;\n --normal-border: hsl(0, 0%, 20%);\n --normal-text: var(--gray1);\n --success-bg: hsl(150, 100%, 6%);\n --success-border: hsl(147, 100%, 12%);\n --success-text: hsl(150, 86%, 65%);\n --info-bg: hsl(215, 100%, 6%);\n --info-border: hsl(223, 100%, 12%);\n --info-text: hsl(216, 87%, 65%);\n --warning-bg: hsl(64, 100%, 6%);\n --warning-border: hsl(60, 100%, 12%);\n --warning-text: hsl(46, 87%, 65%);\n --error-bg: hsl(358, 76%, 10%);\n --error-border: hsl(357, 89%, 16%);\n --error-text: hsl(358, 100%, 81%);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=success] {\n background: var(--success-bg);\n border-color: var(--success-border);\n color: var(--success-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=success] [data-close-button] {\n background: var(--success-bg);\n border-color: var(--success-border);\n color: var(--success-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=info] {\n background: var(--info-bg);\n border-color: var(--info-border);\n color: var(--info-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=info] [data-close-button] {\n background: var(--info-bg);\n border-color: var(--info-border);\n color: var(--info-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=warning] {\n background: var(--warning-bg);\n border-color: var(--warning-border);\n color: var(--warning-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=warning] [data-close-button] {\n background: var(--warning-bg);\n border-color: var(--warning-border);\n color: var(--warning-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=error] {\n background: var(--error-bg);\n border-color: var(--error-border);\n color: var(--error-text);\n}\n[data-rich-colors=true] [data-sonner-toast][data-type=error] [data-close-button] {\n background: var(--error-bg);\n border-color: var(--error-border);\n color: var(--error-text);\n}\n.sonner-loading-wrapper {\n --size: 16px;\n height: var(--size);\n width: var(--size);\n position: absolute;\n inset: 0;\n z-index: 10;\n}\n.sonner-loading-wrapper[data-visible=false] {\n transform-origin: center;\n animation: sonner-fade-out 0.2s ease forwards;\n}\n.sonner-spinner {\n position: relative;\n top: 50%;\n left: 50%;\n height: var(--size);\n width: var(--size);\n}\n.sonner-loading-bar {\n animation: sonner-spin 1.2s linear infinite;\n background: var(--gray11);\n border-radius: 6px;\n height: 8%;\n left: -10%;\n position: absolute;\n top: -3.9%;\n width: 24%;\n}\n.sonner-loading-bar:nth-child(1) {\n animation-delay: -1.2s;\n transform: rotate(0.0001deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(2) {\n animation-delay: -1.1s;\n transform: rotate(30deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(3) {\n animation-delay: -1s;\n transform: rotate(60deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(4) {\n animation-delay: -0.9s;\n transform: rotate(90deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(5) {\n animation-delay: -0.8s;\n transform: rotate(120deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(6) {\n animation-delay: -0.7s;\n transform: rotate(150deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(7) {\n animation-delay: -0.6s;\n transform: rotate(180deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(8) {\n animation-delay: -0.5s;\n transform: rotate(210deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(9) {\n animation-delay: -0.4s;\n transform: rotate(240deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(10) {\n animation-delay: -0.3s;\n transform: rotate(270deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(11) {\n animation-delay: -0.2s;\n transform: rotate(300deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(12) {\n animation-delay: -0.1s;\n transform: rotate(330deg) translate(146%);\n}\n@keyframes sonner-fade-in {\n 0% {\n opacity: 0;\n transform: scale(0.8);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n}\n@keyframes sonner-fade-out {\n 0% {\n opacity: 1;\n transform: scale(1);\n }\n 100% {\n opacity: 0;\n transform: scale(0.8);\n }\n}\n@keyframes sonner-spin {\n 0% {\n opacity: 1;\n }\n 100% {\n opacity: 0.15;\n }\n}\n@media (prefers-reduced-motion) {\n [data-sonner-toast],\n [data-sonner-toast] > *,\n .sonner-loading-bar {\n transition: none !important;\n animation: none !important;\n }\n}\n.sonner-loader {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n transform-origin: center;\n transition: opacity 200ms, transform 200ms;\n}\n.sonner-loader[data-visible=false] {\n opacity: 0;\n transform: scale(0.8) translate(-50%, -50%);\n}\n');
styleInject('html[dir=ltr],\n[data-sonner-toaster][dir=ltr] {\n --toast-icon-margin-start: -3px;\n --toast-icon-margin-end: 4px;\n --toast-svg-margin-start: -1px;\n --toast-svg-margin-end: 0px;\n --toast-button-margin-start: auto;\n --toast-button-margin-end: 0;\n --toast-close-button-start: 0;\n --toast-close-button-end: unset;\n --toast-close-button-transform: translate(-35%, -35%);\n}\nhtml[dir=rtl],\n[data-sonner-toaster][dir=rtl] {\n --toast-icon-margin-start: 4px;\n --toast-icon-margin-end: -3px;\n --toast-svg-margin-start: 0px;\n --toast-svg-margin-end: -1px;\n --toast-button-margin-start: 0;\n --toast-button-margin-end: auto;\n --toast-close-button-start: unset;\n --toast-close-button-end: 0;\n --toast-close-button-transform: translate(35%, -35%);\n}\n[data-sonner-toaster] {\n position: fixed;\n width: var(--width);\n font-family:\n ui-sans-serif,\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n Segoe UI,\n Roboto,\n Helvetica Neue,\n Arial,\n Noto Sans,\n sans-serif,\n Apple Color Emoji,\n Segoe UI Emoji,\n Segoe UI Symbol,\n Noto Color Emoji;\n --gray1: hsl(0, 0%, 99%);\n --gray2: hsl(0, 0%, 97.3%);\n --gray3: hsl(0, 0%, 95.1%);\n --gray4: hsl(0, 0%, 93%);\n --gray5: hsl(0, 0%, 90.9%);\n --gray6: hsl(0, 0%, 88.7%);\n --gray7: hsl(0, 0%, 85.8%);\n --gray8: hsl(0, 0%, 78%);\n --gray9: hsl(0, 0%, 56.1%);\n --gray10: hsl(0, 0%, 52.3%);\n --gray11: hsl(0, 0%, 43.5%);\n --gray12: hsl(0, 0%, 9%);\n --border-radius: 8px;\n box-sizing: border-box;\n padding: 0;\n margin: 0;\n list-style: none;\n outline: none;\n z-index: 999999999;\n transition: transform 400ms ease;\n}\n@media (hover: none) and (pointer: coarse) {\n [data-sonner-toaster][data-lifted=true] {\n transform: none;\n }\n}\n[data-sonner-toaster][data-x-position=right] {\n right: var(--offset-right);\n}\n[data-sonner-toaster][data-x-position=left] {\n left: var(--offset-left);\n}\n[data-sonner-toaster][data-x-position=center] {\n left: 50%;\n transform: translateX(-50%);\n}\n[data-sonner-toaster][data-y-position=top] {\n top: var(--offset-top);\n}\n[data-sonner-toaster][data-y-position=bottom] {\n bottom: var(--offset-bottom);\n}\n[data-sonner-toast] {\n --y: translateY(100%);\n --lift-amount: calc(var(--lift) * var(--gap));\n z-index: var(--z-index);\n position: absolute;\n opacity: 0;\n transform: var(--y);\n touch-action: none;\n transition:\n transform 400ms,\n opacity 400ms,\n height 400ms,\n box-shadow 200ms;\n box-sizing: border-box;\n outline: none;\n overflow-wrap: anywhere;\n}\n[data-sonner-toast][data-styled=true] {\n padding: 16px;\n background: var(--normal-bg);\n border: 1px solid var(--normal-border);\n color: var(--normal-text);\n border-radius: var(--border-radius);\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1);\n width: var(--width);\n font-size: 13px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n[data-sonner-toast]:focus-visible {\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1), 0 0 0 2px rgba(0, 0, 0, 0.2);\n}\n[data-sonner-toast][data-y-position=top] {\n top: 0;\n --y: translateY(-100%);\n --lift: 1;\n --lift-amount: calc(1 * var(--gap));\n}\n[data-sonner-toast][data-y-position=bottom] {\n bottom: 0;\n --y: translateY(100%);\n --lift: -1;\n --lift-amount: calc(var(--lift) * var(--gap));\n}\n[data-sonner-toast][data-styled=true] [data-description] {\n font-weight: 400;\n line-height: 1.4;\n color: #3f3f3f;\n}\n[data-rich-colors=true][data-sonner-toast][data-styled=true] [data-description] {\n color: inherit;\n}\n[data-sonner-toaster][data-sonner-theme=dark] [data-description] {\n color: hsl(0, 0%, 91%);\n}\n[data-sonner-toast][data-styled=true] [data-title] {\n font-weight: 500;\n line-height: 1.5;\n color: inherit;\n}\n[data-sonner-toast][data-styled=true] [data-icon] {\n display: flex;\n height: 16px;\n width: 16px;\n position: relative;\n justify-content: flex-start;\n align-items: center;\n flex-shrink: 0;\n margin-left: var(--toast-icon-margin-start);\n margin-right: var(--toast-icon-margin-end);\n}\n[data-sonner-toast][data-promise=true] [data-icon] > svg {\n opacity: 0;\n transform: scale(0.8);\n transform-origin: center;\n animation: sonner-fade-in 300ms ease forwards;\n}\n[data-sonner-toast][data-styled=true] [data-icon] > * {\n flex-shrink: 0;\n}\n[data-sonner-toast][data-styled=true] [data-icon] svg {\n margin-left: var(--toast-svg-margin-start);\n margin-right: var(--toast-svg-margin-end);\n}\n[data-sonner-toast][data-styled=true] [data-content] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n[data-sonner-toast][data-styled=true] [data-button] {\n border-radius: 4px;\n padding-left: 8px;\n padding-right: 8px;\n height: 24px;\n font-size: 12px;\n color: var(--normal-bg);\n background: var(--normal-text);\n margin-left: var(--toast-button-margin-start);\n margin-right: var(--toast-button-margin-end);\n border: none;\n font-weight: 500;\n cursor: pointer;\n outline: none;\n display: flex;\n align-items: center;\n flex-shrink: 0;\n transition: opacity 400ms, box-shadow 200ms;\n}\n[data-sonner-toast][data-styled=true] [data-button]:focus-visible {\n box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.4);\n}\n[data-sonner-toast][data-styled=true] [data-button]:first-of-type {\n margin-left: var(--toast-button-margin-start);\n margin-right: var(--toast-button-margin-end);\n}\n[data-sonner-toast][data-styled=true] [data-cancel] {\n color: var(--normal-text);\n background: rgba(0, 0, 0, 0.08);\n}\n[data-sonner-toaster][data-sonner-theme=dark] [data-sonner-toast][data-styled=true] [data-cancel] {\n background: rgba(255, 255, 255, 0.3);\n}\n[data-sonner-toast][data-styled=true] [data-close-button] {\n position: absolute;\n left: var(--toast-close-button-start);\n right: var(--toast-close-button-end);\n top: 0;\n height: 20px;\n width: 20px;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 0;\n color: var(--normal-text);\n background: var(--normal-bg);\n border: 1px solid var(--normal-border);\n transform: var(--toast-close-button-transform);\n border-radius: 50%;\n cursor: pointer;\n z-index: 1;\n transition:\n opacity 100ms,\n background 200ms,\n border-color 200ms;\n}\n[data-sonner-toast][data-styled=true] [data-close-button]:focus-visible {\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1), 0 0 0 2px rgba(0, 0, 0, 0.2);\n}\n[data-sonner-toast][data-styled=true] [data-disabled=true] {\n cursor: not-allowed;\n}\n[data-sonner-toast][data-styled=true]:hover [data-close-button]:hover {\n background: var(--gray2);\n border-color: var(--gray5);\n}\n[data-sonner-toast][data-swiping=true]::before {\n content: "";\n position: absolute;\n left: -100%;\n right: -100%;\n height: 100%;\n z-index: -1;\n}\n[data-sonner-toast][data-y-position=top][data-swiping=true]::before {\n bottom: 50%;\n transform: scaleY(3) translateY(50%);\n}\n[data-sonner-toast][data-y-position=bottom][data-swiping=true]::before {\n top: 50%;\n transform: scaleY(3) translateY(-50%);\n}\n[data-sonner-toast][data-swiping=false][data-removed=true]::before {\n content: "";\n position: absolute;\n inset: 0;\n transform: scaleY(2);\n}\n[data-sonner-toast][data-expanded=true]::after {\n content: "";\n position: absolute;\n left: 0;\n height: calc(var(--gap) + 1px);\n bottom: 100%;\n width: 100%;\n}\n[data-sonner-toast][data-mounted=true] {\n --y: translateY(0);\n opacity: 1;\n}\n[data-sonner-toast][data-expanded=false][data-front=false] {\n --scale: var(--toasts-before) * 0.05 + 1;\n --y: translateY(calc(var(--lift-amount) * var(--toasts-before))) scale(calc(-1 * var(--scale)));\n height: var(--front-toast-height);\n}\n[data-sonner-toast] > * {\n transition: opacity 400ms;\n}\n[data-sonner-toast][data-x-position=right] {\n right: 0;\n}\n[data-sonner-toast][data-x-position=left] {\n left: 0;\n}\n[data-sonner-toast][data-expanded=false][data-front=false][data-styled=true] > * {\n opacity: 0;\n}\n[data-sonner-toast][data-visible=false] {\n opacity: 0;\n pointer-events: none;\n}\n[data-sonner-toast][data-mounted=true][data-expanded=true] {\n --y: translateY(calc(var(--lift) * var(--offset)));\n height: var(--initial-height);\n}\n[data-sonner-toast][data-removed=true][data-front=true][data-swipe-out=false] {\n --y: translateY(calc(var(--lift) * -100%));\n opacity: 0;\n}\n[data-sonner-toast][data-removed=true][data-front=false][data-swipe-out=false][data-expanded=true] {\n --y: translateY(calc(var(--lift) * var(--offset) + var(--lift) * -100%));\n opacity: 0;\n}\n[data-sonner-toast][data-removed=true][data-front=false][data-swipe-out=false][data-expanded=false] {\n --y: translateY(40%);\n opacity: 0;\n transition: transform 500ms, opacity 200ms;\n}\n[data-sonner-toast][data-removed=true][data-front=false]::before {\n height: calc(var(--initial-height) + 20%);\n}\n[data-sonner-toast][data-swiping=true] {\n transform: var(--y) translateY(var(--swipe-amount-y, 0px)) translateX(var(--swipe-amount-x, 0px));\n transition: none;\n}\n[data-sonner-toast][data-swiped=true] {\n -webkit-user-select: none;\n user-select: none;\n}\n[data-sonner-toast][data-swipe-out=true][data-y-position=bottom],\n[data-sonner-toast][data-swipe-out=true][data-y-position=top] {\n animation-duration: 200ms;\n animation-timing-function: ease-out;\n animation-fill-mode: forwards;\n}\n[data-sonner-toast][data-swipe-out=true][data-swipe-direction=left] {\n animation-name: swipe-out-left;\n}\n[data-sonner-toast][data-swipe-out=true][data-swipe-direction=right] {\n animation-name: swipe-out-right;\n}\n[data-sonner-toast][data-swipe-out=true][data-swipe-direction=up] {\n animation-name: swipe-out-up;\n}\n[data-sonner-toast][data-swipe-out=true][data-swipe-direction=down] {\n animation-name: swipe-out-down;\n}\n@keyframes swipe-out-left {\n from {\n transform: var(--y) translateX(var(--swipe-amount-x));\n opacity: 1;\n }\n to {\n transform: var(--y) translateX(calc(var(--swipe-amount-x) - 100%));\n opacity: 0;\n }\n}\n@keyframes swipe-out-right {\n from {\n transform: var(--y) translateX(var(--swipe-amount-x));\n opacity: 1;\n }\n to {\n transform: var(--y) translateX(calc(var(--swipe-amount-x) + 100%));\n opacity: 0;\n }\n}\n@keyframes swipe-out-up {\n from {\n transform: var(--y) translateY(var(--swipe-amount-y));\n opacity: 1;\n }\n to {\n transform: var(--y) translateY(calc(var(--swipe-amount-y) - 100%));\n opacity: 0;\n }\n}\n@keyframes swipe-out-down {\n from {\n transform: var(--y) translateY(var(--swipe-amount-y));\n opacity: 1;\n }\n to {\n transform: var(--y) translateY(calc(var(--swipe-amount-y) + 100%));\n opacity: 0;\n }\n}\n@media (max-width: 600px) {\n [data-sonner-toaster] {\n position: fixed;\n right: var(--mobile-offset-right);\n left: var(--mobile-offset-left);\n width: 100%;\n }\n [data-sonner-toaster][dir=rtl] {\n left: calc(var(--mobile-offset-left) * -1);\n }\n [data-sonner-toaster] [data-sonner-toast] {\n left: 0;\n right: 0;\n width: calc(100% - var(--mobile-offset-left) * 2);\n }\n [data-sonner-toaster][data-x-position=left] {\n left: var(--mobile-offset-left);\n }\n [data-sonner-toaster][data-y-position=bottom] {\n bottom: var(--mobile-offset-bottom);\n }\n [data-sonner-toaster][data-y-position=top] {\n top: var(--mobile-offset-top);\n }\n [data-sonner-toaster][data-x-position=center] {\n left: var(--mobile-offset-left);\n right: var(--mobile-offset-right);\n transform: none;\n }\n}\n[data-sonner-toaster][data-sonner-theme=light] {\n --normal-bg: #fff;\n --normal-border: var(--gray4);\n --normal-text: var(--gray12);\n --success-bg: hsl(143, 85%, 96%);\n --success-border: hsl(145, 92%, 87%);\n --success-text: hsl(140, 100%, 27%);\n --info-bg: hsl(208, 100%, 97%);\n --info-border: hsl(221, 91%, 93%);\n --info-text: hsl(210, 92%, 45%);\n --warning-bg: hsl(49, 100%, 97%);\n --warning-border: hsl(49, 91%, 84%);\n --warning-text: hsl(31, 92%, 45%);\n --error-bg: hsl(359, 100%, 97%);\n --error-border: hsl(359, 100%, 94%);\n --error-text: hsl(360, 100%, 45%);\n}\n[data-sonner-toaster][data-sonner-theme=light] [data-sonner-toast][data-invert=true] {\n --normal-bg: #000;\n --normal-border: hsl(0, 0%, 20%);\n --normal-text: var(--gray1);\n}\n[data-sonner-toaster][data-sonner-theme=dark] [data-sonner-toast][data-invert=true] {\n --normal-bg: #fff;\n --normal-border: var(--gray3);\n --normal-text: var(--gray12);\n}\n[data-sonner-toaster][data-sonner-theme=dark] {\n --normal-bg: #000;\n --normal-bg-hover: hsl(0, 0%, 12%);\n --normal-border: hsl(0, 0%, 20%);\n --normal-border-hover: hsl(0, 0%, 25%);\n --normal-text: var(--gray1);\n --success-bg: hsl(150, 100%, 6%);\n --success-border: hsl(147, 100%, 12%);\n --success-text: hsl(150, 86%, 65%);\n --info-bg: hsl(215, 100%, 6%);\n --info-border: hsl(223, 43%, 17%);\n --info-text: hsl(216, 87%, 65%);\n --warning-bg: hsl(64, 100%, 6%);\n --warning-border: hsl(60, 100%, 9%);\n --warning-text: hsl(46, 87%, 65%);\n --error-bg: hsl(358, 76%, 10%);\n --error-border: hsl(357, 89%, 16%);\n --error-text: hsl(358, 100%, 81%);\n}\n[data-sonner-toaster][data-sonner-theme=dark] [data-sonner-toast] [data-close-button] {\n background: var(--normal-bg);\n border-color: var(--normal-border);\n color: var(--normal-text);\n}\n[data-sonner-toaster][data-sonner-theme=dark] [data-sonner-toast] [data-close-button]:hover {\n background: var(--normal-bg-hover);\n border-color: var(--normal-border-hover);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=success] {\n background: var(--success-bg);\n border-color: var(--success-border);\n color: var(--success-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=success] [data-close-button] {\n background: var(--success-bg);\n border-color: var(--success-border);\n color: var(--success-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=info] {\n background: var(--info-bg);\n border-color: var(--info-border);\n color: var(--info-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=info] [data-close-button] {\n background: var(--info-bg);\n border-color: var(--info-border);\n color: var(--info-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=warning] {\n background: var(--warning-bg);\n border-color: var(--warning-border);\n color: var(--warning-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=warning] [data-close-button] {\n background: var(--warning-bg);\n border-color: var(--warning-border);\n color: var(--warning-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=error] {\n background: var(--error-bg);\n border-color: var(--error-border);\n color: var(--error-text);\n}\n[data-rich-colors=true][data-sonner-toast][data-type=error] [data-close-button] {\n background: var(--error-bg);\n border-color: var(--error-border);\n color: var(--error-text);\n}\n.sonner-loading-wrapper {\n --size: 16px;\n height: var(--size);\n width: var(--size);\n position: absolute;\n inset: 0;\n z-index: 10;\n}\n.sonner-loading-wrapper[data-visible=false] {\n transform-origin: center;\n animation: sonner-fade-out 0.2s ease forwards;\n}\n.sonner-spinner {\n position: relative;\n top: 50%;\n left: 50%;\n height: var(--size);\n width: var(--size);\n}\n.sonner-loading-bar {\n animation: sonner-spin 1.2s linear infinite;\n background: var(--gray11);\n border-radius: 6px;\n height: 8%;\n left: -10%;\n position: absolute;\n top: -3.9%;\n width: 24%;\n}\n.sonner-loading-bar:nth-child(1) {\n animation-delay: -1.2s;\n transform: rotate(0.0001deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(2) {\n animation-delay: -1.1s;\n transform: rotate(30deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(3) {\n animation-delay: -1s;\n transform: rotate(60deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(4) {\n animation-delay: -0.9s;\n transform: rotate(90deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(5) {\n animation-delay: -0.8s;\n transform: rotate(120deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(6) {\n animation-delay: -0.7s;\n transform: rotate(150deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(7) {\n animation-delay: -0.6s;\n transform: rotate(180deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(8) {\n animation-delay: -0.5s;\n transform: rotate(210deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(9) {\n animation-delay: -0.4s;\n transform: rotate(240deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(10) {\n animation-delay: -0.3s;\n transform: rotate(270deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(11) {\n animation-delay: -0.2s;\n transform: rotate(300deg) translate(146%);\n}\n.sonner-loading-bar:nth-child(12) {\n animation-delay: -0.1s;\n transform: rotate(330deg) translate(146%);\n}\n@keyframes sonner-fade-in {\n 0% {\n opacity: 0;\n transform: scale(0.8);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n}\n@keyframes sonner-fade-out {\n 0% {\n opacity: 1;\n transform: scale(1);\n }\n 100% {\n opacity: 0;\n transform: scale(0.8);\n }\n}\n@keyframes sonner-spin {\n 0% {\n opacity: 1;\n }\n 100% {\n opacity: 0.15;\n }\n}\n@media (prefers-reduced-motion) {\n [data-sonner-toast],\n [data-sonner-toast] > *,\n .sonner-loading-bar {\n transition: none !important;\n animation: none !important;\n }\n}\n.sonner-loader {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n transform-origin: center;\n transition: opacity 200ms, transform 200ms;\n}\n.sonner-loader[data-visible=false] {\n opacity: 0;\n transform: scale(0.8) translate(-50%, -50%);\n}\n');
// src/index.tsx
import { For as For2, Show, createEffect, createSignal as createSignal2, mergeProps, on, onCleanup as onCleanup2, onMount as onMount2 } from "solid-js";
import { For as For2, Show, createEffect, createMemo, createSignal as createSignal2, mergeProps, on, onCleanup as onCleanup2, onMount as onMount2 } from "solid-js";
import { createStore, produce, reconcile } from "solid-js/store";

@@ -35,31 +35,43 @@

function Loader(props) {
return <div class="sonner-loading-wrapper" data-visible={props.visible}><div class="sonner-spinner"><For each={bars}>{() => <div class="sonner-loading-bar" />}</For></div></div>;
return <div class={["sonner-loading-wrapper", props.class ?? props.className].filter(Boolean).join(" ")} data-visible={props.visible}>
<div class="sonner-spinner">
<For each={bars}>{(_, i) => <div class="sonner-loading-bar" data-index={i()} />}</For>
</div>
</div>;
}
function SuccessIcon() {
return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" height="20" width="20"><path
return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" height="20" width="20">
<path
fill-rule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
clip-rule="evenodd"
/></svg>;
/>
</svg>;
}
function WarningIcon() {
return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" height="20" width="20"><path
return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" height="20" width="20">
<path
fill-rule="evenodd"
d="M9.401 3.003c1.155-2 4.043-2 5.197 0l7.355 12.748c1.154 2-.29 4.5-2.599 4.5H4.645c-2.309 0-3.752-2.5-2.598-4.5L9.4 3.003zM12 8.25a.75.75 0 01.75.75v3.75a.75.75 0 01-1.5 0V9a.75.75 0 01.75-.75zm0 8.25a.75.75 0 100-1.5.75.75 0 000 1.5z"
clip-rule="evenodd"
/></svg>;
/>
</svg>;
}
function InfoIcon() {
return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" height="20" width="20"><path
return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" height="20" width="20">
<path
fill-rule="evenodd"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z"
clip-rule="evenodd"
/></svg>;
/>
</svg>;
}
function ErrorIcon() {
return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" height="20" width="20"><path
return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" height="20" width="20">
<path
fill-rule="evenodd"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-5a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 5zm0 10a1 1 0 100-2 1 1 0 000 2z"
clip-rule="evenodd"
/></svg>;
/>
</svg>;
}

@@ -69,9 +81,9 @@ function getAsset(type) {

case "success":
return SuccessIcon;
return <SuccessIcon />;
case "info":
return InfoIcon;
return <InfoIcon />;
case "warning":
return WarningIcon;
return <WarningIcon />;
case "error":
return ErrorIcon;
return <ErrorIcon />;
default:

@@ -81,13 +93,46 @@ return null;

}
function CloseIcon() {
return <svg
xmlns="http://www.w3.org/2000/svg"
width="12"
height="12"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
>
<line x1="18" y1="6" x2="6" y2="18" />
<line x1="6" y1="6" x2="18" y2="18" />
</svg>;
}
// src/primitives.ts
import { createSignal, onCleanup, onMount } from "solid-js";
function useIsDocumentHidden() {
const [isDocumentHidden, setIsDocumentHidden] = createSignal(typeof document !== "undefined" ? document.hidden : false);
onMount(() => {
const callback = () => {
setIsDocumentHidden(document.hidden);
};
document.addEventListener("visibilitychange", callback);
onCleanup(() => {
document.removeEventListener("visibilitychange", callback);
});
});
return isDocumentHidden;
}
// src/state.ts
var toastsCounter = 0;
var toastsCounter = 1;
var Observer = class {
subscribers;
toasts;
dismissedToasts;
constructor() {
this.subscribers = [];
this.toasts = [];
this.dismissedToasts = /* @__PURE__ */ new Set();
}
// We use arrow functions to maintain the correct `this` reference
subscribe = (subscriber) => {

@@ -109,11 +154,21 @@ this.subscribers.push(subscriber);

const { message, ...rest } = data;
const id = typeof data?.id === "number" || data.id && data.id?.length > 0 ? data.id : toastsCounter++;
const hasStringId = typeof data.id === "string" && data.id.length > 0;
const id = typeof data.id === "number" || hasStringId ? data.id : toastsCounter++;
const alreadyExists = this.toasts.find((toast2) => {
return toast2.id === id;
});
const dismissible = data.dismissible === void 0 ? true : data.dismissible;
if (this.dismissedToasts.has(id))
this.dismissedToasts.delete(id);
if (alreadyExists) {
this.toasts = this.toasts.map((toast2) => {
if (toast2.id === id) {
this.publish({ ...toast2, ...data, id, title: message });
return { ...toast2, ...data, id, title: message };
this.publish({ ...toast2, ...data, id, title: message, dismissible });
return {
...toast2,
...data,
id,
dismissible,
title: message
};
}

@@ -123,3 +178,3 @@ return toast2;

} else {
this.addToast({ title: message, ...rest, id });
this.addToast({ title: message, ...rest, dismissible, id });
}

@@ -129,8 +184,13 @@ return id;

dismiss = (id) => {
if (!id) {
if (id) {
this.dismissedToasts.add(id);
requestAnimationFrame(() => {
this.subscribers.forEach((subscriber) => subscriber({ id, dismiss: true }));
});
} else {
this.toasts.forEach((toast2) => {
this.dismissedToasts.add(toast2.id);
this.subscribers.forEach((subscriber) => subscriber({ id: toast2.id, dismiss: true }));
});
}
this.subscribers.forEach((subscriber) => subscriber({ id, dismiss: true }));
return id;

@@ -153,6 +213,8 @@ };

};
loading = (message, data) => {
return this.create({ ...data, type: "loading", message });
};
promise = (promise, data) => {
if (!data) {
if (!data)
return;
}
let id;

@@ -164,22 +226,41 @@ if (data.loading !== void 0) {

type: "loading",
message: data.loading
message: data.loading,
description: typeof data.description !== "function" ? data.description : void 0
});
}
const p = promise instanceof Promise ? promise : promise();
const p = Promise.resolve(typeof promise === "function" ? promise() : promise);
let shouldDismiss = id !== void 0;
p.then((response) => {
if (response && typeof response.ok === "boolean" && !response.ok) {
let result;
const originalPromise = p.then(async (response) => {
result = ["resolve", response];
if (isValidElement(response)) {
shouldDismiss = false;
const message = typeof data.error === "function" ? data.error(`HTTP error! status: ${response.status}`) : data.error;
this.create({ id, type: "error", message });
this.create({ id, type: "default", message: response });
} else if (isHttpResponse(response) && !response.ok) {
shouldDismiss = false;
const promiseData = typeof data.error === "function" ? await data.error(`HTTP error! status: ${response.status}`) : data.error;
const description = typeof data.description === "function" ? await data.description(`HTTP error! status: ${response.status}`) : data.description;
const toastSettings = isExtendedResult(promiseData) ? promiseData : { message: promiseData };
this.create({ id, type: "error", description, ...toastSettings });
} else if (response instanceof Error) {
shouldDismiss = false;
const promiseData = typeof data.error === "function" ? await data.error(response) : data.error;
const description = typeof data.description === "function" ? await data.description(response) : data.description;
const toastSettings = isExtendedResult(promiseData) ? promiseData : { message: promiseData };
this.create({ id, type: "error", description, ...toastSettings });
} else if (data.success !== void 0) {
shouldDismiss = false;
const message = typeof data.success === "function" ? data.success(response) : data.success;
this.create({ id, type: "success", message });
const promiseData = typeof data.success === "function" ? await data.success(response) : data.success;
const description = typeof data.description === "function" ? await data.description(response) : data.description;
const toastSettings = isExtendedResult(promiseData) ? promiseData : { message: promiseData };
this.create({ id, type: "success", description, ...toastSettings });
}
}).catch((error) => {
}).catch(async (error) => {
result = ["reject", error];
if (data.error !== void 0) {
shouldDismiss = false;
const message = typeof data.error === "function" ? data.error(error) : data.error;
this.create({ id, type: "error", message });
const promiseData = typeof data.error === "function" ? await data.error(error) : data.error;
const description = typeof data.description === "function" ? await data.description(error) : data.description;
const toastSettings = isExtendedResult(promiseData) ? promiseData : { message: promiseData };
this.create({ id, type: "error", description, ...toastSettings });
}

@@ -193,14 +274,32 @@ }).finally(() => {

});
return id;
const unwrap = () => new Promise((resolve, reject) => {
originalPromise.then(() => {
if (result[0] === "reject")
reject(result[1]);
else
resolve(result[1]);
}).catch(reject);
});
if (typeof id !== "string" && typeof id !== "number")
return { unwrap };
return Object.assign(id, { unwrap });
};
loading = (message, data) => {
return this.create({ ...data, type: "loading", message });
};
// We can't provide the toast we just created as a prop as we didn't create it yet, so we can create a default toast object, I just don't know how to use function in argument when calling()?
custom = (jsx, data) => {
const id = data?.id || toastsCounter++;
this.publish({ jsx: jsx(id), id, ...data });
this.create({ jsx: jsx(id), ...data, id });
return id;
};
getActiveToasts = () => {
return this.toasts.filter((toast2) => !this.dismissedToasts.has(toast2.id));
};
};
function isHttpResponse(data) {
return data && typeof data === "object" && "ok" in data && typeof data.ok === "boolean" && "status" in data && typeof data.status === "number";
}
function isExtendedResult(value) {
return typeof value === "object" && value !== null && "message" in value;
}
function isValidElement(value) {
return typeof Node !== "undefined" && value instanceof Node;
}
var ToastState = new Observer();

@@ -217,28 +316,26 @@ function toastFunction(message, data) {

var basicToast = toastFunction;
var toast = Object.assign(basicToast, {
success: ToastState.success,
info: ToastState.info,
warning: ToastState.warning,
error: ToastState.error,
custom: ToastState.custom,
message: ToastState.message,
promise: ToastState.promise,
dismiss: ToastState.dismiss,
loading: ToastState.loading
});
var getHistory = () => ToastState.toasts;
var getToasts = () => ToastState.getActiveToasts();
var toast = Object.assign(
basicToast,
{
success: ToastState.success,
info: ToastState.info,
warning: ToastState.warning,
error: ToastState.error,
custom: ToastState.custom,
message: ToastState.message,
promise: ToastState.promise,
dismiss: ToastState.dismiss,
loading: ToastState.loading
},
{
getHistory,
getToasts
}
);
// src/primitives.ts
import { createSignal, onCleanup, onMount } from "solid-js";
function useIsDocumentHidden() {
const [isDocumentHidden, setIsDocumentHidden] = createSignal(false);
onMount(() => {
const callback = () => {
setIsDocumentHidden(document.hidden);
};
document.addEventListener("visibilitychange", callback);
onCleanup(() => {
window.removeEventListener("visibilitychange", callback);
});
});
return isDocumentHidden;
// src/types.ts
function isAction(action) {
return typeof action === "object" && action !== null && "label" in action;
}

@@ -248,12 +345,99 @@

var VISIBLE_TOASTS_AMOUNT = 3;
var VIEWPORT_OFFSET = "32px";
var VIEWPORT_OFFSET = "24px";
var MOBILE_VIEWPORT_OFFSET = "16px";
var TOAST_LIFETIME = 4e3;
var TOAST_WIDTH = 356;
var GAP = 14;
var SWIPE_TRESHOLD = 20;
var SWIPE_THRESHOLD = 45;
var TIME_BEFORE_UNMOUNT = 200;
function _cn(...classes) {
function cn(...classes) {
return classes.filter(Boolean).join(" ");
}
var Toast = (props) => {
function resolveContent(content) {
return typeof content === "function" ? content() : content;
}
function getDefaultSwipeDirections(position) {
const [y, x] = position.split("-");
const directions = [];
if (y)
directions.push(y);
if (x)
directions.push(x);
return directions;
}
function getDocumentDirection() {
if (typeof window === "undefined" || typeof document === "undefined")
return "ltr";
const dirAttribute = document.documentElement.getAttribute("dir");
if (dirAttribute === "auto" || !dirAttribute)
return window.getComputedStyle(document.documentElement).direction;
return dirAttribute;
}
function assignOffset(defaultOffset, mobileOffset) {
const styles = {};
[defaultOffset, mobileOffset].forEach((offset, index) => {
const isMobile = index === 1;
const prefix = isMobile ? "--mobile-offset" : "--offset";
const defaultValue = isMobile ? MOBILE_VIEWPORT_OFFSET : VIEWPORT_OFFSET;
const assignAll = (value) => {
for (const key of ["top", "right", "bottom", "left"])
styles[`${prefix}-${key}`] = typeof value === "number" ? `${value}px` : value;
};
if (typeof offset === "number" || typeof offset === "string") {
assignAll(offset);
return;
}
if (typeof offset === "object" && offset !== null) {
for (const key of ["top", "right", "bottom", "left"]) {
const value = offset[key];
styles[`${prefix}-${key}`] = value === void 0 ? defaultValue : typeof value === "number" ? `${value}px` : value;
}
return;
}
assignAll(defaultValue);
});
return styles;
}
function mergeClassNames(classNames, legacy) {
return classNames ?? legacy;
}
function mergeDescriptionClassName(descriptionClassName, legacy) {
return descriptionClassName ?? legacy ?? "";
}
function mergeClassName(className, legacy) {
return className ?? legacy ?? "";
}
function useSonner() {
const [activeToasts, setActiveToasts] = createSignal2(toast.getToasts());
onMount2(() => {
const unsubscribe = ToastState.subscribe((toastItem) => {
if (toastItem.dismiss) {
requestAnimationFrame(() => {
setActiveToasts((toasts) => toasts.filter((t) => t.id !== toastItem.id));
});
return;
}
const nextToast = toastItem;
setActiveToasts((toasts) => {
const indexOfExistingToast = toasts.findIndex((t) => t.id === nextToast.id);
if (indexOfExistingToast !== -1) {
return [
...toasts.slice(0, indexOfExistingToast),
{ ...toasts[indexOfExistingToast], ...nextToast },
...toasts.slice(indexOfExistingToast + 1)
];
}
return [nextToast, ...toasts];
});
});
onCleanup2(unsubscribe);
});
return {
toasts: activeToasts
};
}
function createToastTheme(theme) {
return theme !== "system" ? theme : typeof window !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
}
function Toast(props) {
const [mounted, setMounted] = createSignal2(false);

@@ -263,20 +447,32 @@ const [removed, setRemoved] = createSignal2(false);

const [swipeOut, setSwipeOut] = createSignal2(false);
const [isSwiped, setIsSwiped] = createSignal2(false);
const [swipeDirection, setSwipeDirection] = createSignal2(null);
const [swipeOutDirection, setSwipeOutDirection] = createSignal2(null);
const [offsetBeforeRemove, setOffsetBeforeRemove] = createSignal2(0);
const [initialHeight, setInitialHeight] = createSignal2(0);
let toastRef;
let dragStartTime = null;
let closeTimerStartTimeRef = 0;
let lastCloseTimerStartTimeRef = 0;
let remainingTime = TOAST_LIFETIME;
const [pointerStartRef, setPointerStartRef] = createSignal2(null);
const isFront = () => props.index === 0;
const isVisible = () => props.index + 1 <= props.visibleToasts;
const toastType = () => props.toast.type;
const toastClassname = () => props.toast.class || "";
const toastDescriptionClassname = () => props.toast.descriptionClass || "";
const propsWithDefaults = mergeProps({
gap: GAP
}, props);
const heightIndex = () => props.heights.findIndex((height) => height.toastId === props.toast.id) || 0;
const duration = () => props.toast.duration || props.duration || TOAST_LIFETIME;
let closeTimerStartTimeRef = 0;
let lastCloseTimerStartTimeRef = 0;
const [pointerStartRef, setPointerStartRef] = createSignal2(null);
const coords = () => props.position.split("-");
const toastsHeightBefore = () => {
const dismissible = () => props.toast.dismissible !== false;
const classNames = () => mergeClassNames(props.classNames, props.classes);
const className = () => mergeClassName(props.className, props.class);
const descriptionClassName = () => mergeDescriptionClassName(props.descriptionClassName, props.descriptionClass);
const toastClassName = () => mergeClassName(props.toast.className, props.toast.class);
const toastDescriptionClassName = () => mergeDescriptionClassName(props.toast.descriptionClassName, props.toast.descriptionClass);
const toastClassNames = () => mergeClassNames(props.toast.classNames, props.toast.classes);
const closeButton = () => props.toast.closeButton ?? props.closeButton;
const duration = () => props.toast.duration ?? props.duration ?? TOAST_LIFETIME;
const invert = () => props.toast.invert ?? props.invert;
const disabled = () => toastType() === "loading";
const swipeDirections = () => props.swipeDirections ?? getDefaultSwipeDirections(props.position);
const y = createMemo(() => props.position.split("-")[0]);
const x = createMemo(() => props.position.split("-")[1]);
const heightIndex = createMemo(() => Math.max(0, props.heights.findIndex((height) => height.toastId === props.toast.id)));
const toastsHeightBefore = createMemo(() => {
return props.heights.reduce((prev, curr, reducerIndex) => {

@@ -287,56 +483,58 @@ if (reducerIndex >= heightIndex())

}, 0);
};
});
const offset = createMemo(() => heightIndex() * (props.gap ?? GAP) + toastsHeightBefore());
const isDocumentHidden = useIsDocumentHidden();
const invert = () => props.toast.invert || props.invert;
const disabled = () => toastType() === "loading";
const offset = () => heightIndex() * propsWithDefaults.gap + toastsHeightBefore();
createEffect(() => {
remainingTime = duration();
});
function deleteToast() {
setRemoved(true);
setOffsetBeforeRemove(offset());
props.setHeights((heights) => heights.filter((height) => height.toastId !== props.toast.id));
window.setTimeout(() => {
props.removeToast(props.toast);
}, TIME_BEFORE_UNMOUNT);
}
function getLoadingIcon() {
if (props.icons?.loading) {
return <div class="sonner-loader" data-visible={toastType() === "loading"}>{props.icons.loading}</div>;
return <div class={cn(classNames()?.loader, toastClassNames()?.loader, "sonner-loader")} data-visible={toastType() === "loading"}>
{props.icons.loading}
</div>;
}
return <Loader visible={toastType() === "loading"} />;
return <Loader class={cn(classNames()?.loader, toastClassNames()?.loader)} visible={toastType() === "loading"} />;
}
const icon = () => props.toast.icon ?? props.icons?.[toastType()] ?? getAsset(toastType());
onMount2(() => {
setMounted(true);
if (!toastRef)
return;
const height = toastRef.getBoundingClientRect().height;
setInitialHeight(height);
props.setHeights((h) => [{ toastId: props.toast.id, toasterId: props.toast.toasterId, height, position: props.toast.position }, ...h]);
onCleanup2(() => {
props.setHeights((h) => h.filter((height2) => height2.toastId !== props.toast.id));
});
});
onMount2(() => {
const toastNode = toastRef;
const originalHeight = toastNode.style.height;
toastNode.style.height = "auto";
const newHeight = toastNode.getBoundingClientRect().height;
toastNode.style.height = originalHeight;
setInitialHeight(newHeight);
createEffect(() => {
props.setHeights((heights) => {
const alreadyExists = heights.find((height) => height.toastId === props.toast.id);
if (!alreadyExists)
return [{ toastId: props.toast.id, height: newHeight, position: props.toast.position }, ...heights];
else
return heights.map((height) => height.toastId === props.toast.id ? { ...height, height: newHeight } : height);
});
createEffect(() => {
if (!mounted() || !toastRef)
return;
resolveContent(props.toast.title);
resolveContent(props.toast.description);
const originalHeight = toastRef.style.height;
toastRef.style.height = "auto";
const nextHeight = toastRef.getBoundingClientRect().height;
toastRef.style.height = originalHeight;
setInitialHeight(nextHeight);
props.setHeights((heights) => {
const alreadyExists = heights.find((height) => height.toastId === props.toast.id);
if (!alreadyExists)
return [{ toastId: props.toast.id, toasterId: props.toast.toasterId, height: nextHeight, position: props.toast.position }, ...heights];
return heights.map((height) => height.toastId === props.toast.id ? { ...height, height: nextHeight } : height);
});
});
const deleteToast = () => {
setRemoved(true);
setOffsetBeforeRemove(offset());
props.setHeights((h) => h.filter((height) => height.toastId !== props.toast.id));
setTimeout(() => {
props.removeToast(props.toast);
}, TIME_BEFORE_UNMOUNT);
};
let remainingTime = duration();
createEffect(
on(
() => [
props.expanded,
props.interacting,
props.toast,
duration(),
props.toast.promise,
toastType(),
props.pauseWhenPageIsHidden,
isDocumentHidden()
],
([expanded, interacting, toast2, duration2, promise, toastType2, pauseWhenPageIsHidden, isDocumentHidden2]) => {
if (promise && toastType2 === "loading" || duration2 === Number.POSITIVE_INFINITY)
() => [props.expanded, props.interacting, props.toast, toastType(), isDocumentHidden(), duration()],
([expanded, interacting, currentToast, currentType]) => {
if (currentToast.promise && currentType === "loading" || currentToast.duration === Number.POSITIVE_INFINITY || currentType === "loading")
return;

@@ -347,3 +545,3 @@ let timeoutId;

const elapsedTime = (/* @__PURE__ */ new Date()).getTime() - closeTimerStartTimeRef;
remainingTime = remainingTime - elapsedTime;
remainingTime -= elapsedTime;
}

@@ -353,9 +551,12 @@ lastCloseTimerStartTimeRef = (/* @__PURE__ */ new Date()).getTime();

const startTimer = () => {
if (remainingTime === Number.POSITIVE_INFINITY)
return;
closeTimerStartTimeRef = (/* @__PURE__ */ new Date()).getTime();
timeoutId = setTimeout(() => {
toast2.onAutoClose?.(toast2);
currentToast.onAutoClose?.(currentToast);
deleteToast();
}, remainingTime);
};
if (expanded || interacting || pauseWhenPageIsHidden && isDocumentHidden2)
const shouldPause = expanded || interacting || (props.pauseWhenPageIsHidden ?? true) && isDocumentHidden();
if (shouldPause)
pauseTimer();

@@ -365,3 +566,4 @@ else

onCleanup2(() => {
clearTimeout(timeoutId);
if (timeoutId)
clearTimeout(timeoutId);
});

@@ -373,22 +575,8 @@ }

on(
() => props.toast.id,
(toastId) => {
const toastNode = toastRef;
if (toastNode) {
const height = toastNode.getBoundingClientRect().height;
setInitialHeight(height);
props.setHeights((h) => [{ toastId, height, position: props.toast.position }, ...h]);
onCleanup2(() => {
props.setHeights((h) => h.filter((height2) => height2.toastId !== toastId));
});
}
}
)
);
createEffect(
on(
() => props.toast.delete,
(d) => {
if (d)
(shouldDelete) => {
if (shouldDelete) {
deleteToast();
props.toast.onDismiss?.(props.toast);
}
}

@@ -398,31 +586,33 @@ )

return <li
aria-live={props.toast.important ? "assertive" : "polite"}
aria-atomic="true"
role="status"
tabIndex={0}
ref={toastRef}
class={_cn(
props.class,
toastClassname(),
props.classes?.toast,
props.toast?.classes?.toast,
props.classes?.default,
props.classes?.[toastType()],
props.toast?.classes?.[toastType()]
class={cn(
className(),
toastClassName(),
classNames()?.toast,
toastClassNames()?.toast,
classNames()?.default,
classNames()?.[toastType()],
toastClassNames()?.[toastType()]
)}
data-sonner-toast=""
data-rich-colors={props.toast.richColors ?? props.defaultRichColors}
data-styled={!(props.toast.jsx || props.toast.unstyled || props.unstyled)}
data-mounted={mounted()}
data-promise={Boolean(props.toast.promise)}
data-swiped={isSwiped()}
data-removed={removed()}
data-visible={isVisible()}
data-y-position={coords()[0]}
data-x-position={coords()[1]}
data-y-position={y()}
data-x-position={x()}
data-index={props.index}
data-front={isFront()}
data-swiping={swiping()}
data-dismissible={dismissible()}
data-type={toastType()}
data-invert={invert()}
data-swipe-out={swipeOut()}
data-swipe-direction={swipeOutDirection()}
data-expanded={Boolean(props.expanded || props.expandByDefault && mounted())}
data-testid={props.toast.testId}
style={{

@@ -437,7 +627,15 @@ "--index": props.index,

}}
onDragEnd={() => {
setSwiping(false);
setSwipeDirection(null);
setPointerStartRef(null);
}}
onPointerDown={(event) => {
if (disabled())
if (event.button === 2)
return;
if (disabled() || !dismissible())
return;
dragStartTime = /* @__PURE__ */ new Date();
setOffsetBeforeRemove(offset());
event.target.setPointerCapture(event.pointerId);
event.currentTarget.setPointerCapture(event.pointerId);
if (event.target.tagName === "BUTTON")

@@ -449,9 +647,17 @@ return;

onPointerUp={() => {
if (swipeOut())
if (swipeOut() || !dismissible())
return;
setPointerStartRef(null);
const swipeAmount = Number(toastRef?.style.getPropertyValue("--swipe-amount").replace("px", "") || 0);
if (Math.abs(swipeAmount) >= SWIPE_TRESHOLD) {
const swipeAmountX = Number(toastRef?.style.getPropertyValue("--swipe-amount-x").replace("px", "") || 0);
const swipeAmountY = Number(toastRef?.style.getPropertyValue("--swipe-amount-y").replace("px", "") || 0);
const timeTaken = Math.max(1, (/* @__PURE__ */ new Date()).getTime() - (dragStartTime?.getTime() ?? 0));
const swipeAmount = swipeDirection() === "x" ? swipeAmountX : swipeAmountY;
const velocity = Math.abs(swipeAmount) / timeTaken;
if (Math.abs(swipeAmount) >= SWIPE_THRESHOLD || velocity > 0.11) {
setOffsetBeforeRemove(offset());
props.toast.onDismiss?.(props.toast);
if (swipeDirection() === "x")
setSwipeOutDirection(swipeAmountX > 0 ? "right" : "left");
else
setSwipeOutDirection(swipeAmountY > 0 ? "down" : "up");
deleteToast();

@@ -461,83 +667,128 @@ setSwipeOut(true);

}
toastRef?.style.setProperty("--swipe-amount", "0px");
toastRef?.style.setProperty("--swipe-amount-x", "0px");
toastRef?.style.setProperty("--swipe-amount-y", "0px");
setIsSwiped(false);
setSwiping(false);
setSwipeDirection(null);
}}
onPointerMove={(event) => {
if (!pointerStartRef())
if (!pointerStartRef() || !dismissible())
return;
const yPosition = event.clientY - pointerStartRef().y;
const xPosition = event.clientX - pointerStartRef().x;
const clamp = coords()[0] === "top" ? Math.min : Math.max;
const clampedY = clamp(0, yPosition);
const swipeStartThreshold = event.pointerType === "touch" ? 10 : 2;
const isAllowedToSwipe = Math.abs(clampedY) > swipeStartThreshold;
if (isAllowedToSwipe) {
toastRef?.style.setProperty("--swipe-amount", `${yPosition}px`);
} else if (Math.abs(xPosition) > swipeStartThreshold) {
setPointerStartRef(null);
if ((window.getSelection()?.toString().length ?? 0) > 0)
return;
const yDelta = event.clientY - pointerStartRef().y;
const xDelta = event.clientX - pointerStartRef().x;
if (!swipeDirection() && (Math.abs(xDelta) > 1 || Math.abs(yDelta) > 1))
setSwipeDirection(Math.abs(xDelta) > Math.abs(yDelta) ? "x" : "y");
const swipeAmount = { x: 0, y: 0 };
const getDampening = (delta) => {
const factor = Math.abs(delta) / 20;
return 1 / (1.5 + factor);
};
if (swipeDirection() === "y") {
if (swipeDirections().includes("top") || swipeDirections().includes("bottom")) {
if (swipeDirections().includes("top") && yDelta < 0 || swipeDirections().includes("bottom") && yDelta > 0)
swipeAmount.y = yDelta;
else
swipeAmount.y = yDelta * getDampening(yDelta);
}
} else if (swipeDirection() === "x") {
if (swipeDirections().includes("left") || swipeDirections().includes("right")) {
if (swipeDirections().includes("left") && xDelta < 0 || swipeDirections().includes("right") && xDelta > 0)
swipeAmount.x = xDelta;
else
swipeAmount.x = xDelta * getDampening(xDelta);
}
}
if (Math.abs(swipeAmount.x) > 0 || Math.abs(swipeAmount.y) > 0)
setIsSwiped(true);
toastRef?.style.setProperty("--swipe-amount-x", `${swipeAmount.x}px`);
toastRef?.style.setProperty("--swipe-amount-y", `${swipeAmount.y}px`);
}}
><Show when={props.closeButton && !props.toast.jsx}><button
aria-label="Close toast"
>
<Show when={closeButton() && !props.toast.jsx && toastType() !== "loading"}>
<button
aria-label={props.closeButtonAriaLabel ?? "Close toast"}
data-disabled={disabled()}
data-close-button
onClick={disabled() ? void 0 : () => {
onClick={() => {
if (disabled() || !dismissible())
return;
deleteToast();
props.toast.onDismiss?.(props.toast);
}}
class={_cn(props.classes?.closeButton, props.toast?.classes?.closeButton)}
><svg
xmlns="http://www.w3.org/2000/svg"
width="12"
height="12"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
><line x1="18" y1="6" x2="6" y2="18" /><line x1="6" y1="6" x2="18" y2="18" /></svg></button></Show><Show
when={props.toast.jsx || props.toast.title instanceof Element}
fallback={<><Show when={toastType() || props.toast.icon || props.toast.promise}><div data-icon="">{props.toast.promise || props.toast.type === "loading" && !props.toast.icon ? props.toast.icon || getLoadingIcon() : null}{props.toast.type !== "loading" ? props.toast.icon || props.icons?.[toastType()] || getAsset(toastType())() : null}</div></Show><div data-content=""><div data-title="" class={_cn(props.classes?.title, props.toast?.classes?.title)}>{props.toast.title}</div><Show when={props.toast.description}><div
data-description=""
class={_cn(
props.descriptionClass,
toastDescriptionClassname(),
props.classes?.description,
props.toast?.classes?.description
)}
>{props.toast.description}</div></Show></div><Show when={props.toast.cancel}><button
data-button
data-cancel
style={props.toast.cancelButtonStyle || props.cancelButtonStyle}
onClick={() => {
deleteToast();
if (props.toast.cancel?.onClick)
props.toast.cancel.onClick();
}}
class={_cn(props.classes?.cancelButton, props.toast?.classes?.cancelButton)}
>{props.toast.cancel.label}</button></Show><Show when={props.toast.action}><button
data-button=""
style={props.toast.actionButtonStyle || props.actionButtonStyle}
onClick={(event) => {
props.toast.action?.onClick(event);
if (event.defaultPrevented)
return;
deleteToast();
}}
class={_cn(props.classes?.actionButton, props.toast?.classes?.actionButton)}
>{props.toast.action.label}</button></Show></>}
>{props.toast.jsx || props.toast.title}</Show></li>;
};
function getDocumentDirection() {
if (typeof window === "undefined")
return "ltr";
if (typeof document === "undefined")
return "ltr";
const dirAttribute = document.documentElement.getAttribute("dir");
if (dirAttribute === "auto" || !dirAttribute)
return window.getComputedStyle(document.documentElement).direction;
return dirAttribute;
class={cn(classNames()?.closeButton, toastClassNames()?.closeButton)}
>
{props.icons?.close ?? <CloseIcon />}
</button>
</Show>
<Show when={(toastType() || props.toast.icon || props.toast.promise) && props.toast.icon !== null && (props.icons?.[toastType()] !== null || props.toast.icon)}>
<div data-icon="" class={cn(classNames()?.icon, toastClassNames()?.icon)}>
{props.toast.promise || props.toast.type === "loading" && !props.toast.icon ? props.toast.icon || getLoadingIcon() : null}
{props.toast.type !== "loading" ? icon() : null}
</div>
</Show>
<div data-content="" class={cn(classNames()?.content, toastClassNames()?.content)}>
<div data-title="" class={cn(classNames()?.title, toastClassNames()?.title)}>
{props.toast.jsx ? props.toast.jsx : resolveContent(props.toast.title)}
</div>
<Show when={props.toast.description}>
<div
data-description=""
class={cn(
descriptionClassName(),
toastDescriptionClassName(),
classNames()?.description,
toastClassNames()?.description
)}
>
{resolveContent(props.toast.description)}
</div>
</Show>
</div>
<Show when={props.toast.cancel}>
{(cancel) => <Show when={!isAction(cancel())} fallback={<button
data-button
data-cancel
style={props.toast.cancelButtonStyle ?? props.cancelButtonStyle}
onClick={(event) => {
const currentCancel = cancel();
if (!dismissible())
return;
currentCancel.onClick?.(event);
deleteToast();
}}
class={cn(classNames()?.cancelButton, toastClassNames()?.cancelButton)}
>
{cancel().label}
</button>}>
{cancel()}
</Show>}
</Show>
<Show when={props.toast.action}>
{(action) => <Show when={!isAction(action())} fallback={<button
data-button
data-action
style={props.toast.actionButtonStyle ?? props.actionButtonStyle}
onClick={(event) => {
const currentAction = action();
currentAction.onClick?.(event);
if (event.defaultPrevented)
return;
deleteToast();
}}
class={cn(classNames()?.actionButton, toastClassNames()?.actionButton)}
>
{action().label}
</button>}>
{action()}
</Show>}
</Show>
</li>;
}
var Toaster = (props) => {
function Toaster(props) {
const propsWithDefaults = mergeProps({

@@ -547,67 +798,86 @@ position: "bottom-right",

theme: "light",
gap: GAP,
visibleToasts: VISIBLE_TOASTS_AMOUNT,
dir: getDocumentDirection()
dir: getDocumentDirection(),
containerAriaLabel: "Notifications"
}, props);
const initialTheme = createToastTheme(propsWithDefaults.theme);
const [toastsStore, setToastsStore] = createStore({ toasts: [] });
const possiblePositions = () => {
return Array.from(
new Set([propsWithDefaults.position].concat(toastsStore.toasts.filter((toast2) => toast2.position).map((toast2) => toast2.position)))
);
};
const filteredToasts = createMemo(() => {
const toasts = toastsStore.toasts;
if (propsWithDefaults.id)
return toasts.filter((toast2) => toast2.toasterId === propsWithDefaults.id);
return toasts.filter((toast2) => !toast2.toasterId);
});
const possiblePositions = createMemo(() => {
return Array.from(/* @__PURE__ */ new Set([propsWithDefaults.position, ...filteredToasts().filter((toast2) => toast2.position).map((toast2) => toast2.position)]));
});
const [heights, setHeights] = createSignal2([]);
const [expanded, setExpanded] = createSignal2(false);
const [interacting, setInteracting] = createSignal2(false);
const [actualTheme, setActualTheme] = createSignal2(initialTheme);
const [lastFocusedElementRef, setLastFocusedElementRef] = createSignal2(null);
const [isFocusWithinRef, setIsFocusWithinRef] = createSignal2(false);
let listRef;
const hotkeyLabel = () => propsWithDefaults.hotkey.join("+").replace(/Key/g, "").replace(/Digit/g, "");
const [lastFocusedElementRef, setLastFocusedElementRef] = createSignal2(null);
const [isFocusedWithinRef, setIsFocusedWithinRef] = createSignal2(false);
const [actualTheme, setActualTheme] = createSignal2(
propsWithDefaults.theme !== "system" ? propsWithDefaults.theme : typeof window !== "undefined" ? window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : "light"
);
const removeToast = (toast2) => setToastsStore("toasts", (toasts) => toasts.filter(({ id }) => id !== toast2.id));
const className = () => mergeClassName(propsWithDefaults.className, propsWithDefaults.class);
const toastOptions = () => propsWithDefaults.toastOptions;
const toastClassNames = () => mergeClassNames(toastOptions()?.classNames, toastOptions()?.classes);
const toastDescriptionClassName = () => mergeDescriptionClassName(toastOptions()?.descriptionClassName, toastOptions()?.descriptionClass);
const toastClassName = () => mergeClassName(toastOptions()?.className, toastOptions()?.class);
const removeToast = (toastToRemove) => {
setToastsStore("toasts", (toasts) => {
if (!toasts.find((toast2) => toast2.id === toastToRemove.id)?.delete)
ToastState.dismiss(toastToRemove.id);
return toasts.filter(({ id }) => id !== toastToRemove.id);
});
};
onMount2(() => {
const unsub = ToastState.subscribe((toast2) => {
if (toast2.dismiss) {
setToastsStore("toasts", produce((_toasts) => {
_toasts.forEach((t) => {
if (t.id === toast2.id)
t.delete = true;
});
}));
const unsubscribe = ToastState.subscribe((toastItem) => {
if (toastItem.dismiss) {
requestAnimationFrame(() => {
setToastsStore("toasts", produce((toasts) => {
toasts.forEach((toast2) => {
if (toast2.id === toastItem.id)
toast2.delete = true;
});
}));
});
return;
}
const changedIndex = toastsStore.toasts.findIndex((t) => t.id === toast2.id);
if (changedIndex !== -1) {
setToastsStore("toasts", [changedIndex], reconcile(toast2));
const nextToast = toastItem;
const indexOfExistingToast = toastsStore.toasts.findIndex((t) => t.id === nextToast.id);
if (indexOfExistingToast !== -1) {
setToastsStore("toasts", indexOfExistingToast, reconcile(nextToast));
return;
}
setToastsStore("toasts", produce((_toasts) => {
_toasts.unshift(toast2);
setToastsStore("toasts", produce((toasts) => {
toasts.unshift(nextToast);
}));
});
onCleanup2(() => {
unsub();
});
onCleanup2(unsubscribe);
});
createEffect(
on(
() => propsWithDefaults.theme,
(theme) => {
if (theme !== "system") {
setActualTheme(theme);
return;
}
if (typeof window === "undefined")
return;
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", ({ matches }) => {
if (matches)
setActualTheme("dark");
else
setActualTheme("light");
});
}
)
);
createEffect(() => {
if (toastsStore.toasts.length <= 1)
const theme = propsWithDefaults.theme;
if (theme !== "system") {
setActualTheme(theme);
return;
}
if (typeof window === "undefined")
return;
const darkMediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
const updateTheme = ({ matches }) => {
setActualTheme(matches ? "dark" : "light");
};
updateTheme(darkMediaQuery);
try {
darkMediaQuery.addEventListener("change", updateTheme);
onCleanup2(() => darkMediaQuery.removeEventListener("change", updateTheme));
} catch {
darkMediaQuery.addListener(updateTheme);
onCleanup2(() => darkMediaQuery.removeListener(updateTheme));
}
});
createEffect(() => {
if (filteredToasts().length <= 1)
setExpanded(false);

@@ -617,3 +887,3 @@ });

const handleKeyDown = (event) => {
const isHotkeyPressed = propsWithDefaults.hotkey.every((key) => event[key] || event.code === key);
const isHotkeyPressed = propsWithDefaults.hotkey.length > 0 && propsWithDefaults.hotkey.every((key) => event[key] || event.code === key);
if (isHotkeyPressed) {

@@ -627,46 +897,44 @@ setExpanded(true);

document.addEventListener("keydown", handleKeyDown);
onCleanup2(() => {
document.removeEventListener("keydown", handleKeyDown);
});
onCleanup2(() => document.removeEventListener("keydown", handleKeyDown));
});
createEffect(
on(
() => listRef,
(ref) => {
if (ref) {
onCleanup2(() => {
if (lastFocusedElementRef()) {
lastFocusedElementRef()?.focus({ preventScroll: true });
setLastFocusedElementRef(null);
setIsFocusedWithinRef(false);
}
});
}
}
)
);
return <Show when={toastsStore.toasts.length > 0}>{
/* Remove item from normal navigation flow, only available via hotkey */
}<section aria-label={`Notifications ${hotkeyLabel()}`} tabIndex={-1}><For2 each={possiblePositions()}>{(position, index) => {
onCleanup2(() => {
if (lastFocusedElementRef()) {
lastFocusedElementRef()?.focus({ preventScroll: true });
setLastFocusedElementRef(null);
setIsFocusWithinRef(false);
}
});
return <section
aria-label={propsWithDefaults.customAriaLabel ?? `${propsWithDefaults.containerAriaLabel} ${hotkeyLabel()}`}
tabIndex={-1}
aria-live="polite"
aria-relevant="additions text"
aria-atomic="false"
data-react-aria-top-layer
>
<For2 each={possiblePositions()}>
{(position, index) => {
const [y, x] = position.split("-");
return <ol
const toastsByPosition = createMemo(() => filteredToasts().filter((toast2) => !toast2.position && index() === 0 || toast2.position === position));
const heightsByPosition = createMemo(() => heights().filter((height) => index() === 0 && !height.position || height.position === position));
return <Show when={filteredToasts().length > 0}>
<ol
tabIndex={-1}
ref={listRef}
dir={propsWithDefaults.dir === "auto" ? getDocumentDirection() : propsWithDefaults.dir}
class={propsWithDefaults.class}
class={className()}
data-sonner-toaster
data-theme={actualTheme()}
data-rich-colors={propsWithDefaults.richColors}
data-sonner-theme={actualTheme()}
data-y-position={y}
data-x-position={x}
style={{
"--front-toast-height": `${heights()[0]?.height}px`,
"--offset": typeof propsWithDefaults.offset === "number" ? `${propsWithDefaults.offset}px` : propsWithDefaults.offset || VIEWPORT_OFFSET,
"--front-toast-height": `${heightsByPosition()[0]?.height ?? 0}px`,
"--width": `${TOAST_WIDTH}px`,
"--gap": `${GAP}px`,
...propsWithDefaults.style
"--gap": `${propsWithDefaults.gap}px`,
...propsWithDefaults.style,
...assignOffset(propsWithDefaults.offset, propsWithDefaults.mobileOffset)
}}
onBlur={(event) => {
if (isFocusedWithinRef() && !event.currentTarget.contains(event.relatedTarget)) {
setIsFocusedWithinRef(false);
if (isFocusWithinRef() && !event.currentTarget.contains(event.relatedTarget)) {
setIsFocusWithinRef(false);
if (lastFocusedElementRef()) {

@@ -679,4 +947,7 @@ lastFocusedElementRef()?.focus({ preventScroll: true });

onFocus={(event) => {
if (!isFocusedWithinRef()) {
setIsFocusedWithinRef(true);
const isNotDismissible = event.target instanceof HTMLElement && event.target.dataset.dismissible === "false";
if (isNotDismissible)
return;
if (!isFocusWithinRef()) {
setIsFocusWithinRef(true);
setLastFocusedElementRef(event.relatedTarget);

@@ -691,26 +962,34 @@ }

}}
onPointerDown={() => {
onDragEnd={() => setExpanded(false)}
onPointerDown={(event) => {
const isNotDismissible = event.target instanceof HTMLElement && event.target.dataset.dismissible === "false";
if (isNotDismissible)
return;
setInteracting(true);
}}
onPointerUp={() => setInteracting(false)}
><For2 each={toastsStore.toasts.filter((toast2) => !toast2.position && index() === 0 || toast2.position === position)}>{(toast2, index2) => <Toast
index={index2()}
>
<For2 each={toastsByPosition()}>
{(toastItem, toastIndex) => <Toast
icons={propsWithDefaults.icons}
toast={toast2}
duration={propsWithDefaults.toastOptions?.duration ?? props.duration}
class={propsWithDefaults.toastOptions?.class}
classes={propsWithDefaults.toastOptions?.classes}
cancelButtonStyle={propsWithDefaults.toastOptions?.cancelButtonStyle}
actionButtonStyle={propsWithDefaults.toastOptions?.actionButtonStyle}
descriptionClass={propsWithDefaults.toastOptions?.descriptionClass}
index={toastIndex()}
toast={toastItem}
defaultRichColors={propsWithDefaults.richColors}
duration={toastOptions()?.duration ?? propsWithDefaults.duration}
class={toastClassName()}
descriptionClassName={toastDescriptionClassName()}
invert={Boolean(propsWithDefaults.invert)}
visibleToasts={propsWithDefaults.visibleToasts}
closeButton={Boolean(propsWithDefaults.closeButton)}
closeButton={toastOptions()?.closeButton ?? propsWithDefaults.closeButton ?? false}
interacting={interacting()}
position={propsWithDefaults.position}
style={propsWithDefaults.toastOptions?.style}
unstyled={propsWithDefaults.toastOptions?.unstyled}
position={position}
style={toastOptions()?.style}
unstyled={toastOptions()?.unstyled}
classNames={toastClassNames()}
cancelButtonStyle={toastOptions()?.cancelButtonStyle}
actionButtonStyle={toastOptions()?.actionButtonStyle}
closeButtonAriaLabel={toastOptions()?.closeButtonAriaLabel}
removeToast={removeToast}
toasts={toastsStore.toasts}
heights={heights()}
toasts={toastsByPosition()}
heights={heightsByPosition()}
setHeights={setHeights}

@@ -720,9 +999,16 @@ expandByDefault={Boolean(propsWithDefaults.expand)}

expanded={expanded()}
swipeDirections={propsWithDefaults.swipeDirections}
pauseWhenPageIsHidden={propsWithDefaults.pauseWhenPageIsHidden}
/>}</For2></ol>;
}}</For2></section></Show>;
};
/>}
</For2>
</ol>
</Show>;
}}
</For2>
</section>;
}
export {
Toaster,
toast
toast,
useSonner
};

@@ -729,0 +1015,0 @@ /*!

{
"name": "solid-sonner",
"type": "module",
"version": "0.2.8",
"version": "0.3.0",
"private": false,
"packageManager": "pnpm@9.2.0",
"description": "An opinionated toast component for Solid.",

@@ -46,14 +45,2 @@ "author": "Robert Soriano <sorianorobertc@gmail.com>",

"browser": {},
"scripts": {
"dev": "vite serve dev",
"build": "tsup",
"dev:build": "vite build dev",
"test": "playwright test",
"prepublishOnly": "pnpm build",
"update-deps": "pnpm up -Li",
"typecheck": "tsc --noEmit",
"lint": "eslint .",
"release": "bumpp && npm publish",
"lint:fix": "eslint . --fix"
},
"peerDependencies": {

@@ -64,18 +51,18 @@ "solid-js": "^1.6.0"

"@antfu/eslint-config-ts": "^0.43.1",
"@playwright/test": "^1.44.1",
"@types/node": "^20.14.2",
"bumpp": "^9.4.1",
"@changesets/cli": "^2.30.0",
"@playwright/test": "^1.58.2",
"@types/node": "^20.19.37",
"copy-to-clipboard": "^3.3.3",
"esbuild": "^0.21.4",
"esbuild": "^0.21.5",
"esbuild-plugin-solid": "^0.6.0",
"eslint": "^8.56.0",
"eslint-plugin-solid": "^0.14.0",
"highlight.js": "^11.9.0",
"jsdom": "^24.1.0",
"solid-js": "^1.8.17",
"tsup": "^8.1.0",
"eslint-plugin-solid": "^0.14.5",
"highlight.js": "^11.11.1",
"jsdom": "^24.1.3",
"solid-js": "^1.9.11",
"tsup": "^8.5.1",
"tsup-preset-solid": "^2.2.0",
"typescript": "^5.4.5",
"vite": "^5.2.13",
"vite-plugin-solid": "^2.10.2"
"typescript": "^5.9.3",
"vite": "^5.4.21",
"vite-plugin-solid": "^2.11.10"
},

@@ -90,3 +77,14 @@ "eslintConfig": {

]
},
"scripts": {
"dev": "vite serve dev",
"build": "tsup",
"dev:build": "vite build dev",
"test": "playwright test",
"update-deps": "pnpm up -Li",
"typecheck": "tsc --noEmit",
"lint": "eslint .",
"release": "changeset publish",
"lint:fix": "eslint . --fix"
}
}
}
+101
-252

@@ -11,8 +11,6 @@ <p>

Based on the React [implementation](https://sonner.emilkowal.ski/).
This package tracks the React [Sonner](https://sonner.emilkowal.ski/) API as closely as possible while keeping the implementation Solid-friendly.
## Quick start
## Install
Install it:
```bash

@@ -26,3 +24,3 @@ npm i solid-sonner

Add `<Toaster />` to your app, it will be the place where all your toasts will be rendered. After that you can use `toast()` from anywhere in your app.
## Quick start

@@ -32,5 +30,3 @@ ```tsx

// ...
function App() {
export default function App() {
return (

@@ -45,59 +41,28 @@ <div>

## Types
## API
### Default
Exports:
Most basic toast. You can customize it (and any other type) by passing an options object as the second argument.
- `Toaster`
- `toast`
- `useSonner`
- types: `Action`, `ExternalToast`, `ToastClassnames`, `ToastT`, `ToastToDismiss`, `ToasterProps`
```jsx
### Toast types
```tsx
toast('Event has been created')
```
With custom icon and description:
```jsx
toast('Event has been created', {
description: 'Monday, January 3rd at 6:00pm',
icon: <MyIcon />,
})
```
### Success
Renders a checkmark icon in front of the message.
```jsx
toast.success('Event has been created')
```
### Info
Renders an error icon in front of the message.
```jsx
toast.info('Event has new information')
```
### Warning
Renders an error icon in front of the message.
```jsx
toast.warning('Event has warning')
```
### Error
Renders an error icon in front of the message.
```jsx
toast.error('Event has not been created')
toast.loading('Loading data')
```
### Action
With description, icon, and actions:
Renders a button.
```jsx
```tsx
toast('Event has been created', {
description: 'Monday, January 3rd at 6:00pm',
icon: <MyIcon />,
action: {

@@ -107,13 +72,14 @@ label: 'Undo',

},
cancel: {
label: 'Cancel',
},
})
```
### Promise
### Promise toasts
Starts in a loading state and will update automatically after the promise resolves or fails.
```jsx
toast.promise(() => new Promise(resolve => setTimeout(resolve, 2000)), {
loading: 'Loading',
success: 'Success',
```tsx
toast.promise(fetchData(), {
loading: 'Loading...',
success: data => `${data.name} has been added!`,
error: 'Error',

@@ -123,52 +89,34 @@ })

You can pass a function to the success/error messages to incorporate the result/error of the promise.
Extended results are supported too:
```jsx
toast.promise(promise, {
loading: 'Loading...',
success: (data) => {
return `${data.name} has been added!`
},
error: 'Error',
```tsx
toast.promise(saveProject(), {
loading: 'Saving...',
success: result => ({
message: 'Project saved',
description: result.id,
}),
error: error => ({
message: 'Save failed',
description: String(error),
}),
})
```
### Loading
### Updating and dismissing
Renders a toast with a loading spinner. Useful when you want to handle various states yourself instead of using a promise toast.
```tsx
const id = toast('Uploading...', { duration: Number.POSITIVE_INFINITY })
```jsx
toast.loading('Loading data')
toast.success('Done', { id })
toast.dismiss(id)
toast.dismiss()
```
### Custom JSX
### Headless custom toasts
You can pass jsx as the first argument instead of a string to render custom jsx while maintaining default styling. You can use the headless version below for a custom, unstyled toast.
```jsx
toast(<div>A custom toast with default styling</div>)
```
### Updating a toast
You can update a toast by using the `toast` function and passing it the id of the toast you want to update, the rest stays the same.
```jsx
const toastId = toast('Sonner')
toast.success('Toast has been updated', {
id: toastId,
})
```
## Customization
### Headless
You can use `toast.custom` to render an unstyled toast with custom jsx while maintaining the functionality.
```jsx
toast.custom(t => (
```tsx
toast.custom(id => (
<div>
This is a custom component <button onClick={() => toast.dismiss(t)}>close</button>
Custom toast <button onClick={() => toast.dismiss(id)}>close</button>
</div>

@@ -178,66 +126,37 @@ ))

### Theme
### Read current state
You can change the theme using the `theme` prop. Default theme is light.
```tsx
const { toasts } = useSonner()
```jsx
<Toaster theme="dark" />
toast.getToasts()
toast.getHistory()
```
### Position
## Toaster props
You can change the position through the `position` prop on the `<Toaster />` component. Default is `bottom-right`.
```jsx
// Available positions
// top-left, top-center, top-right, bottom-left, bottom-center, bottom-right
<Toaster position="top-center" />
```
### Expanded
Toasts can also be expanded by default through the `expand` prop. You can also change the amount of visible toasts which is 3 by default.
```jsx
<Toaster expand visibleToasts={9} />
```
### Styling
Styling can be done globally via `toastOptions`, this way every toast will have the same styling.
```jsx
<Toaster
toastOptions={{ style: { background: 'red' }, class: 'my-toast', descriptionClass: 'my-toast-description' }}
/>
```
You can also use the same props when calling toast to style a specific toast.
```jsx
toast('Event has been created', {
style: {
background: 'red',
},
class: 'my-toast',
descriptionClass: 'my-toast-description',
})
```
### Tailwind CSS
The preferred way to style the toasts with tailwind is by using the `unstyled` prop. That will give you an unstyled toast which you can then style with tailwind.
```tsx
<Toaster
theme="system"
position="top-right"
richColors
closeButton
expand
visibleToasts={5}
duration={5000}
gap={14}
offset={32}
mobileOffset={{ bottom: 24, left: 16, right: 16 }}
hotkey={['altKey', 'KeyT']}
dir="auto"
swipeDirections={['top', 'right']}
containerAriaLabel="Notifications"
toastOptions={{
unstyled: true,
classes: {
toast: 'bg-blue-400',
title: 'text-red-400',
description: 'text-red-400',
actionButton: 'bg-zinc-400',
cancelButton: 'bg-orange-400',
closeButton: 'bg-lime-400',
className: 'my-toast',
descriptionClassName: 'my-toast-description',
closeButtonAriaLabel: 'Close notification',
classNames: {
toast: 'toast',
title: 'title',
description: 'description',
},

@@ -248,19 +167,21 @@ }}

You can do the same when calling `toast()`.
Legacy aliases from older `solid-sonner` versions still work for compatibility:
- `class` -> `className`
- `classes` -> `classNames`
- `descriptionClass` -> `descriptionClassName`
## Multiple toasters
```tsx
toast('Hello World', {
unstyled: true,
classes: {
toast: 'bg-blue-400',
title: 'text-red-400 text-2xl',
description: 'text-red-400',
actionButton: 'bg-zinc-400',
cancelButton: 'bg-orange-400',
closeButton: 'bg-lime-400',
},
})
<>
<Toaster />
<Toaster id="sidebar" position="top-left" />
</>
toast('Global toast')
toast('Sidebar toast', { toasterId: 'sidebar' })
```
Styling per toast type is also possible.
## Tailwind / unstyled mode

@@ -271,7 +192,9 @@ ```tsx

unstyled: true,
classes: {
error: 'bg-red-400',
success: 'text-green-400',
warning: 'text-yellow-400',
info: 'bg-blue-400',
classNames: {
toast: 'bg-blue-500 text-white',
title: 'font-semibold',
description: 'text-blue-100',
actionButton: 'bg-white text-blue-700',
cancelButton: 'bg-blue-700 text-white',
closeButton: 'bg-white text-black',
},

@@ -282,84 +205,10 @@ }}

### Close button
## Notes
Add a close button to all toasts that shows on hover by adding the `closeButton` prop.
- `pauseWhenPageIsHidden` is available and defaults to Sonner-like hidden-page pausing behavior
- Per-toast `closeButton`, `dismissible`, `richColors`, `testId`, and `toasterId` are supported
- `action` respects `event.preventDefault()` and will keep the toast open
```jsx
<Toaster closeButton />
```
### Rich colors
You can make error and success state more colorful by adding the `richColors` prop.
```jsx
<Toaster richColors />
```
### Custom offset
Offset from the edges of the screen.
```jsx
<Toaster offset="80px" />
```
### Programmatically remove toast
To remove a toast programmatically use `toast.dismiss(id)`.
```jsx
const toastId = toast('Event has been created')
toast.dismiss(toastId)
```
You can also use the dismiss method without the id to dismiss all toasts.
```jsx
// Removes all toasts
toast.dismiss()
```
### Duration
You can change the duration of each toast by using the `duration` property, or change the duration of all toasts like this:
```jsx
<Toaster duration={10000} />
```
```jsx
toast('Event has been created', {
duration: 10000,
})
// Persisent toast
toast('Event has been created', {
duration: Number.POSITIVE_INFINITY,
})
```
### On Close Callback
You can pass `onDismiss` and `onAutoClose` callbacks. `onDismiss` gets fired when either the close button gets clicked or the toast is swiped. `onAutoClose` fires when the toast disappears automatically after it's timeout (`duration` prop).
```jsx
toast('Event has been created', {
onDismiss: t => console.log(`Toast with id ${t.id} has been dismissed`),
onAutoClose: t => console.log(`Toast with id ${t.id} has been closed automatically`),
})
```
## Keyboard focus
You can focus on the toast area by pressing ⌥/alt + T. You can override it by providing an array of event.code values for each key.
```jsx
<Toaster hotkey={['KeyC']} />
```
## License
MIT