{
  "name": "toggle-group",
  "type": "registry:component",
  "files": [
    {
      "name": "toggle-group.component.ts",
      "content": "import { NgTemplateOutlet } from '@angular/common';\nimport {\n  booleanAttribute,\n  ChangeDetectionStrategy,\n  Component,\n  computed,\n  forwardRef,\n  input,\n  linkedSignal,\n  output,\n  signal,\n  type TemplateRef,\n  ViewEncapsulation,\n} from '@angular/core';\nimport { type ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\n\nimport { NgIcon, type IconName } from '@ng-icons/core';\nimport type { ClassValue } from 'clsx';\n\nimport {\n  toggleVariants,\n  type ZardToggleSizeVariants,\n  type ZardToggleTypeVariants,\n} from '@/shared/components/toggle/toggle.variants';\nimport { mergeClasses } from '@/shared/utils/merge-classes';\n\nimport { toggleGroupItemVariants, toggleGroupVariants } from './toggle-group.variants';\n\nexport interface ZardToggleGroupItem {\n  value: string;\n  label?: string;\n  icon?: IconName;\n  template?: TemplateRef<void>;\n  disabled?: boolean;\n  ariaLabel?: string;\n}\n\ntype OnTouchedType = () => void;\ntype OnChangeType = (value: string | string[]) => void;\n\n@Component({\n  selector: 'z-toggle-group',\n  imports: [NgIcon, NgTemplateOutlet],\n  template: `\n    <div\n      role=\"group\"\n      data-slot=\"toggle-group\"\n      [class]=\"classes()\"\n      [attr.data-variant]=\"zType()\"\n      [attr.data-size]=\"zSize()\"\n      [attr.data-orientation]=\"zOrientation()\"\n      [attr.data-horizontal]=\"zOrientation() === 'horizontal' || null\"\n      [attr.data-vertical]=\"zOrientation() === 'vertical' || null\"\n      [attr.data-spacing]=\"zSpacing()\"\n      [style.--gap]=\"zSpacing()\"\n    >\n      @for (item of zItems(); track item.value) {\n        <button\n          type=\"button\"\n          data-slot=\"toggle-group-item\"\n          [attr.data-variant]=\"zType()\"\n          [attr.data-size]=\"zSize()\"\n          [attr.data-spacing]=\"zSpacing()\"\n          [attr.aria-pressed]=\"isItemPressed(item.value)\"\n          [attr.data-state]=\"isItemPressed(item.value) ? 'on' : 'off'\"\n          [attr.aria-label]=\"item.ariaLabel\"\n          [class]=\"itemClasses()\"\n          [disabled]=\"disabledState() || item.disabled\"\n          (click)=\"toggleItem(item)\"\n        >\n          @if (item.template) {\n            <ng-container [ngTemplateOutlet]=\"item.template\" />\n          } @else {\n            @if (item.icon) {\n              <ng-icon [name]=\"item.icon\" class=\"size-4!\" />\n            }\n            @if (item.label) {\n              <span>{{ item.label }}</span>\n            } @else if (!item.icon) {\n              <span>{{ item.value }}</span>\n            }\n          }\n        </button>\n      }\n    </div>\n  `,\n  providers: [\n    {\n      provide: NG_VALUE_ACCESSOR,\n      useExisting: forwardRef(() => ZardToggleGroupComponent),\n      multi: true,\n    },\n  ],\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  encapsulation: ViewEncapsulation.None,\n  exportAs: 'zToggleGroup',\n})\nexport class ZardToggleGroupComponent implements ControlValueAccessor {\n  readonly class = input<ClassValue>('');\n  readonly zDefaultValue = input<string | string[]>();\n  readonly zDisabled = input(false, { transform: booleanAttribute });\n  readonly zMode = input<'single' | 'multiple'>('multiple');\n  readonly zItemClass = input<ClassValue>('');\n  readonly zItems = input<ZardToggleGroupItem[]>([]);\n  readonly zOrientation = input<'horizontal' | 'vertical'>('horizontal');\n  readonly zSize = input<ZardToggleSizeVariants>('default');\n  readonly zSpacing = input(0);\n  readonly zType = input<ZardToggleTypeVariants>('default');\n  readonly zValue = input<string | string[]>();\n\n  readonly valueChange = output<string | string[]>();\n\n  protected readonly disabledState = linkedSignal(() => this.zDisabled());\n  private readonly internalValue = signal<string | string[] | undefined>(undefined);\n\n  protected readonly classes = computed(() => mergeClasses(toggleGroupVariants(), this.class()));\n\n  protected readonly itemClasses = computed(() =>\n    mergeClasses(\n      toggleGroupItemVariants(),\n      toggleVariants({\n        zType: this.zType(),\n        zSize: this.zSize(),\n      }),\n      this.zItemClass(),\n    ),\n  );\n\n  protected readonly currentValue = computed(() => {\n    const internal = this.internalValue();\n    const input = this.zValue();\n    const defaultVal = this.zDefaultValue();\n\n    if (internal !== undefined) {\n      return internal;\n    }\n    if (input !== undefined) {\n      return input;\n    }\n    if (defaultVal !== undefined) {\n      return defaultVal;\n    }\n\n    return this.zMode() === 'single' ? '' : [];\n  });\n\n  protected isItemPressed(itemValue: string): boolean {\n    const current = this.currentValue();\n    if (this.zMode() === 'single') {\n      return current === itemValue;\n    }\n    return Array.isArray(current) && current.includes(itemValue);\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-empty-function\n  private onTouched: OnTouchedType = () => {};\n  // eslint-disable-next-line @typescript-eslint/no-empty-function\n  private onChangeFn: OnChangeType = () => {};\n\n  toggleItem(item: ZardToggleGroupItem) {\n    if (this.disabledState() || item.disabled) {\n      return;\n    }\n\n    const currentValue = this.currentValue();\n    let newValue: string | string[];\n\n    if (this.zMode() === 'single') {\n      newValue = currentValue === item.value ? '' : item.value;\n    } else {\n      const currentArray = Array.isArray(currentValue) ? currentValue : [];\n      if (currentArray.includes(item.value)) {\n        newValue = currentArray.filter(v => v !== item.value);\n      } else {\n        newValue = [...currentArray, item.value];\n      }\n    }\n\n    this.internalValue.set(newValue);\n    this.valueChange.emit(newValue);\n    this.onChangeFn(newValue);\n    this.onTouched();\n  }\n\n  writeValue(value: string | string[]): void {\n    if (value !== undefined) {\n      this.internalValue.set(value);\n    }\n  }\n\n  registerOnChange(fn: OnChangeType): void {\n    this.onChangeFn = fn;\n  }\n\n  registerOnTouched(fn: OnTouchedType): void {\n    this.onTouched = fn;\n  }\n\n  setDisabledState(isDisabled: boolean): void {\n    this.disabledState.set(isDisabled);\n  }\n}\n"
    },
    {
      "name": "toggle-group.variants.ts",
      "content": "import { cva } from 'class-variance-authority';\n\nexport const toggleGroupVariants = cva(\n  'group/toggle-group flex w-fit flex-row items-center gap-[--spacing(var(--gap))] rounded-lg data-[size=sm]:rounded-[min(var(--radius-md),10px)] data-vertical:flex-col data-vertical:items-stretch',\n);\n\nexport const toggleGroupItemVariants = cva(\n  'shrink-0 group-data-[spacing=0]/toggle-group:rounded-none group-data-[spacing=0]/toggle-group:px-2 focus:z-10 focus-visible:z-10 group-data-[spacing=0]/toggle-group:has-data-[icon=inline-end]:pr-1.5 group-data-[spacing=0]/toggle-group:has-data-[icon=inline-start]:pl-1.5 group-data-horizontal/toggle-group:data-[spacing=0]:first:rounded-l-lg group-data-vertical/toggle-group:data-[spacing=0]:first:rounded-t-lg group-data-horizontal/toggle-group:data-[spacing=0]:last:rounded-r-lg group-data-vertical/toggle-group:data-[spacing=0]:last:rounded-b-lg group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:border-l-0 group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:border-t-0 group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-l group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-t',\n);\n"
    },
    {
      "name": "index.ts",
      "content": "export * from './toggle-group.component';\nexport * from './toggle-group.variants';\n"
    }
  ],
  "registryDependencies": [
    "toggle"
  ],
  "demos": [
    {
      "name": "custom.ts",
      "content": "import { Component, computed, signal, type TemplateRef, viewChild } from '@angular/core';\n\nimport { ZardFieldImports } from '@/shared/components/field';\nimport {\n  ZardToggleGroupComponent,\n  type ZardToggleGroupItem,\n} from '@/shared/components/toggle-group/toggle-group.component';\n\n@Component({\n  selector: 'demo-toggle-group-custom',\n  imports: [ZardToggleGroupComponent, ...ZardFieldImports],\n  template: `\n    <div z-field class=\"w-full\">\n      <label z-field-label for=\"fontToggle\">Font Weight</label>\n      <z-toggle-group\n        id=\"fontToggle\"\n        zItemClass=\"flex size-16 flex-col items-center justify-center rounded-xl\"\n        zMode=\"single\"\n        zType=\"outline\"\n        zSize=\"lg\"\n        [zItems]=\"items()\"\n        [zSpacing]=\"2\"\n        (valueChange)=\"onToggleChange($event)\"\n      />\n      <p z-field-description>\n        Use\n        <code class=\"bg-muted rounded-md px-1 py-0.5 font-mono\">font-{{ fontWeight() }}</code>\n        to set the font weight.\n      </p>\n    </div>\n\n    <ng-template #light>\n      <span class=\"text-2xl leading-none font-light\">Aa</span>\n      <span class=\"text-muted-foreground text-xs\">Light</span>\n    </ng-template>\n\n    <ng-template #normal>\n      <span class=\"text-2xl leading-none font-normal\">Aa</span>\n      <span class=\"text-muted-foreground text-xs\">Normal</span>\n    </ng-template>\n\n    <ng-template #medium>\n      <span class=\"text-2xl leading-none font-medium\">Aa</span>\n      <span class=\"text-muted-foreground text-xs\">Medium</span>\n    </ng-template>\n\n    <ng-template #bold>\n      <span class=\"text-2xl leading-none font-bold\">Aa</span>\n      <span class=\"text-muted-foreground text-xs\">Bold</span>\n    </ng-template>\n  `,\n})\nexport default class ToggleGroupCustomComponent {\n  readonly light = viewChild<TemplateRef<void>>('light');\n  readonly normal = viewChild<TemplateRef<void>>('normal');\n  readonly medium = viewChild<TemplateRef<void>>('medium');\n  readonly bold = viewChild<TemplateRef<void>>('bold');\n\n  protected readonly fontWeight = signal<string>('');\n\n  readonly items = computed<ZardToggleGroupItem[]>(() => [\n    {\n      value: 'light',\n      template: this.light(),\n      ariaLabel: 'Light',\n    },\n    {\n      value: 'normal',\n      template: this.normal(),\n      ariaLabel: 'Normal',\n    },\n    {\n      value: 'medium',\n      template: this.medium(),\n      ariaLabel: 'Medium',\n    },\n    {\n      value: 'bold',\n      template: this.bold(),\n      ariaLabel: 'Bold',\n    },\n  ]);\n\n  onToggleChange(value: string | string[]) {\n    let weight = '';\n    if (Array.isArray(value)) {\n      [weight] = value;\n    } else {\n      weight = value;\n    }\n    this.fontWeight.set(weight);\n  }\n}\n"
    },
    {
      "name": "default.ts",
      "content": "import { Component } from '@angular/core';\n\nimport { provideIcons } from '@ng-icons/core';\nimport { lucideBold, lucideItalic, lucideUnderline } from '@ng-icons/lucide';\n\nimport {\n  ZardToggleGroupComponent,\n  type ZardToggleGroupItem,\n} from '@/shared/components/toggle-group/toggle-group.component';\n\n@Component({\n  selector: 'demo-toggle-group-default',\n  imports: [ZardToggleGroupComponent],\n  template: `\n    <z-toggle-group zMode=\"multiple\" zType=\"outline\" [zItems]=\"items\" (valueChange)=\"onToggleChange($event)\" />\n  `,\n  viewProviders: [\n    provideIcons({\n      lucideBold,\n      lucideItalic,\n      lucideUnderline,\n    }),\n  ],\n})\nexport default class ToggleGroupDefaultComponent {\n  items: ZardToggleGroupItem[] = [\n    {\n      value: 'bold',\n      icon: 'lucideBold',\n      ariaLabel: 'Toggle bold',\n    },\n    {\n      value: 'italic',\n      icon: 'lucideItalic',\n      ariaLabel: 'Toggle italic',\n    },\n    {\n      value: 'underline',\n      icon: 'lucideUnderline',\n      ariaLabel: 'Toggle underline',\n    },\n  ];\n\n  onToggleChange(value: string | string[]) {\n    console.log('Toggle group changed:', value);\n  }\n}\n"
    },
    {
      "name": "disabled.ts",
      "content": "import { Component } from '@angular/core';\n\nimport { provideIcons } from '@ng-icons/core';\nimport { lucideBold, lucideItalic, lucideUnderline } from '@ng-icons/lucide';\n\nimport {\n  ZardToggleGroupComponent,\n  type ZardToggleGroupItem,\n} from '@/shared/components/toggle-group/toggle-group.component';\n\n@Component({\n  selector: 'demo-toggle-group-disabled',\n  imports: [ZardToggleGroupComponent],\n  template: `\n    <z-toggle-group [zDisabled]=\"true\" zMode=\"multiple\" [zItems]=\"items\" (valueChange)=\"onToggleChange($event)\" />\n  `,\n  viewProviders: [\n    provideIcons({\n      lucideBold,\n      lucideItalic,\n      lucideUnderline,\n    }),\n  ],\n})\nexport default class ToggleGroupDisabledComponent {\n  items: ZardToggleGroupItem[] = [\n    {\n      value: 'bold',\n      icon: 'lucideBold',\n      ariaLabel: 'Toggle bold',\n    },\n    {\n      value: 'italic',\n      icon: 'lucideItalic',\n      ariaLabel: 'Toggle italic',\n    },\n    {\n      value: 'underline',\n      icon: 'lucideUnderline',\n      ariaLabel: 'Toggle underline',\n    },\n  ];\n\n  onToggleChange(value: string | string[]) {\n    console.log('Toggle group changed:', value);\n  }\n}\n"
    },
    {
      "name": "outline.ts",
      "content": "import { Component } from '@angular/core';\n\nimport {\n  ZardToggleGroupComponent,\n  type ZardToggleGroupItem,\n} from '@/shared/components/toggle-group/toggle-group.component';\n\n@Component({\n  selector: 'demo-toggle-group-outline',\n  imports: [ZardToggleGroupComponent],\n  template: `\n    <z-toggle-group\n      zDefaultValue=\"all\"\n      zMode=\"single\"\n      zType=\"outline\"\n      [zItems]=\"items\"\n      (valueChange)=\"onToggleChange($event)\"\n    />\n  `,\n})\nexport default class ToggleGroupOutlineComponent {\n  items: ZardToggleGroupItem[] = [\n    {\n      value: 'all',\n      label: 'All',\n      ariaLabel: 'Toggle all',\n    },\n    {\n      value: 'missed',\n      label: 'Missed',\n      ariaLabel: 'Toggle missed',\n    },\n  ];\n\n  onToggleChange(value: string | string[]) {\n    console.log('Selected:', value);\n  }\n}\n"
    },
    {
      "name": "sizes.ts",
      "content": "import { Component } from '@angular/core';\n\nimport {\n  ZardToggleGroupComponent,\n  type ZardToggleGroupItem,\n} from '@/shared/components/toggle-group/toggle-group.component';\n\n@Component({\n  selector: 'demo-toggle-group-sizes',\n  imports: [ZardToggleGroupComponent],\n  template: `\n    <div class=\"space-y-4\">\n      <div>\n        <z-toggle-group\n          zDefaultValue=\"top\"\n          zMode=\"single\"\n          zSize=\"sm\"\n          [zItems]=\"items\"\n          zType=\"outline\"\n          (valueChange)=\"onToggleChange($event)\"\n        />\n      </div>\n      <div>\n        <z-toggle-group\n          zDefaultValue=\"top\"\n          zMode=\"single\"\n          zSize=\"lg\"\n          [zItems]=\"items\"\n          zType=\"outline\"\n          (valueChange)=\"onToggleChange($event)\"\n        />\n      </div>\n    </div>\n  `,\n})\nexport default class ToggleGroupSizesComponent {\n  items: ZardToggleGroupItem[] = [\n    {\n      value: 'top',\n      label: 'Top',\n      ariaLabel: 'Toggle top',\n    },\n    {\n      value: 'bottom',\n      label: 'Bottom',\n      ariaLabel: 'Toggle bottom',\n    },\n    {\n      value: 'left',\n      label: 'Left',\n      ariaLabel: 'Toggle left',\n    },\n    {\n      value: 'right',\n      label: 'Right',\n      ariaLabel: 'Toggle right',\n    },\n  ];\n\n  onToggleChange(value: string | string[]) {\n    console.log('Selected:', value);\n  }\n}\n"
    },
    {
      "name": "spacing.ts",
      "content": "import { Component } from '@angular/core';\n\nimport {\n  ZardToggleGroupComponent,\n  type ZardToggleGroupItem,\n} from '@/shared/components/toggle-group/toggle-group.component';\n\n@Component({\n  selector: 'demo-toggle-group-spacing',\n  imports: [ZardToggleGroupComponent],\n  template: `\n    <z-toggle-group\n      zDefaultValue=\"top\"\n      zMode=\"single\"\n      zSize=\"sm\"\n      zType=\"outline\"\n      [zItems]=\"items\"\n      [zSpacing]=\"2\"\n      (valueChange)=\"onToggleChange($event)\"\n    />\n  `,\n})\nexport default class ToggleGroupSpacingComponent {\n  items: ZardToggleGroupItem[] = [\n    {\n      value: 'top',\n      label: 'Top',\n      ariaLabel: 'Toggle top',\n    },\n    {\n      value: 'bottom',\n      label: 'Bottom',\n      ariaLabel: 'Toggle bottom',\n    },\n    {\n      value: 'left',\n      label: 'Left',\n      ariaLabel: 'Toggle left',\n    },\n    {\n      value: 'right',\n      label: 'Right',\n      ariaLabel: 'Toggle right',\n    },\n  ];\n\n  onToggleChange(value: string | string[]) {\n    console.log('Selected:', value);\n  }\n}\n"
    },
    {
      "name": "vertical.ts",
      "content": "import { Component } from '@angular/core';\n\nimport { provideIcons } from '@ng-icons/core';\nimport { lucideBold, lucideItalic, lucideUnderline } from '@ng-icons/lucide';\n\nimport {\n  ZardToggleGroupComponent,\n  type ZardToggleGroupItem,\n} from '@/shared/components/toggle-group/toggle-group.component';\n\n@Component({\n  selector: 'demo-toggle-group-vertical',\n  imports: [ZardToggleGroupComponent],\n  template: `\n    <z-toggle-group\n      zMode=\"multiple\"\n      zOrientation=\"vertical\"\n      [zDefaultValue]=\"['bold', 'italic']\"\n      [zItems]=\"items\"\n      [zSpacing]=\"1\"\n      (valueChange)=\"onToggleChange($event)\"\n    />\n  `,\n  viewProviders: [\n    provideIcons({\n      lucideBold,\n      lucideItalic,\n      lucideUnderline,\n    }),\n  ],\n})\nexport default class ToggleGroupVerticalComponent {\n  items: ZardToggleGroupItem[] = [\n    {\n      value: 'bold',\n      icon: 'lucideBold',\n      ariaLabel: 'Toggle bold',\n    },\n    {\n      value: 'italic',\n      icon: 'lucideItalic',\n      ariaLabel: 'Toggle italic',\n    },\n    {\n      value: 'underline',\n      icon: 'lucideUnderline',\n      ariaLabel: 'Toggle underline',\n    },\n  ];\n\n  onToggleChange(value: string | string[]) {\n    console.log('Toggle group changed:', value);\n  }\n}\n"
    }
  ]
}
