UNPKG

ngx-sonner

Version:

An opinionated toast component for Angular.

1 lines 67.1 kB
{"version":3,"file":"ngx-sonner.mjs","sources":["../../../../libs/ngx-sonner/src/lib/state.ts","../../../../libs/ngx-sonner/src/lib/icon.component.ts","../../../../libs/ngx-sonner/src/lib/internal/constants.ts","../../../../libs/ngx-sonner/src/lib/loader.component.ts","../../../../libs/ngx-sonner/src/lib/pipes/toast-filter.pipe.ts","../../../../libs/ngx-sonner/src/lib/internal/cn.ts","../../../../libs/ngx-sonner/src/lib/pipes/as-component.pipe.ts","../../../../libs/ngx-sonner/src/lib/pipes/is-string.pipe.ts","../../../../libs/ngx-sonner/src/lib/toast.component.ts","../../../../libs/ngx-sonner/src/lib/toaster.component.ts","../../../../libs/ngx-sonner/src/ngx-sonner.ts"],"sourcesContent":["import { signal, Type } from '@angular/core';\nimport {\n ExternalToast,\n HeightT,\n PromiseData,\n PromiseT,\n ToastT,\n ToastTypes,\n} from './types';\n\nlet toastsCounter = 0;\n\nfunction createToastState() {\n const toasts = signal<ToastT[]>([]);\n const heights = signal<HeightT[]>([]);\n\n function addToast(data: ToastT) {\n toasts.update(prev => [data, ...prev]);\n }\n\n function create(\n data: ExternalToast & {\n message?: string | Type<unknown>;\n type?: ToastTypes;\n promise?: PromiseT;\n }\n ) {\n const { message, ...rest } = data;\n const id =\n typeof data?.id === 'number' || (data.id && data.id?.length > 0)\n ? data.id\n : toastsCounter++;\n\n const dismissible = data.dismissible ?? true;\n const type = data.type ?? 'default';\n\n const alreadyExists = toasts().find(toast => toast.id === id);\n\n if (alreadyExists) {\n toasts.update(prev =>\n prev.map(toast => {\n if (toast.id === id) {\n return {\n ...toast,\n ...data,\n id,\n title: message,\n dismissible,\n type,\n updated: true,\n };\n } else return { ...toast, updated: false };\n })\n );\n } else {\n addToast({ ...rest, id, title: message, dismissible: dismissible, type });\n }\n\n return id;\n }\n\n function dismiss(id?: number | string) {\n if (id === undefined) {\n toasts.set([]);\n return;\n }\n toasts.update(prev => prev.filter(toast => toast.id !== id));\n\n return id;\n }\n\n function message(message: string | Type<unknown>, data?: ExternalToast) {\n return create({ ...data, type: 'default', message });\n }\n\n function error(message: string | Type<unknown>, data?: ExternalToast) {\n return create({ ...data, type: 'error', message });\n }\n\n function success(message: string | Type<unknown>, data?: ExternalToast) {\n return create({ ...data, type: 'success', message });\n }\n\n function info(message: string | Type<unknown>, data?: ExternalToast) {\n return create({ ...data, type: 'info', message });\n }\n\n function warning(message: string | Type<unknown>, data?: ExternalToast) {\n return create({ ...data, type: 'warning', message });\n }\n\n function loading(message: string | Type<unknown>, data?: ExternalToast) {\n return create({ ...data, type: 'loading', message });\n }\n\n function promise<ToastData>(\n promise: PromiseT<ToastData>,\n data?: PromiseData<ToastData>\n ) {\n if (!data) return;\n\n let id: string | number | undefined = undefined;\n if (data.loading !== undefined) {\n id = create({\n ...data,\n promise,\n type: 'loading',\n message: data.loading,\n });\n }\n\n const p = promise instanceof Promise ? promise : promise();\n\n let shouldDismiss = id !== undefined;\n\n p.then(response => {\n // @ts-expect-error: Incorrect response type\n if (response && typeof response.ok === 'boolean' && !response.ok) {\n shouldDismiss = false;\n\n const message =\n typeof data.error === 'function'\n ? // @ts-expect-error: TODO: Better function checking\n data.error(`HTTP error! status: ${response.status}`)\n : data.error;\n create({ id, type: 'error', message });\n } else if (data.success !== undefined) {\n shouldDismiss = false;\n\n const message =\n typeof data.success === 'function'\n ? // @ts-expect-error: TODO: Better function checking\n data.success(response)\n : data.success;\n create({ id, type: 'success', message });\n }\n })\n .catch(error => {\n if (data.error !== undefined) {\n shouldDismiss = false;\n const message =\n // @ts-expect-error: TODO: Better function checking\n typeof data.error === 'function' ? data.error(error) : data.error;\n create({ id, type: 'error', message });\n }\n })\n .finally(() => {\n if (shouldDismiss) {\n // Toast is still in load state (and will be indefinitely — dismiss it)\n dismiss(id);\n id = undefined;\n }\n\n data.finally?.();\n });\n\n return id;\n }\n\n function custom<T>(component: Type<T>, data?: ExternalToast) {\n const id = data?.id ?? toastsCounter++;\n create({ component, id, ...data });\n\n return id;\n }\n\n function removeHeight(id: number | string) {\n heights.update(prev => prev.filter(height => height.toastId !== id));\n }\n\n function addHeight(height: HeightT) {\n heights.update(prev => [height, ...prev].sort(sortHeights));\n }\n\n const sortHeights = (a: HeightT, b: HeightT) =>\n toasts().findIndex(t => t.id === a.toastId) -\n toasts().findIndex(t => t.id === b.toastId);\n\n function reset() {\n toasts.set([]);\n heights.set([]);\n }\n\n return {\n //methods\n create,\n addToast,\n dismiss,\n message,\n error,\n success,\n info,\n warning,\n loading,\n promise,\n custom,\n removeHeight,\n addHeight,\n reset,\n // signals\n toasts: toasts.asReadonly(),\n heights: heights.asReadonly(),\n };\n}\n\nexport const toastState = createToastState();\n\n// bind this to the toast function\nfunction toastFunction(message: string | Type<unknown>, data?: ExternalToast) {\n return toastState.create({\n message,\n ...data,\n });\n}\n\nconst basicToast = toastFunction;\n\nexport const toast = Object.assign(basicToast, {\n success: toastState.success,\n info: toastState.info,\n warning: toastState.warning,\n error: toastState.error,\n custom: toastState.custom,\n message: toastState.message,\n promise: toastState.promise,\n dismiss: toastState.dismiss,\n loading: toastState.loading,\n});\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { ToastTypes } from './types';\n\n@Component({\n selector: 'ngx-sonner-icon',\n template: `\n @switch (type()) {\n @case ('success') {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n height=\"20\"\n width=\"20\">\n <path\n fill-rule=\"evenodd\"\n 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\"\n clip-rule=\"evenodd\" />\n </svg>\n }\n @case ('error') {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n height=\"20\"\n width=\"20\">\n <path\n fill-rule=\"evenodd\"\n 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\"\n clip-rule=\"evenodd\" />\n </svg>\n }\n @case ('info') {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n height=\"20\"\n width=\"20\">\n <path\n fill-rule=\"evenodd\"\n 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\"\n clip-rule=\"evenodd\" />\n </svg>\n }\n @case ('warning') {\n <svg\n viewBox=\"0 0 64 64\"\n fill=\"currentColor\"\n height=\"20\"\n width=\"20\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M32.427,7.987c2.183,0.124 4,1.165 5.096,3.281l17.936,36.208c1.739,3.66 -0.954,8.585 -5.373,8.656l-36.119,0c-4.022,-0.064 -7.322,-4.631 -5.352,-8.696l18.271,-36.207c0.342,-0.65 0.498,-0.838 0.793,-1.179c1.186,-1.375 2.483,-2.111 4.748,-2.063Zm-0.295,3.997c-0.687,0.034 -1.316,0.419 -1.659,1.017c-6.312,11.979 -12.397,24.081 -18.301,36.267c-0.546,1.225 0.391,2.797 1.762,2.863c12.06,0.195 24.125,0.195 36.185,0c1.325,-0.064 2.321,-1.584 1.769,-2.85c-5.793,-12.184 -11.765,-24.286 -17.966,-36.267c-0.366,-0.651 -0.903,-1.042 -1.79,-1.03Z\" />\n <path\n d=\"M33.631,40.581l-3.348,0l-0.368,-16.449l4.1,0l-0.384,16.449Zm-3.828,5.03c0,-0.609 0.197,-1.113 0.592,-1.514c0.396,-0.4 0.935,-0.601 1.618,-0.601c0.684,0 1.223,0.201 1.618,0.601c0.395,0.401 0.593,0.905 0.593,1.514c0,0.587 -0.193,1.078 -0.577,1.473c-0.385,0.395 -0.929,0.593 -1.634,0.593c-0.705,0 -1.249,-0.198 -1.634,-0.593c-0.384,-0.395 -0.576,-0.886 -0.576,-1.473Z\" />\n </svg>\n }\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class IconComponent {\n type = input<ToastTypes>('default');\n}\n","import { ToastClassnames } from '../types';\n\n// Visible toasts amount\nexport const VISIBLE_TOASTS_AMOUNT = 3;\n\n// Viewport padding\nexport const VIEWPORT_OFFSET = '32px';\n\n// Default lifetime of a toasts (in ms)\nexport const TOAST_LIFETIME = 4000;\n\n// Default toast width\nexport const TOAST_WIDTH = 356;\n\n// Default gap between toasts\nexport const GAP = 14;\n\n// Threshold to dismiss a toast\nexport const SWIPE_THRESHOLD = 20;\n\n// Equal to exit animation duration\nexport const TIME_BEFORE_UNMOUNT = 200;\n\nexport const defaultClasses: ToastClassnames = {\n toast: '',\n title: '',\n description: '',\n loader: '',\n closeButton: '',\n cancelButton: '',\n actionButton: '',\n action: '',\n warning: '',\n error: '',\n success: '',\n default: '',\n info: '',\n loading: '',\n};\n","import {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n input,\n} from '@angular/core';\n\n@Component({\n selector: 'ngx-sonner-loader',\n template: `\n <div class=\"sonner-loading-wrapper\" [attr.data-visible]=\"isVisible()\">\n <div class=\"sonner-spinner\">\n @for (_ of bars; track $index) {\n <div class=\"sonner-loading-bar\"></div>\n }\n </div>\n </div>\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class LoaderComponent {\n isVisible = input.required({ transform: booleanAttribute });\n bars = Array(12).fill(0);\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { Position, ToastT } from '../types';\n\n@Pipe({ name: 'toastFilter' })\nexport class ToastFilterPipe implements PipeTransform {\n transform(toasts: ToastT[], index: number, position: Position): ToastT[] {\n return toasts.filter(\n toast => (!toast.position && index === 0) || toast.position === position\n );\n }\n}\n","export function cn(...classes: (string | undefined)[]) {\n return classes.filter(Boolean).join(' ');\n}\n","import { Pipe, PipeTransform, Type } from '@angular/core';\n\n@Pipe({ name: 'asComponent' })\nexport class AsComponentPipe implements PipeTransform {\n transform(value: unknown): Type<unknown> {\n return value as Type<unknown>;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\n\n@Pipe({ name: 'isString' })\nexport class IsStringPipe implements PipeTransform {\n transform(value: unknown): boolean {\n return typeof value === 'string';\n }\n}\n","import { NgComponentOutlet } from '@angular/common';\nimport {\n afterRenderEffect,\n AfterViewInit,\n ChangeDetectionStrategy,\n Component,\n computed,\n effect,\n ElementRef,\n input,\n linkedSignal,\n OnDestroy,\n signal,\n viewChild,\n} from '@angular/core';\nimport { cn } from './internal/cn';\nimport {\n defaultClasses,\n GAP,\n SWIPE_THRESHOLD,\n TIME_BEFORE_UNMOUNT,\n TOAST_LIFETIME,\n} from './internal/constants';\nimport { AsComponentPipe } from './pipes/as-component.pipe';\nimport { IsStringPipe } from './pipes/is-string.pipe';\nimport { toastState } from './state';\nimport { ToastProps } from './types';\n\n@Component({\n selector: 'ngx-sonner-toast',\n imports: [NgComponentOutlet, IsStringPipe, AsComponentPipe],\n template: `\n <li\n #toastRef\n data-sonner-toast\n [attr.aria-live]=\"toast().important ? 'assertive' : 'polite'\"\n aria-atomic=\"true\"\n role=\"status\"\n tabindex=\"0\"\n [class]=\"toastClasses()\"\n [attr.data-styled]=\"\n !(toast().component || toast().unstyled || unstyled())\n \"\n [attr.data-mounted]=\"mounted()\"\n [attr.data-promise]=\"!!toast().promise\"\n [attr.data-removed]=\"removed()\"\n [attr.data-visible]=\"isVisible()\"\n [attr.data-y-position]=\"coords()[0]\"\n [attr.data-x-position]=\"coords()[1]\"\n [attr.data-index]=\"index()\"\n [attr.data-front]=\"isFront()\"\n [attr.data-swiping]=\"swiping()\"\n [attr.data-dismissible]=\"toast().dismissible\"\n [attr.data-type]=\"toastType()\"\n [attr.data-invert]=\"invert()\"\n [attr.data-swipe-out]=\"swipeOut()\"\n [attr.data-expanded]=\"expanded() || (expandByDefault() && mounted())\"\n [style]=\"toastStyle()\"\n (pointerdown)=\"onPointerDown($event)\"\n (pointerup)=\"onPointerUp()\"\n (pointermove)=\"onPointerMove($event)\">\n @if (closeButton() && !toast().component) {\n <button\n aria-label=\"Close toast\"\n [attr.data-disabled]=\"disabled()\"\n data-close-button\n (click)=\"onCloseButtonClick()\"\n [class]=\"cn(classes().closeButton, toast().classes?.closeButton)\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n }\n\n @if (toast().component) {\n <ng-container\n *ngComponentOutlet=\"\n toast().component | asComponent;\n inputs: toast().componentProps\n \" />\n } @else {\n @if (toastType() !== 'default' || toast().icon || toast().promise) {\n <div data-icon>\n @if (toastType() === 'loading' && !toast().icon) {\n <ng-content select=\"[loading-icon]\" />\n }\n @if (toast().icon) {\n <ng-container\n *ngComponentOutlet=\"\n toast().icon | asComponent;\n inputs: toast().componentProps\n \" />\n } @else {\n @switch (toastType()) {\n @case ('success') {\n <ng-content select=\"[success-icon]\" />\n }\n @case ('error') {\n <ng-content select=\"[error-icon]\" />\n }\n @case ('warning') {\n <ng-content select=\"[warning-icon]\" />\n }\n @case ('info') {\n <ng-content select=\"[info-icon]\" />\n }\n }\n }\n </div>\n }\n <div data-content>\n @if (toast().title; as title) {\n <div\n data-title\n [class]=\"cn(classes().title, toast().classes?.title)\">\n @if (title | isString) {\n {{ toast().title }}\n } @else {\n <ng-container\n *ngComponentOutlet=\"\n title | asComponent;\n inputs: toast().componentProps\n \" />\n }\n </div>\n }\n @if (toast().description; as description) {\n <div\n data-description\n [class]=\"\n cn(\n descriptionClass(),\n toastDescriptionClass(),\n classes().description,\n toast().classes?.description\n )\n \">\n @if (description | isString) {\n {{ toast().description }}\n } @else {\n <ng-container\n *ngComponentOutlet=\"\n description | asComponent;\n inputs: toast().componentProps\n \" />\n }\n </div>\n }\n </div>\n @if (toast().cancel; as cancel) {\n <button\n data-button\n data-cancel\n [style]=\"cancelButtonStyle() ?? toast().cancelButtonStyle\"\n [class]=\"cn(classes().cancelButton, toast().classes?.cancelButton)\"\n (click)=\"onCancelClick()\">\n {{ cancel.label }}\n </button>\n }\n @if (toast().action; as action) {\n <button\n data-button\n [style]=\"actionButtonStyle() ?? toast().actionButtonStyle\"\n [class]=\"cn(classes().actionButton, toast().classes?.actionButton)\"\n (click)=\"onActionClick($event)\">\n {{ action.label }}\n </button>\n }\n }\n </li>\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ToastComponent implements AfterViewInit, OnDestroy {\n protected readonly cn = cn;\n\n toasts = toastState.toasts;\n heights = toastState.heights;\n removeHeight = toastState.removeHeight;\n addHeight = toastState.addHeight;\n dismiss = toastState.dismiss;\n\n toast = input.required<ToastProps['toast']>();\n index = input.required<ToastProps['index']>();\n expanded = input.required<ToastProps['expanded']>();\n _invert = input.required<ToastProps['invert']>({ alias: 'invert' });\n position = input.required<ToastProps['position']>();\n visibleToasts = input.required<ToastProps['visibleToasts']>();\n expandByDefault = input.required<ToastProps['expandByDefault']>();\n _closeButton = input.required<ToastProps['closeButton']>({\n alias: 'closeButton',\n });\n interacting = input.required<ToastProps['interacting']>();\n cancelButtonStyle = input<ToastProps['cancelButtonStyle']>();\n actionButtonStyle = input<ToastProps['actionButtonStyle']>();\n duration = input<ToastProps['duration']>(TOAST_LIFETIME);\n descriptionClass = input<ToastProps['descriptionClass']>('');\n _classes = input<ToastProps['classes']>({}, { alias: 'classes' });\n unstyled = input<ToastProps['unstyled']>(false);\n _class = input('', { alias: 'class' });\n _style = input<Record<string, string>>({}, { alias: 'style' });\n\n mounted = signal(false);\n removed = signal(false);\n swiping = signal(false);\n swipeOut = signal(false);\n offsetBeforeRemove = signal(0);\n initialHeight = signal(0);\n\n toastRef = viewChild.required<ElementRef<HTMLLIElement>>('toastRef');\n\n classes: any = computed(() => ({\n ...defaultClasses,\n ...this._classes(),\n }));\n\n isFront = computed(() => this.index() === 0);\n isVisible = computed(() => this.index() + 1 <= this.visibleToasts());\n toastType = computed(() => this.toast().type ?? 'default');\n toastClass = computed(() => this.toast().class ?? '');\n toastPosition = computed(() => this.toast().position ?? this.position());\n toastDescriptionClass = computed(() => this.toast().descriptionClass ?? '');\n\n heightIndex = computed(() =>\n this.heights().findIndex(height => height.toastId === this.toast().id)\n );\n\n offset = linkedSignal({\n source: () => ({\n heightIndex: this.heightIndex(),\n toastsHeightBefore: this.toastsHeightBefore(),\n }),\n computation: ({ heightIndex, toastsHeightBefore }) =>\n Math.round(heightIndex * GAP + toastsHeightBefore),\n });\n\n closeTimerStartTimeRef = 0;\n lastCloseTimerStartTimeRef = 0;\n pointerStartRef: { x: number; y: number } | null = null;\n\n coords = computed(() => this.toastPosition().split('-'));\n toastsHeightBefore = computed(() =>\n this.heights().reduce((prev, curr, reducerIndex) => {\n if (reducerIndex >= this.heightIndex()) return prev;\n return prev + curr.height;\n }, 0)\n );\n invert = computed(() => this.toast().invert ?? this._invert());\n closeButton = computed(() => this.toast().closeButton ?? this._closeButton());\n disabled = computed(() => this.toastType() === 'loading');\n\n timeoutId: ReturnType<typeof setTimeout> | undefined;\n remainingTime = 0;\n\n isPromiseLoadingOrInfiniteDuration = computed(\n () =>\n (this.toast().promise && this.toastType() === 'loading') ||\n this.toast().duration === Number.POSITIVE_INFINITY\n );\n\n toastClasses = computed(() =>\n cn(\n this._class(),\n this.toastClass(),\n this.classes().toast,\n this.toast().classes?.toast,\n this.classes()[this.toastType()],\n this.toast().classes?.[this.toastType()]\n )\n );\n toastStyle = computed(() => ({\n '--index': `${this.index()}`,\n '--toasts-before': `${this.index()}`,\n '--z-index': `${this.toasts().length - this.index()}`,\n '--offset': `${this.removed() ? this.offsetBeforeRemove() : this.offset()}px`,\n '--initial-height': this.expandByDefault()\n ? 'auto'\n : `${this.initialHeight()}px`,\n ...this._style(),\n }));\n\n constructor() {\n effect(() => {\n if (this.toast().updated) {\n // if the toast has been updated after the initial render,\n // we want to reset the timer and set the remaining time to the\n // new duration\n clearTimeout(this.timeoutId);\n this.remainingTime =\n this.toast().duration ?? this.duration() ?? TOAST_LIFETIME;\n this.startTimer();\n }\n });\n\n afterRenderEffect(onCleanup => {\n if (!this.isPromiseLoadingOrInfiniteDuration()) {\n if (this.expanded() || this.interacting()) {\n this.pauseTimer();\n } else {\n this.startTimer();\n }\n }\n\n onCleanup(() => clearTimeout(this.timeoutId));\n });\n\n effect(() => {\n if (this.toast().delete) {\n this.deleteToast();\n }\n });\n }\n\n ngAfterViewInit() {\n this.remainingTime =\n this.toast().duration ?? this.duration() ?? TOAST_LIFETIME;\n this.mounted.set(true);\n const height = this.toastRef().nativeElement.getBoundingClientRect().height;\n this.initialHeight.set(height);\n this.addHeight({ toastId: this.toast().id, height });\n }\n\n ngOnDestroy() {\n clearTimeout(this.timeoutId);\n this.removeHeight(this.toast().id);\n }\n\n deleteToast() {\n this.removed.set(true);\n this.offsetBeforeRemove.set(this.offset());\n\n this.removeHeight(this.toast().id);\n\n setTimeout(() => {\n this.dismiss(this.toast().id);\n }, TIME_BEFORE_UNMOUNT);\n }\n\n // If toast's duration changes, it will be out of sync with the\n // remainingAtTimeout, so we know we need to restart the timer\n // with the new duration\n\n // Pause the timer on each hover\n pauseTimer() {\n if (this.lastCloseTimerStartTimeRef < this.closeTimerStartTimeRef) {\n // Get the elapsed time since the timer started\n const elapsedTime = new Date().getTime() - this.closeTimerStartTimeRef;\n this.remainingTime = this.remainingTime - elapsedTime;\n }\n\n this.lastCloseTimerStartTimeRef = new Date().getTime();\n }\n\n startTimer() {\n this.closeTimerStartTimeRef = new Date().getTime();\n // Let the toast know it has started\n this.timeoutId = setTimeout(() => {\n this.toast().onAutoClose?.(this.toast());\n this.deleteToast();\n }, this.remainingTime);\n }\n\n onPointerDown(event: PointerEvent) {\n if (this.disabled() || !this.toast().dismissible) return;\n\n this.offsetBeforeRemove.set(this.offset());\n const target = event.target as HTMLElement;\n // Ensure we maintain correct pointer capture even when going outside the toast (e.g. when swiping)\n target.setPointerCapture(event.pointerId);\n if (target.tagName === 'BUTTON') {\n return;\n }\n this.swiping.set(true);\n this.pointerStartRef = { x: event.clientX, y: event.clientY };\n }\n\n onPointerUp() {\n if (this.swipeOut() || !this.toast().dismissible) return;\n\n this.pointerStartRef = null;\n const swipeAmount = Number(\n this.toastRef()\n .nativeElement.style.getPropertyValue('--swipe-amount')\n .replace('px', '') || 0\n );\n\n // Remove only if threshold is met\n if (Math.abs(swipeAmount) >= SWIPE_THRESHOLD) {\n this.offsetBeforeRemove.set(this.offset());\n this.toast().onDismiss?.(this.toast());\n this.deleteToast();\n this.swipeOut.set(true);\n return;\n }\n\n this.toastRef().nativeElement.style.setProperty('--swipe-amount', '0px');\n this.swiping.set(false);\n }\n\n onPointerMove(event: PointerEvent) {\n if (!this.pointerStartRef || !this.toast().dismissible) return;\n\n const yPosition = event.clientY - this.pointerStartRef.y;\n const xPosition = event.clientX - this.pointerStartRef.x;\n\n const clamp = this.coords()[0] === 'top' ? Math.min : Math.max;\n const clampedY = clamp(0, yPosition);\n const swipeStartThreshold = event.pointerType === 'touch' ? 10 : 2;\n const isAllowedToSwipe = Math.abs(clampedY) > swipeStartThreshold;\n\n if (isAllowedToSwipe) {\n this.toastRef().nativeElement.style.setProperty(\n '--swipe-amount',\n `${yPosition}px`\n );\n } else if (Math.abs(xPosition) > swipeStartThreshold) {\n // User is swiping in wrong direction, so we disable swipe gesture\n // for the current pointer down interaction\n this.pointerStartRef = null;\n }\n }\n\n onCloseButtonClick() {\n if (this.disabled() || !this.toast().dismissible) return;\n this.deleteToast();\n this.toast().onDismiss?.(this.toast());\n }\n\n onCancelClick() {\n const toast = this.toast();\n if (!toast.dismissible) return;\n this.deleteToast();\n if (toast.cancel?.onClick) {\n toast.cancel.onClick();\n }\n }\n\n onActionClick(event: MouseEvent) {\n const toast = this.toast();\n toast.action?.onClick(event);\n if (event.defaultPrevented) return;\n this.deleteToast();\n }\n}\n","import { isPlatformBrowser } from '@angular/common';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n ElementRef,\n inject,\n input,\n linkedSignal,\n numberAttribute,\n OnDestroy,\n PLATFORM_ID,\n signal,\n viewChild,\n ViewEncapsulation,\n} from '@angular/core';\nimport { IconComponent } from './icon.component';\nimport {\n GAP,\n TOAST_LIFETIME,\n TOAST_WIDTH,\n VIEWPORT_OFFSET,\n VISIBLE_TOASTS_AMOUNT,\n} from './internal/constants';\nimport { LoaderComponent } from './loader.component';\nimport { ToastFilterPipe } from './pipes/toast-filter.pipe';\nimport { toastState } from './state';\nimport { ToastComponent } from './toast.component';\nimport { Position, Theme, ToasterProps } from './types';\n\n@Component({\n selector: 'ngx-sonner-toaster',\n imports: [ToastComponent, ToastFilterPipe, IconComponent, LoaderComponent],\n template: `\n @if (toasts().length > 0) {\n <section\n [attr.aria-label]=\"'Notifications ' + hotKeyLabel()\"\n [tabIndex]=\"-1\">\n @for (pos of possiblePositions(); track pos) {\n <ol\n #listRef\n [tabIndex]=\"-1\"\n [class]=\"_class()\"\n data-sonner-toaster\n [attr.data-theme]=\"actualTheme()\"\n [attr.data-rich-colors]=\"richColors()\"\n [attr.dir]=\"dir() === 'auto' ? getDocumentDirection() : dir()\"\n [attr.data-y-position]=\"pos.split('-')[0]\"\n [attr.data-x-position]=\"pos.split('-')[1]\"\n (blur)=\"handleBlur($event)\"\n (focus)=\"handleFocus($event)\"\n (mouseenter)=\"expanded.set(true)\"\n (mousemove)=\"expanded.set(true)\"\n (mouseleave)=\"handleMouseLeave()\"\n (pointerdown)=\"handlePointerDown($event)\"\n (pointerup)=\"interacting.set(false)\"\n [style]=\"toasterStyles()\">\n @for (\n toast of toasts() | toastFilter: $index : pos;\n track toast.id\n ) {\n <ngx-sonner-toast\n [index]=\"$index\"\n [toast]=\"toast\"\n [invert]=\"invert()\"\n [visibleToasts]=\"visibleToasts()\"\n [closeButton]=\"closeButton()\"\n [interacting]=\"interacting()\"\n [position]=\"position()\"\n [expandByDefault]=\"expand()\"\n [expanded]=\"expanded()\"\n [actionButtonStyle]=\"toastOptions().actionButtonStyle\"\n [cancelButtonStyle]=\"toastOptions().cancelButtonStyle\"\n [class]=\"toastOptions().class ?? ''\"\n [descriptionClass]=\"toastOptions().descriptionClass ?? ''\"\n [classes]=\"toastOptions().classes ?? {}\"\n [duration]=\"toastOptions().duration ?? duration()\"\n [unstyled]=\"toastOptions().unstyled ?? false\">\n <ng-content select=\"[loading-icon]\" loading-icon>\n <ngx-sonner-loader [isVisible]=\"toast.type === 'loading'\" />\n </ng-content>\n <ng-content select=\"[success-icon]\" success-icon>\n <ngx-sonner-icon type=\"success\" />\n </ng-content>\n <ng-content select=\"[error-icon]\" error-icon>\n <ngx-sonner-icon type=\"error\" />\n </ng-content>\n <ng-content select=\"[warning-icon]\" warning-icon>\n <ngx-sonner-icon type=\"warning\" />\n </ng-content>\n <ng-content select=\"[info-icon]\" info-icon>\n <ngx-sonner-icon type=\"info\" />\n </ng-content>\n </ngx-sonner-toast>\n }\n </ol>\n }\n </section>\n }\n `,\n styleUrl: 'toaster.component.css',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\n// eslint-disable-next-line @angular-eslint/component-class-suffix\nexport class NgxSonnerToaster implements OnDestroy {\n private readonly platformId = inject(PLATFORM_ID);\n\n toasts = toastState.toasts;\n heights = toastState.heights;\n reset = toastState.reset;\n\n invert = input<ToasterProps['invert'], boolean | string>(false, {\n transform: booleanAttribute,\n });\n theme = input<ToasterProps['theme']>('light');\n position = input<ToasterProps['position']>('bottom-right');\n hotKey = input<ToasterProps['hotkey']>(['altKey', 'KeyT']);\n richColors = input<ToasterProps['richColors'], boolean | string>(false, {\n transform: booleanAttribute,\n });\n expand = input<ToasterProps['expand'], boolean | string>(false, {\n transform: booleanAttribute,\n });\n duration = input<ToasterProps['duration'], number | string>(TOAST_LIFETIME, {\n transform: numberAttribute,\n });\n visibleToasts = input<ToasterProps['visibleToasts'], number | string>(\n VISIBLE_TOASTS_AMOUNT,\n { transform: numberAttribute }\n );\n closeButton = input<ToasterProps['closeButton'], boolean | string>(false, {\n transform: booleanAttribute,\n });\n toastOptions = input<ToasterProps['toastOptions']>({});\n offset = input<ToasterProps['offset']>(null);\n dir = input<ToasterProps['dir']>(this.getDocumentDirection());\n _class = input('', { alias: 'class' });\n _style = input<Record<string, string>>({}, { alias: 'style' });\n\n possiblePositions = computed(\n () =>\n Array.from(\n new Set(\n [\n this.position(),\n ...this.toasts()\n .filter(toast => toast.position)\n .map(toast => toast.position),\n ].filter(Boolean)\n )\n ) as Position[]\n );\n\n expanded = linkedSignal({\n source: this.toasts,\n computation: toasts => toasts.length < 1,\n });\n actualTheme = linkedSignal({\n source: this.theme,\n computation: newTheme => this.getActualTheme(newTheme),\n });\n interacting = signal(false);\n\n listRef = viewChild<ElementRef<HTMLOListElement>>('listRef');\n lastFocusedElementRef = signal<HTMLElement | null>(null);\n isFocusWithinRef = signal(false);\n\n hotKeyLabel = computed(() =>\n this.hotKey().join('+').replace(/Key/g, '').replace(/Digit/g, '')\n );\n\n toasterStyles = computed(() => ({\n '--front-toast-height': `${this.heights()[0]?.height}px`,\n '--offset':\n typeof this.offset() === 'number'\n ? `${this.offset()}px`\n : this.offset() ?? `${VIEWPORT_OFFSET}`,\n '--width': `${TOAST_WIDTH}px`,\n '--gap': `${GAP}px`,\n ...this._style(),\n }));\n\n constructor() {\n this.reset();\n\n if (isPlatformBrowser(this.platformId)) {\n document.addEventListener('keydown', this.handleKeydown);\n window\n .matchMedia('(prefers-color-scheme: dark)')\n .addEventListener('change', this.handleThemePreferenceChange);\n }\n }\n\n ngOnDestroy() {\n if (isPlatformBrowser(this.platformId)) {\n document.removeEventListener('keydown', this.handleKeydown);\n window\n .matchMedia('(prefers-color-scheme: dark)')\n .removeEventListener('change', this.handleThemePreferenceChange);\n }\n }\n\n handleBlur(event: FocusEvent) {\n if (\n this.isFocusWithinRef() &&\n !(event.target as HTMLOListElement).contains(\n event.relatedTarget as HTMLElement\n )\n ) {\n this.isFocusWithinRef.set(false);\n if (this.lastFocusedElementRef()) {\n this.lastFocusedElementRef()?.focus({ preventScroll: true });\n this.lastFocusedElementRef.set(null);\n }\n }\n }\n\n handleFocus(event: FocusEvent) {\n const isNotDismissible =\n event.target instanceof HTMLElement &&\n event.target.dataset['dismissible'] === 'false';\n\n if (isNotDismissible) return;\n\n if (!this.isFocusWithinRef()) {\n this.isFocusWithinRef.set(true);\n this.lastFocusedElementRef.set(event.relatedTarget as HTMLElement);\n }\n }\n\n handlePointerDown(event: MouseEvent) {\n const isNotDismissible =\n event.target instanceof HTMLElement &&\n event.target.dataset['dismissible'] === 'false';\n\n if (isNotDismissible) return;\n this.interacting.set(true);\n }\n\n handleMouseLeave() {\n if (!this.interacting()) {\n this.expanded.set(false);\n }\n }\n\n private handleKeydown = (event: KeyboardEvent) => {\n const listRef = this.listRef()?.nativeElement;\n if (!listRef) return;\n\n const isHotkeyPressed = this.hotKey().every(\n key => (event as never)[key] || event.code === key\n );\n\n if (isHotkeyPressed) {\n this.expanded.set(true);\n listRef.focus();\n }\n\n if (\n event.code === 'Escape' &&\n (document.activeElement === listRef ||\n listRef.contains(document.activeElement))\n ) {\n this.expanded.set(false);\n }\n };\n\n private handleThemePreferenceChange = ({ matches }: MediaQueryListEvent) => {\n if (this.theme() === 'system') {\n this.actualTheme.set(matches ? 'dark' : 'light');\n }\n };\n\n private getActualTheme(theme: Theme): Theme {\n if (theme !== 'system') {\n return theme;\n }\n\n if (isPlatformBrowser(this.platformId)) {\n const prefersDark = window.matchMedia?.(\n '(prefers-color-scheme: dark)'\n ).matches;\n return prefersDark ? 'dark' : 'light';\n }\n\n return 'light';\n }\n\n getDocumentDirection(): ToasterProps['dir'] {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return 'ltr';\n }\n\n const dirAttribute = document.documentElement.getAttribute('dir');\n\n if (!dirAttribute || dirAttribute === 'auto') {\n return window.getComputedStyle(document.documentElement)\n .direction as ToasterProps['dir'];\n }\n\n return dirAttribute as ToasterProps['dir'];\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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