{
  "name": "sonner",
  "type": "registry:component",
  "files": [
    {
      "name": "sonner.component.ts",
      "content": "import { ChangeDetectionStrategy, Component, computed, input, ViewEncapsulation } from '@angular/core';\n\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { lucideCircleCheck, lucideInfo, lucideLoader2, lucideOctagonX, lucideTriangleAlert } from '@ng-icons/lucide';\nimport type { ClassValue } from 'clsx';\nimport { NgxSonnerToaster, type ToasterProps } from 'ngx-sonner';\n\nimport { mergeClasses } from '@/shared/utils/merge-classes';\n\nimport { sonnerVariants } from './sonner.variants';\n\nexport type ZardSonnerPosition =\n  | 'top-left'\n  | 'top-center'\n  | 'top-right'\n  | 'bottom-left'\n  | 'bottom-center'\n  | 'bottom-right';\n\nconst DEFAULT_STYLE: Record<string, string> = {\n  '--normal-bg': 'var(--popover)',\n  '--normal-text': 'var(--popover-foreground)',\n  '--normal-border': 'var(--border)',\n  '--border-radius': 'var(--radius)',\n};\n\nconst DEFAULT_TOAST_OPTIONS: ToasterProps['toastOptions'] = {\n  classes: {\n    toast: 'cn-toast',\n  },\n};\n\n@Component({\n  selector: 'z-sonner',\n  imports: [NgIcon, NgxSonnerToaster],\n  template: `\n    <ngx-sonner-toaster\n      [theme]=\"theme()\"\n      [class]=\"classes()\"\n      [style]=\"resolvedStyle()\"\n      [position]=\"position()\"\n      [richColors]=\"richColors()\"\n      [expand]=\"expand()\"\n      [duration]=\"duration()\"\n      [visibleToasts]=\"visibleToasts()\"\n      [closeButton]=\"closeButton()\"\n      [toastOptions]=\"resolvedToastOptions()\"\n      [dir]=\"dir()\"\n    >\n      <ng-icon loading-icon name=\"lucideLoader2\" class=\"size-4 [&>svg]:animate-spin\" />\n      <ng-icon success-icon name=\"lucideCircleCheck\" class=\"size-4\" />\n      <ng-icon error-icon name=\"lucideOctagonX\" class=\"size-4\" />\n      <ng-icon warning-icon name=\"lucideTriangleAlert\" class=\"size-4\" />\n      <ng-icon info-icon name=\"lucideInfo\" class=\"size-4\" />\n    </ngx-sonner-toaster>\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  encapsulation: ViewEncapsulation.None,\n  viewProviders: [provideIcons({ lucideCircleCheck, lucideInfo, lucideLoader2, lucideOctagonX, lucideTriangleAlert })],\n  exportAs: 'zSonner',\n})\nexport class ZardSonnerComponent {\n  readonly class = input<ClassValue>('');\n  readonly theme = input<'light' | 'dark' | 'system'>('system');\n  readonly position = input<ZardSonnerPosition>('top-center');\n  readonly richColors = input<boolean>(false);\n  readonly expand = input<boolean>(false);\n  readonly duration = input<number>(4000);\n  readonly visibleToasts = input<number>(3);\n  readonly closeButton = input<boolean>(false);\n  readonly toastOptions = input<ToasterProps['toastOptions']>();\n  readonly style = input<Record<string, string>>();\n  readonly dir = input<'ltr' | 'rtl' | 'auto'>('auto');\n\n  protected readonly classes = computed(() => mergeClasses(sonnerVariants(), this.class()));\n  protected readonly resolvedStyle = computed(() => ({ ...DEFAULT_STYLE, ...(this.style() ?? {}) }));\n  protected readonly resolvedToastOptions = computed<ToasterProps['toastOptions']>(() => {\n    const provided = this.toastOptions();\n    if (!provided) return DEFAULT_TOAST_OPTIONS;\n    return {\n      ...DEFAULT_TOAST_OPTIONS,\n      ...provided,\n      classes: { ...DEFAULT_TOAST_OPTIONS.classes, ...(provided.classes ?? {}) },\n    };\n  });\n}\n"
    },
    {
      "name": "sonner.service.ts",
      "content": "import { Injectable, type Type } from '@angular/core';\n\nimport { toast, type ExternalToast, type PromiseData, type PromiseT } from 'ngx-sonner';\n\n/**\n * Type-safe Angular wrapper around the underlying `ngx-sonner` toast API.\n *\n * Use this service from any component / service to dispatch toasts\n * without coupling the consumer code to the third-party library.\n *\n * @example\n * private readonly sonner = inject(ZardSonnerService);\n *\n * this.sonner.success('Saved!');\n * this.sonner.error('Failed', { description: 'Try again later.' });\n * this.sonner.promise(savePromise, {\n *   loading: 'Saving...',\n *   success: 'Saved!',\n *   error: 'Failed.',\n * });\n */\n@Injectable({ providedIn: 'root' })\nexport class ZardSonnerService {\n  /** Dispatch a default toast. Returns the toast id. */\n  show(message: string | Type<unknown>, options?: ExternalToast): string | number {\n    return toast(message, options);\n  }\n\n  /** Dispatch a success-styled toast (green). */\n  success(message: string | Type<unknown>, options?: ExternalToast): string | number {\n    return toast.success(message, options);\n  }\n\n  /** Dispatch an error-styled toast (red). */\n  error(message: string | Type<unknown>, options?: ExternalToast): string | number {\n    return toast.error(message, options);\n  }\n\n  /** Dispatch a warning-styled toast (yellow). */\n  warning(message: string | Type<unknown>, options?: ExternalToast): string | number {\n    return toast.warning(message, options);\n  }\n\n  /** Dispatch an info-styled toast (blue). */\n  info(message: string | Type<unknown>, options?: ExternalToast): string | number {\n    return toast.info(message, options);\n  }\n\n  /** Dispatch a loading-styled toast (with spinner). */\n  loading(message: string | Type<unknown>, options?: ExternalToast): string | number {\n    return toast.loading(message, options);\n  }\n\n  /** Dispatch a neutral message-styled toast. */\n  message(message: string | Type<unknown>, options?: ExternalToast): string | number {\n    return toast.message(message, options);\n  }\n\n  /**\n   * Bind a toast lifecycle to a promise. The toast updates from `loading`\n   * to `success` / `error` based on the promise resolution.\n   */\n  promise<T>(promise: PromiseT<T>, options?: PromiseData<T>): string | number | undefined {\n    return toast.promise(promise, options);\n  }\n\n  /** Dismiss a toast by id, or all toasts when no id is provided. */\n  dismiss(id?: string | number): void {\n    toast.dismiss(id);\n  }\n\n  /** Dispatch a toast that renders a custom Angular component. */\n  custom<T>(component: Type<T>, options?: ExternalToast): string | number {\n    return toast.custom(component, options);\n  }\n}\n"
    },
    {
      "name": "sonner.variants.ts",
      "content": "import { cva } from 'class-variance-authority';\n\nexport const sonnerVariants = cva('toaster group');\n"
    },
    {
      "name": "index.ts",
      "content": "export * from './sonner.component';\nexport * from './sonner.service';\nexport * from './sonner.variants';\n"
    }
  ],
  "dependencies": [
    "ngx-sonner"
  ],
  "demos": [
    {
      "name": "default.ts",
      "content": "import { ChangeDetectionStrategy, Component, inject } from '@angular/core';\n\nimport { ZardButtonComponent } from '@/shared/components/button/button.component';\nimport { ZardSonnerService } from '@/shared/components/sonner/sonner.service';\n\n@Component({\n  selector: 'zard-demo-sonner-default',\n  imports: [ZardButtonComponent],\n  template: `\n    <button type=\"button\" z-button zType=\"outline\" (click)=\"show()\">Show Toast</button>\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ZardDemoSonnerDefaultComponent {\n  private readonly sonner = inject(ZardSonnerService);\n\n  show() {\n    this.sonner.show('Event has been created', {\n      description: 'Sunday, December 03, 2023 at 9:00 AM',\n      action: {\n        label: 'Undo',\n        onClick: () => console.log('Undo'),\n      },\n    });\n  }\n}\n"
    },
    {
      "name": "description.ts",
      "content": "import { ChangeDetectionStrategy, Component, inject } from '@angular/core';\n\nimport { ZardButtonComponent } from '@/shared/components/button/button.component';\nimport { ZardSonnerService } from '@/shared/components/sonner/sonner.service';\n\n@Component({\n  selector: 'zard-demo-sonner-description',\n  imports: [ZardButtonComponent],\n  template: `\n    <button type=\"button\" z-button zType=\"outline\" class=\"w-fit\" (click)=\"show()\">Show Toast</button>\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ZardDemoSonnerDescriptionComponent {\n  private readonly sonner = inject(ZardSonnerService);\n\n  show() {\n    this.sonner.show('Event has been created', {\n      description: 'Monday, January 3rd at 6:00pm',\n    });\n  }\n}\n"
    },
    {
      "name": "position.ts",
      "content": "import { ChangeDetectionStrategy, Component, inject } from '@angular/core';\n\nimport { ZardButtonComponent } from '@/shared/components/button/button.component';\nimport { type ZardSonnerPosition } from '@/shared/components/sonner/sonner.component';\nimport { ZardSonnerService } from '@/shared/components/sonner/sonner.service';\n\n@Component({\n  selector: 'zard-demo-sonner-position',\n  imports: [ZardButtonComponent],\n  template: `\n    <div class=\"flex flex-wrap justify-center gap-2\">\n      <button type=\"button\" z-button zType=\"outline\" (click)=\"show('top-left')\">Top Left</button>\n      <button type=\"button\" z-button zType=\"outline\" (click)=\"show('top-center')\">Top Center</button>\n      <button type=\"button\" z-button zType=\"outline\" (click)=\"show('top-right')\">Top Right</button>\n      <button type=\"button\" z-button zType=\"outline\" (click)=\"show('bottom-left')\">Bottom Left</button>\n      <button type=\"button\" z-button zType=\"outline\" (click)=\"show('bottom-center')\">Bottom Center</button>\n      <button type=\"button\" z-button zType=\"outline\" (click)=\"show('bottom-right')\">Bottom Right</button>\n    </div>\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ZardDemoSonnerPositionComponent {\n  private readonly sonner = inject(ZardSonnerService);\n\n  show(position: ZardSonnerPosition) {\n    this.sonner.show('Event has been created', { position });\n  }\n}\n"
    },
    {
      "name": "types.ts",
      "content": "import { ChangeDetectionStrategy, Component, inject } from '@angular/core';\n\nimport { ZardButtonComponent } from '@/shared/components/button/button.component';\nimport { ZardSonnerService } from '@/shared/components/sonner/sonner.service';\n\n@Component({\n  selector: 'zard-demo-sonner-types',\n  imports: [ZardButtonComponent],\n  template: `\n    <div class=\"flex flex-wrap gap-2\">\n      <button type=\"button\" z-button zType=\"outline\" (click)=\"sonner.show('Event has been created')\">Default</button>\n      <button type=\"button\" z-button zType=\"outline\" (click)=\"sonner.success('Event has been created')\">Success</button>\n      <button\n        type=\"button\"\n        z-button\n        zType=\"outline\"\n        (click)=\"sonner.info('Be at the area 10 minutes before the event time')\"\n      >\n        Info\n      </button>\n      <button\n        type=\"button\"\n        z-button\n        zType=\"outline\"\n        (click)=\"sonner.warning('Event start time cannot be earlier than 8am')\"\n      >\n        Warning\n      </button>\n      <button type=\"button\" z-button zType=\"outline\" (click)=\"sonner.error('Event has not been created')\">Error</button>\n      <button type=\"button\" z-button zType=\"outline\" (click)=\"showPromise()\">Promise</button>\n    </div>\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ZardDemoSonnerTypesComponent {\n  protected readonly sonner = inject(ZardSonnerService);\n\n  showPromise() {\n    this.sonner.promise<{ name: string }>(\n      () => new Promise(resolve => setTimeout(() => resolve({ name: 'Event' }), 2000)),\n      {\n        loading: 'Loading...',\n        success: data => `${data.name} has been created`,\n        error: 'Error',\n      },\n    );\n  }\n}\n"
    }
  ]
}
