{
  "name": "sheet",
  "type": "registry:component",
  "files": [
    {
      "name": "sheet.component.ts",
      "content": "import { A11yModule } from '@angular/cdk/a11y';\nimport { OverlayModule } from '@angular/cdk/overlay';\nimport {\n  BasePortalOutlet,\n  CdkPortalOutlet,\n  type ComponentPortal,\n  PortalModule,\n  type TemplatePortal,\n} from '@angular/cdk/portal';\nimport {\n  ChangeDetectionStrategy,\n  Component,\n  type ComponentRef,\n  computed,\n  ElementRef,\n  type EmbeddedViewRef,\n  type EventEmitter,\n  inject,\n  output,\n  type TemplateRef,\n  type Type,\n  viewChild,\n  type ViewContainerRef,\n} from '@angular/core';\n\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { lucideX } from '@ng-icons/lucide';\nimport type { ClassValue } from 'clsx';\n\nimport { ZardButtonComponent } from '@/shared/components/button';\nimport { ZardIdDirective } from '@/shared/core';\nimport { mergeClasses, noopFn } from '@/shared/utils/merge-classes';\n\nimport type { ZardSheetRef } from './sheet-ref';\nimport {\n  sheetDescriptionVariants,\n  sheetFooterVariants,\n  sheetHeaderVariants,\n  sheetTitleVariants,\n  sheetVariants,\n  type ZardSheetVariants,\n} from './sheet.variants';\n\nexport type OnClickCallback<T> = (instance: T) => false | void | object;\nexport class ZardSheetOptions<T, U> {\n  zCancelIcon?: string;\n  zCancelText?: string | null;\n  zClosable?: boolean;\n  zContent?: string | TemplateRef<T> | Type<T>;\n  zCustomClasses?: ClassValue;\n  zData?: U;\n  zDescription?: string;\n  /** Animation duration (ms) used when closing. Defaults to 200 (matches CSS transition). */\n  zDuration?: number;\n  zHeight?: string;\n  zHideFooter?: boolean;\n  zMaskClosable?: boolean;\n  zOkDestructive?: boolean;\n  zOkDisabled?: boolean;\n  zOkIcon?: string;\n  zOkText?: string | null;\n  zOnCancel?: EventEmitter<T> | OnClickCallback<T> = noopFn;\n  zOnOk?: EventEmitter<T> | OnClickCallback<T> = noopFn;\n  zSide?: ZardSheetVariants['zSide'] = 'right';\n  zSize?: ZardSheetVariants['zSize'] = 'default';\n  zTitle?: string | TemplateRef<T>;\n  zViewContainerRef?: ViewContainerRef;\n  zWidth?: string;\n}\n\n@Component({\n  selector: 'z-sheet',\n  imports: [A11yModule, OverlayModule, PortalModule, ZardButtonComponent, ZardIdDirective, NgIcon],\n  template: `\n    <ng-container zardId=\"z-sheet\" #idRef=\"zardId\">\n      @if (config.zClosable || config.zClosable === undefined) {\n        <button\n          type=\"button\"\n          data-testid=\"z-close-header-button\"\n          data-slot=\"sheet-close\"\n          z-button\n          zType=\"ghost\"\n          zSize=\"icon-sm\"\n          class=\"absolute top-3 right-3\"\n          (click)=\"onCloseClick()\"\n        >\n          <ng-icon name=\"lucideX\" class=\"size-4!\" />\n          <span class=\"sr-only\">Close</span>\n        </button>\n      }\n\n      @if (config.zTitle || config.zDescription) {\n        <header [class]=\"headerClasses()\" data-slot=\"sheet-header\">\n          @if (config.zTitle) {\n            <h4 data-testid=\"z-title\" data-slot=\"sheet-title\" [class]=\"titleClasses()\" [id]=\"idRef.id() + '-title'\">\n              {{ config.zTitle }}\n            </h4>\n\n            @if (config.zDescription) {\n              <p\n                data-testid=\"z-description\"\n                data-slot=\"sheet-description\"\n                [class]=\"descriptionClasses()\"\n                [id]=\"idRef.id() + '-description'\"\n              >\n                {{ config.zDescription }}\n              </p>\n            }\n          }\n        </header>\n      }\n\n      <!-- min-h-0 lets the content area shrink below its intrinsic height, so scrollable\n           content stays inside the sheet instead of pushing the footer past the viewport. -->\n      <main class=\"flex min-h-0 w-full flex-1 flex-col space-y-4\">\n        <ng-template cdkPortalOutlet />\n\n        @if (isStringContent()) {\n          <!-- Angular auto-sanitizes [innerHTML] by default; scripts/event handlers are stripped. -->\n          <div data-testid=\"z-content\" [innerHTML]=\"config.zContent\"></div>\n        }\n      </main>\n\n      @if (!config.zHideFooter) {\n        <footer [class]=\"footerClasses()\" data-slot=\"sheet-footer\">\n          @if (config.zOkText !== null) {\n            <button\n              type=\"button\"\n              data-testid=\"z-ok-button\"\n              z-button\n              [zType]=\"config.zOkDestructive ? 'destructive' : 'default'\"\n              [zDisabled]=\"config.zOkDisabled\"\n              (click)=\"onOkClick()\"\n            >\n              @if (config.zOkIcon) {\n                @if (isSvgString(config.zOkIcon)) {\n                  <ng-icon [svg]=\"config.zOkIcon\" class=\"size-4!\" />\n                } @else {\n                  <ng-icon [name]=\"config.zOkIcon\" class=\"size-4!\" />\n                }\n              }\n\n              {{ config.zOkText ?? 'OK' }}\n            </button>\n          }\n\n          @if (config.zCancelText !== null) {\n            <button type=\"button\" data-testid=\"z-cancel-button\" z-button zType=\"outline\" (click)=\"onCloseClick()\">\n              @if (config.zCancelIcon) {\n                @if (isSvgString(config.zCancelIcon)) {\n                  <ng-icon [svg]=\"config.zCancelIcon\" class=\"size-4!\" />\n                } @else {\n                  <ng-icon [name]=\"config.zCancelIcon\" class=\"size-4!\" />\n                }\n              }\n\n              {{ config.zCancelText ?? 'Cancel' }}\n            </button>\n          }\n        </footer>\n      }\n    </ng-container>\n  `,\n  styles: `\n    :host {\n      --z-sheet-duration: 200ms;\n      opacity: 1;\n      translate: 0 0;\n      transition:\n        opacity var(--z-sheet-duration) ease-in-out,\n        translate var(--z-sheet-duration) ease-in-out;\n    }\n\n    @starting-style {\n      :host([data-side='right']) {\n        opacity: 0;\n        translate: 2.5rem 0;\n      }\n\n      :host([data-side='left']) {\n        opacity: 0;\n        translate: -2.5rem 0;\n      }\n\n      :host([data-side='top']) {\n        opacity: 0;\n        translate: 0 -2.5rem;\n      }\n\n      :host([data-side='bottom']) {\n        opacity: 0;\n        translate: 0 2.5rem;\n      }\n    }\n\n    :host(.sheet-leave[data-side='right']) {\n      opacity: 0;\n      translate: 2.5rem 0;\n    }\n\n    :host(.sheet-leave[data-side='left']) {\n      opacity: 0;\n      translate: -2.5rem 0;\n    }\n\n    :host(.sheet-leave[data-side='top']) {\n      opacity: 0;\n      translate: 0 -2.5rem;\n    }\n\n    :host(.sheet-leave[data-side='bottom']) {\n      opacity: 0;\n      translate: 0 2.5rem;\n    }\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  viewProviders: [provideIcons({ lucideX })],\n  host: {\n    'data-slot': 'sheet-content',\n    '[class]': 'classes()',\n    '[style.width]': 'config.zWidth ? config.zWidth : null',\n    '[style.height]': 'config.zHeight ? config.zHeight : null',\n    '[style.--z-sheet-duration]': 'durationCss()',\n    role: 'dialog',\n    'aria-modal': 'true',\n    '[attr.aria-labelledby]': 'titleId()',\n    '[attr.aria-describedby]': 'descriptionId()',\n    cdkTrapFocus: 'true',\n    cdkTrapFocusAutoCapture: 'true',\n  },\n  exportAs: 'zSheet',\n})\nexport class ZardSheetComponent<T, U> extends BasePortalOutlet {\n  private readonly host = inject(ElementRef<HTMLElement>);\n  protected readonly config = inject(ZardSheetOptions<T, U>);\n  private readonly idRef = viewChild.required<ZardIdDirective>('idRef');\n\n  protected readonly side = computed(() => this.config.zSide ?? 'right');\n\n  protected readonly classes = computed(() => {\n    const zSize = this.config.zWidth || this.config.zHeight ? 'custom' : this.config.zSize;\n\n    return mergeClasses(sheetVariants({ zSide: this.side(), zSize }), this.config.zCustomClasses);\n  });\n\n  protected readonly headerClasses = computed(() => sheetHeaderVariants());\n  protected readonly titleClasses = computed(() => sheetTitleVariants());\n  protected readonly descriptionClasses = computed(() => sheetDescriptionVariants());\n  protected readonly footerClasses = computed(() => sheetFooterVariants());\n  protected readonly isStringContent = computed(() => typeof this.config.zContent === 'string');\n  protected readonly titleId = computed(() => (this.config.zTitle ? `${this.idRef().id()}-title` : null));\n  protected readonly descriptionId = computed(() =>\n    this.config.zDescription ? `${this.idRef().id()}-description` : null,\n  );\n\n  protected readonly durationCss = computed(() =>\n    this.config.zDuration !== undefined ? `${this.config.zDuration}ms` : null,\n  );\n\n  protected isSvgString(icon: string): boolean {\n    return /^\\s*<svg/i.test(icon);\n  }\n\n  sheetRef?: ZardSheetRef<T>;\n\n  constructor() {\n    super();\n\n    // Set in the constructor rather than through a host binding: the CDK appends this element to the\n    // DOM before the first change detection runs, and `@starting-style` only applies to the very\n    // first style resolution — a late `data-side` would silently skip the enter animation.\n    this.host.nativeElement.setAttribute('data-side', this.side());\n  }\n\n  readonly portalOutlet = viewChild.required(CdkPortalOutlet);\n\n  readonly okTriggered = output<void>();\n  readonly cancelTriggered = output<void>();\n\n  getNativeElement(): HTMLElement {\n    return this.host.nativeElement;\n  }\n\n  attachComponentPortal<C>(portal: ComponentPortal<C>): ComponentRef<C> {\n    if (this.portalOutlet().hasAttached()) {\n      throw new Error('Attempting to attach modal content after content is already attached');\n    }\n    return this.portalOutlet().attachComponentPortal(portal);\n  }\n\n  attachTemplatePortal<C>(portal: TemplatePortal<C>): EmbeddedViewRef<C> {\n    if (this.portalOutlet().hasAttached()) {\n      throw new Error('Attempting to attach modal content after content is already attached');\n    }\n\n    return this.portalOutlet().attachTemplatePortal(portal);\n  }\n\n  onOkClick() {\n    this.okTriggered.emit();\n  }\n\n  onCloseClick() {\n    this.cancelTriggered.emit();\n  }\n}\n"
    },
    {
      "name": "sheet.variants.ts",
      "content": "import { cva, type VariantProps } from 'class-variance-authority';\n\nexport const sheetVariants = cva(\n  [\n    'fixed z-50 flex flex-col gap-4',\n    'bg-popover bg-clip-padding text-sm text-popover-foreground shadow-lg outline-none',\n  ].join(' '),\n  {\n    variants: {\n      zSide: {\n        top: 'inset-x-0 top-0 h-auto border-b',\n        right: 'inset-y-0 right-0 h-full w-3/4 border-l',\n        bottom: 'inset-x-0 bottom-0 h-auto border-t',\n        left: 'inset-y-0 left-0 h-full w-3/4 border-r',\n      },\n      zSize: {\n        default: '',\n        sm: '',\n        lg: '',\n        // Dimensions come from zWidth/zHeight as inline styles.\n        custom: '',\n      },\n    },\n    compoundVariants: [\n      {\n        zSide: ['left', 'right'],\n        zSize: 'default',\n        class: 'sm:max-w-sm',\n      },\n      {\n        zSide: ['left', 'right'],\n        zSize: 'sm',\n        class: 'w-1/2 sm:max-w-xs',\n      },\n      {\n        zSide: ['left', 'right'],\n        zSize: 'lg',\n        class: 'w-full sm:max-w-lg',\n      },\n      {\n        zSide: ['top', 'bottom'],\n        zSize: 'sm',\n        class: 'h-1/3',\n      },\n      {\n        zSide: ['top', 'bottom'],\n        zSize: 'lg',\n        class: 'h-3/4',\n      },\n    ],\n    defaultVariants: {\n      zSide: 'right',\n      zSize: 'default',\n    },\n  },\n);\n\nexport const sheetHeaderVariants = cva('flex flex-col gap-0.5 p-4');\n\nexport const sheetTitleVariants = cva('text-base font-medium text-foreground');\n\nexport const sheetDescriptionVariants = cva('text-sm text-muted-foreground');\n\nexport const sheetFooterVariants = cva('mt-auto flex flex-col gap-2 p-4');\n\nexport type ZardSheetVariants = VariantProps<typeof sheetVariants>;\n"
    },
    {
      "name": "sheet-ref.ts",
      "content": "import type { OverlayRef } from '@angular/cdk/overlay';\nimport { isPlatformBrowser } from '@angular/common';\nimport { EventEmitter, signal } from '@angular/core';\nimport { outputToObservable } from '@angular/core/rxjs-interop';\n\nimport { filter, takeUntil } from 'rxjs';\n\nimport type { ZardSheetComponent, ZardSheetOptions } from './sheet.component';\n\nconst enum eTriggerAction {\n  CANCEL = 'cancel',\n  OK = 'ok',\n}\n\nconst ESCAPE_KEYS = ['Escape', 'Esc'] as const;\n\n/**\n * Reference to a sheet opened via {@link ZardSheetService}.\n *\n * Exposes signals for reactive consumption (`isClosing`, `result`,\n * `componentInstance`) and methods for closing the sheet.\n *\n * Multiple open sheets are tracked in a private stack so that pressing\n * Escape only closes the topmost one.\n */\nexport class ZardSheetRef<T = unknown, R = unknown, U = unknown> {\n  /** Stack of currently open sheets. The last entry is the topmost. */\n  private static readonly stack: ZardSheetRef[] = [];\n\n  /** Element focused before the sheet opened, used to restore focus on close. */\n  private readonly previouslyFocusedElement: HTMLElement | null;\n\n  /** Animation duration (ms) used when closing. Mirrors the CSS transition. */\n  private readonly animationDuration: number;\n\n  /** Pending dispose timer; cleared if dispose runs early or twice. */\n  private disposeTimer: ReturnType<typeof setTimeout> | null = null;\n  private disposed = false;\n\n  private readonly _isClosing = signal(false);\n  private readonly _result = signal<R | undefined>(undefined);\n  private readonly _componentInstance = signal<T | null>(null);\n\n  /** True from the moment {@link close} is called until the overlay is disposed. */\n  readonly isClosing = this._isClosing.asReadonly();\n  /** Result passed to {@link close}, available after it's called. */\n  readonly result = this._result.asReadonly();\n  /** Instance of the component projected as content, or null for templates / strings. */\n  readonly componentInstance = this._componentInstance.asReadonly();\n\n  constructor(\n    private readonly overlayRef: OverlayRef | null,\n    private readonly config: ZardSheetOptions<T, U>,\n    private readonly containerInstance: ZardSheetComponent<T, U> | null,\n    private readonly platformId: object,\n  ) {\n    this.animationDuration = config.zDuration ?? 200;\n    this.previouslyFocusedElement = isPlatformBrowser(platformId)\n      ? (document.activeElement as HTMLElement | null)\n      : null;\n\n    if (!this.overlayRef || !this.containerInstance) return;\n\n    ZardSheetRef.stack.push(this as unknown as ZardSheetRef);\n\n    const detached$ = this.overlayRef.detachments();\n\n    // If the overlay is torn down externally (parent destroyed, app shutdown, etc.),\n    // ensure stack/focus state is cleaned up.\n    detached$.subscribe(() => this.dispose());\n\n    outputToObservable(this.containerInstance.cancelTriggered)\n      .pipe(takeUntil(detached$))\n      .subscribe(() => this.trigger(eTriggerAction.CANCEL));\n    outputToObservable(this.containerInstance.okTriggered)\n      .pipe(takeUntil(detached$))\n      .subscribe(() => this.trigger(eTriggerAction.OK));\n\n    if (config.zMaskClosable ?? true) {\n      this.overlayRef\n        .outsidePointerEvents()\n        .pipe(takeUntil(detached$))\n        .subscribe(() => this.close());\n    }\n\n    this.overlayRef\n      .keydownEvents()\n      .pipe(\n        filter(event => ESCAPE_KEYS.includes(event.key as (typeof ESCAPE_KEYS)[number])),\n        takeUntil(detached$),\n      )\n      .subscribe(event => {\n        if (this.isTopmost()) {\n          event.preventDefault();\n          this.close();\n        }\n      });\n  }\n\n  /** Internal: set the component instance once attached. */\n  setComponentInstance(instance: T | null) {\n    this._componentInstance.set(instance);\n  }\n\n  close(result?: R) {\n    if (this._isClosing()) return;\n\n    this._isClosing.set(true);\n    this._result.set(result);\n\n    if (isPlatformBrowser(this.platformId) && this.containerInstance) {\n      const hostElement = this.containerInstance.getNativeElement();\n      hostElement.classList.add('sheet-leave');\n    }\n\n    this.disposeTimer = setTimeout(() => this.dispose(), this.animationDuration);\n  }\n\n  private dispose() {\n    if (this.disposed) return;\n    this.disposed = true;\n\n    if (this.disposeTimer !== null) {\n      clearTimeout(this.disposeTimer);\n      this.disposeTimer = null;\n    }\n\n    if (this.overlayRef) {\n      if (this.overlayRef.hasAttached()) {\n        this.overlayRef.detachBackdrop();\n      }\n      this.overlayRef.dispose();\n    }\n\n    const idx = ZardSheetRef.stack.indexOf(this as unknown as ZardSheetRef);\n    if (idx >= 0) ZardSheetRef.stack.splice(idx, 1);\n\n    if (isPlatformBrowser(this.platformId) && this.previouslyFocusedElement?.isConnected) {\n      this.previouslyFocusedElement.focus();\n    }\n  }\n\n  private isTopmost(): boolean {\n    return ZardSheetRef.stack[ZardSheetRef.stack.length - 1] === (this as unknown as ZardSheetRef);\n  }\n\n  private trigger(action: eTriggerAction) {\n    const trigger = action === eTriggerAction.OK ? this.config.zOnOk : this.config.zOnCancel;\n\n    if (trigger instanceof EventEmitter) {\n      trigger.emit(this._componentInstance() as T);\n    } else if (typeof trigger === 'function') {\n      const result = trigger(this._componentInstance() as T) as R | false;\n      if (result !== false) {\n        this.close(result as R);\n      }\n    } else {\n      this.close();\n    }\n  }\n}\n"
    },
    {
      "name": "sheet.imports.ts",
      "content": "import { OverlayModule } from '@angular/cdk/overlay';\nimport { PortalModule } from '@angular/cdk/portal';\n\nimport { ZardSheetComponent } from '@/shared/components/sheet/sheet.component';\n\nexport const ZardSheetImports = [ZardSheetComponent, OverlayModule, PortalModule] as const;\n"
    },
    {
      "name": "sheet.service.ts",
      "content": "import { type ComponentType, Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay';\nimport { ComponentPortal, TemplatePortal } from '@angular/cdk/portal';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n  inject,\n  Injectable,\n  InjectionToken,\n  Injector,\n  PLATFORM_ID,\n  TemplateRef,\n  type ViewContainerRef,\n} from '@angular/core';\n\nimport { ZardSheetRef } from './sheet-ref';\nimport { ZardSheetComponent, ZardSheetOptions } from './sheet.component';\n\ntype ContentType<T> = ComponentType<T> | TemplateRef<T> | string;\n\nexport const Z_SHEET_DATA = new InjectionToken<unknown>('Z_SHEET_DATA');\n\n/**\n * Type-safe accessor for the data passed to a sheet via {@link ZardSheetOptions.zData}.\n *\n * Must be called from an injection context (component constructor / field initializer).\n *\n * @example\n * private readonly data = injectSheetData<MyData>();\n */\nexport function injectSheetData<T>(): T {\n  return inject(Z_SHEET_DATA) as T;\n}\n\n@Injectable({\n  providedIn: 'root',\n})\nexport class ZardSheetService {\n  private readonly overlay = inject(Overlay);\n  private readonly injector = inject(Injector);\n  private readonly platformId = inject(PLATFORM_ID);\n\n  /**\n   * Opens a sheet with the given configuration.\n   *\n   * On non-browser platforms (SSR / build) the returned `ZardSheetRef` is a\n   * no-op that resolves cleanly when calling `close()`.\n   */\n  create<T, U = unknown>(config: ZardSheetOptions<T, U>): ZardSheetRef<T> {\n    if (!isPlatformBrowser(this.platformId)) {\n      return new ZardSheetRef<T>(null, config, null, this.platformId);\n    }\n\n    const overlayRef = this.createOverlay();\n    const sheetContainer = this.attachSheetContainer<T, U>(overlayRef, config);\n    const sheetRef = this.attachSheetContent<T, U>(\n      config.zContent as ContentType<T>,\n      sheetContainer,\n      overlayRef,\n      config,\n    );\n\n    sheetContainer.sheetRef = sheetRef;\n\n    return sheetRef;\n  }\n\n  private createOverlay(): OverlayRef {\n    return this.overlay.create(\n      new OverlayConfig({\n        hasBackdrop: true,\n        backdropClass: ['bg-black/10', 'supports-backdrop-filter:backdrop-blur-xs'],\n        positionStrategy: this.overlay.position().global(),\n      }),\n    );\n  }\n\n  private attachSheetContainer<T, U>(overlayRef: OverlayRef, config: ZardSheetOptions<T, U>) {\n    const injector = Injector.create({\n      parent: this.injector,\n      providers: [\n        { provide: OverlayRef, useValue: overlayRef },\n        { provide: ZardSheetOptions, useValue: config },\n      ],\n    });\n\n    const containerPortal = new ComponentPortal<ZardSheetComponent<T, U>>(\n      ZardSheetComponent,\n      config.zViewContainerRef,\n      injector,\n    );\n\n    return overlayRef.attach<ZardSheetComponent<T, U>>(containerPortal).instance;\n  }\n\n  private attachSheetContent<T, U>(\n    componentOrTemplateRef: ContentType<T>,\n    sheetContainer: ZardSheetComponent<T, U>,\n    overlayRef: OverlayRef,\n    config: ZardSheetOptions<T, U>,\n  ): ZardSheetRef<T> {\n    const sheetRef = new ZardSheetRef<T>(overlayRef, config, sheetContainer, this.platformId);\n\n    if (componentOrTemplateRef instanceof TemplateRef) {\n      // CDK's TemplatePortal type requires a ViewContainerRef even though it tolerates null at runtime,\n      // and types the template context as T (the template's data shape) — we expose `sheetRef` instead.\n      const vcr = (config.zViewContainerRef ?? null) as unknown as ViewContainerRef;\n      const ctx = { sheetRef } as unknown as T;\n      sheetContainer.attachTemplatePortal(new TemplatePortal(componentOrTemplateRef, vcr, ctx));\n    } else if (componentOrTemplateRef != null && typeof componentOrTemplateRef !== 'string') {\n      // Guard against a missing `zContent`: without it, `undefined` reaches ComponentPortal and\n      // Angular throws NG0919 (DEF_TYPE_UNDEFINED) while creating the component.\n      const injector = this.createInjector<T, U>(sheetRef, config);\n      const contentRef = sheetContainer.attachComponentPortal<T>(\n        new ComponentPortal(componentOrTemplateRef, config.zViewContainerRef, injector),\n      );\n      sheetRef.setComponentInstance(contentRef.instance);\n    }\n\n    return sheetRef;\n  }\n\n  private createInjector<T, U>(sheetRef: ZardSheetRef<T>, config: ZardSheetOptions<T, U>): Injector {\n    return Injector.create({\n      parent: this.injector,\n      providers: [\n        { provide: ZardSheetRef, useValue: sheetRef },\n        { provide: Z_SHEET_DATA, useValue: config.zData },\n      ],\n    });\n  }\n}\n"
    },
    {
      "name": "index.ts",
      "content": "export { type OnClickCallback as SheetOnClickCallback } from '@/shared/components/sheet/sheet.component';\nexport { ZardSheetComponent, ZardSheetOptions } from '@/shared/components/sheet/sheet.component';\nexport * from '@/shared/components/sheet/sheet.service';\nexport * from '@/shared/components/sheet/sheet-ref';\nexport * from '@/shared/components/sheet/sheet.imports';\nexport * from '@/shared/components/sheet/sheet.variants';\n"
    }
  ],
  "registryDependencies": [
    "button"
  ],
  "demos": [
    {
      "name": "no-close-button.ts",
      "content": "import { ChangeDetectionStrategy, Component, inject } from '@angular/core';\n\nimport { ZardButtonComponent } from '@/shared/components/button';\nimport { ZardSheetService } from '@/shared/components/sheet/sheet.service';\n\n@Component({\n  selector: 'zard-demo-sheet-no-close-button',\n  imports: [ZardButtonComponent],\n  template: `\n    <button type=\"button\" z-button zType=\"outline\" (click)=\"openSheet()\">Open Sheet</button>\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ZardDemoSheetNoCloseButtonComponent {\n  private readonly sheetService = inject(ZardSheetService);\n\n  openSheet() {\n    this.sheetService.create({\n      zTitle: 'No Close Button',\n      zDescription: \"This sheet doesn't have a close button in the top-right corner. Click outside to close.\",\n      zClosable: false,\n      zHideFooter: true,\n    });\n  }\n}\n"
    },
    {
      "name": "preview.ts",
      "content": "import { ChangeDetectionStrategy, Component, inject } from '@angular/core';\nimport { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';\n\nimport { ZardButtonComponent } from '@/shared/components/button';\nimport { ZardInputComponent } from '@/shared/components/input';\nimport { ZardSheetImports } from '@/shared/components/sheet/sheet.imports';\nimport { ZardSheetService } from '@/shared/components/sheet/sheet.service';\n\n@Component({\n  selector: 'zard-demo-sheet-preview-form',\n  imports: [FormsModule, ReactiveFormsModule, ZardInputComponent],\n  template: `\n    <form [formGroup]=\"form\" class=\"grid flex-1 auto-rows-min gap-6 px-4\">\n      <div class=\"grid gap-3\">\n        <label for=\"sheet-demo-name\" class=\"text-sm leading-none font-medium select-none\">Name</label>\n        <input z-input id=\"sheet-demo-name\" formControlName=\"name\" />\n      </div>\n\n      <div class=\"grid gap-3\">\n        <label for=\"sheet-demo-username\" class=\"text-sm leading-none font-medium select-none\">Username</label>\n        <input z-input id=\"sheet-demo-username\" formControlName=\"username\" />\n      </div>\n    </form>\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  exportAs: 'zardDemoSheetPreviewForm',\n})\nexport class ZardDemoSheetPreviewFormComponent {\n  form = new FormGroup({\n    name: new FormControl('Pedro Duarte'),\n    username: new FormControl('@peduarte'),\n  });\n}\n\n@Component({\n  imports: [ZardButtonComponent, ZardSheetImports],\n  template: `\n    <button type=\"button\" z-button zType=\"outline\" (click)=\"openSheet()\">Open</button>\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ZardDemoSheetPreviewComponent {\n  private readonly sheetService = inject(ZardSheetService);\n\n  openSheet() {\n    this.sheetService.create({\n      zTitle: 'Edit profile',\n      zDescription: `Make changes to your profile here. Click save when you're done.`,\n      zContent: ZardDemoSheetPreviewFormComponent,\n      zOkText: 'Save changes',\n      zCancelText: 'Close',\n      zOnOk: instance => {\n        console.log('Form submitted:', instance.form.value);\n      },\n    });\n  }\n}\n"
    },
    {
      "name": "side.ts",
      "content": "import { ChangeDetectionStrategy, Component, inject } from '@angular/core';\n\nimport { ZardButtonComponent } from '@/shared/components/button';\nimport { ZardSheetService } from '@/shared/components/sheet/sheet.service';\nimport type { ZardSheetVariants } from '@/shared/components/sheet/sheet.variants';\n\ntype SheetSide = NonNullable<ZardSheetVariants['zSide']>;\n\nconst PARAGRAPHS = Array.from({ length: 10 }).map(\n  () =>\n    'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',\n);\n\n@Component({\n  selector: 'zard-demo-sheet-side-content',\n  template: `\n    @for (paragraph of paragraphs; track $index) {\n      <p class=\"mb-2 leading-relaxed\">{{ paragraph }}</p>\n    }\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  host: { class: 'no-scrollbar min-h-0 overflow-y-auto px-4' },\n})\nexport class ZardDemoSheetSideContentComponent {\n  protected readonly paragraphs = PARAGRAPHS;\n}\n\n@Component({\n  imports: [ZardButtonComponent],\n  template: `\n    <div class=\"flex flex-wrap gap-2\">\n      @for (side of sides; track side) {\n        <button type=\"button\" z-button zType=\"outline\" class=\"capitalize\" (click)=\"openSheet(side)\">{{ side }}</button>\n      }\n    </div>\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ZardDemoSheetSideComponent {\n  private readonly sheetService = inject(ZardSheetService);\n\n  protected readonly sides = ['top', 'right', 'bottom', 'left'] as const satisfies readonly SheetSide[];\n\n  openSheet(side: SheetSide) {\n    this.sheetService.create({\n      zTitle: 'Edit profile',\n      zDescription: `Make changes to your profile here. Click save when you're done.`,\n      zContent: ZardDemoSheetSideContentComponent,\n      zSide: side,\n      // Horizontal sheets already fill the viewport height; cap the vertical ones so the\n      // content scrolls instead of pushing the footer off-screen.\n      zCustomClasses: side === 'top' || side === 'bottom' ? 'max-h-[50vh]' : undefined,\n      zOkText: 'Save changes',\n      zCancelText: 'Cancel',\n    });\n  }\n}\n"
    }
  ]
}
