@sonny-ui/core 0.1.0-alpha.12 → 0.1.0-alpha.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,8 +3,8 @@ import { twMerge } from 'tailwind-merge';
3
3
  import { cva } from 'class-variance-authority';
4
4
  export { cva } from 'class-variance-authority';
5
5
  import * as i0 from '@angular/core';
6
- import { inject, PLATFORM_ID, signal, computed, Injectable, InjectionToken, makeEnvironmentProviders, provideEnvironmentInitializer, input, Directive, ChangeDetectionStrategy, Component, ElementRef, model, viewChild, effect, forwardRef, HostListener, Injector, afterNextRender, Renderer2, output, contentChildren } from '@angular/core';
7
- import { DOCUMENT, isPlatformBrowser } from '@angular/common';
6
+ import { inject, PLATFORM_ID, signal, computed, Injectable, InjectionToken, makeEnvironmentProviders, provideEnvironmentInitializer, input, Directive, ChangeDetectionStrategy, Component, ElementRef, model, viewChild, forwardRef, HostListener, TemplateRef, output, contentChildren, contentChild, effect, untracked, Injector, afterNextRender, Renderer2 } from '@angular/core';
7
+ import { DOCUMENT, isPlatformBrowser, NgTemplateOutlet } from '@angular/common';
8
8
  import { Dialog, DialogRef } from '@angular/cdk/dialog';
9
9
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
10
10
  import { createGlobalPositionStrategy } from '@angular/cdk/overlay';
@@ -107,7 +107,7 @@ class SnyButtonDirective {
107
107
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
108
108
  loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
109
109
  class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
110
- computedClass = computed(() => cn(buttonVariants({ variant: this.variant(), size: this.size() }), this.loading() && 'relative cursor-wait', this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
110
+ computedClass = computed(() => cn(buttonVariants({ variant: this.variant(), size: this.size() }), this.loading() && 'cursor-wait opacity-70', this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
111
111
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyButtonDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
112
112
  static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnyButtonDirective, isStandalone: true, selector: "button[snyBtn], a[snyBtn]", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "computedClass()", "attr.aria-disabled": "disabled() || loading() || null", "attr.disabled": "disabled() || loading() || null", "attr.tabindex": "(disabled() || loading()) ? -1 : null" } }, ngImport: i0 });
113
113
  }
@@ -1079,19 +1079,7 @@ class SnyComboboxComponent {
1079
1079
  resizeHandler = null;
1080
1080
  _onChange = () => { };
1081
1081
  onTouched = () => { };
1082
- _writing = false;
1083
- constructor() {
1084
- effect(() => {
1085
- const val = this.value();
1086
- if (this._writing) {
1087
- this._writing = false;
1088
- return;
1089
- }
1090
- this._onChange(val);
1091
- });
1092
- }
1093
1082
  writeValue(val) {
1094
- this._writing = true;
1095
1083
  this.value.set(val ?? '');
1096
1084
  }
1097
1085
  registerOnChange(fn) {
@@ -1186,6 +1174,7 @@ class SnyComboboxComponent {
1186
1174
  }
1187
1175
  select(opt) {
1188
1176
  this.value.set(opt.value);
1177
+ this._onChange(opt.value);
1189
1178
  this.close();
1190
1179
  }
1191
1180
  onKeydown(event) {
@@ -1258,7 +1247,7 @@ class SnyComboboxComponent {
1258
1247
 
1259
1248
  <!-- Options list -->
1260
1249
  @if (filtered().length > 0) {
1261
- <ul role="listbox" class="max-h-60 overflow-auto p-1">
1250
+ <ul role="listbox" class="max-h-60 overflow-auto p-1 sny-scrollbar">
1262
1251
  @for (opt of filtered(); track opt.value; let i = $index) {
1263
1252
  <li
1264
1253
  role="option"
@@ -1336,7 +1325,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
1336
1325
 
1337
1326
  <!-- Options list -->
1338
1327
  @if (filtered().length > 0) {
1339
- <ul role="listbox" class="max-h-60 overflow-auto p-1">
1328
+ <ul role="listbox" class="max-h-60 overflow-auto p-1 sny-scrollbar">
1340
1329
  @for (opt of filtered(); track opt.value; let i = $index) {
1341
1330
  <li
1342
1331
  role="option"
@@ -1362,7 +1351,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
1362
1351
  }
1363
1352
  `,
1364
1353
  }]
1365
- }], ctorParameters: () => [], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], triggerRef: [{ type: i0.ViewChild, args: ['triggerEl', { isSignal: true }] }], searchRef: [{ type: i0.ViewChild, args: ['searchEl', { isSignal: true }] }], dropdownRef: [{ type: i0.ViewChild, args: ['dropdownEl', { isSignal: true }] }], onDocumentClick: [{
1354
+ }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], triggerRef: [{ type: i0.ViewChild, args: ['triggerEl', { isSignal: true }] }], searchRef: [{ type: i0.ViewChild, args: ['searchEl', { isSignal: true }] }], dropdownRef: [{ type: i0.ViewChild, args: ['dropdownEl', { isSignal: true }] }], onDocumentClick: [{
1366
1355
  type: HostListener,
1367
1356
  args: ['document:click', ['$event']]
1368
1357
  }] } });
@@ -1469,19 +1458,7 @@ class SnySwitchComponent {
1469
1458
  isDisabled = computed(() => this.disabled() || this._disabledByCva(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
1470
1459
  _onChange = () => { };
1471
1460
  onTouched = () => { };
1472
- _writing = false;
1473
- constructor() {
1474
- effect(() => {
1475
- const val = this.checked();
1476
- if (this._writing) {
1477
- this._writing = false;
1478
- return;
1479
- }
1480
- this._onChange(val);
1481
- });
1482
- }
1483
1461
  writeValue(val) {
1484
- this._writing = true;
1485
1462
  this.checked.set(val ?? false);
1486
1463
  }
1487
1464
  registerOnChange(fn) {
@@ -1493,6 +1470,11 @@ class SnySwitchComponent {
1493
1470
  setDisabledState(isDisabled) {
1494
1471
  this._disabledByCva.set(isDisabled);
1495
1472
  }
1473
+ toggle() {
1474
+ const newVal = !this.checked();
1475
+ this.checked.set(newVal);
1476
+ this._onChange(newVal);
1477
+ }
1496
1478
  trackClass = computed(() => cn(switchTrackVariants({ size: this.size() }), this.checked() ? 'bg-primary' : 'bg-input', this.class()), ...(ngDevMode ? [{ debugName: "trackClass" }] : /* istanbul ignore next */ []));
1497
1479
  thumbClass = computed(() => cn('pointer-events-none block rounded-full bg-background shadow-lg ring-0 transition-transform', switchThumbSize[this.size()], this.checked() ? switchThumbTranslate[this.size()] : 'translate-x-0'), ...(ngDevMode ? [{ debugName: "thumbClass" }] : /* istanbul ignore next */ []));
1498
1480
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySwitchComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -1505,7 +1487,7 @@ class SnySwitchComponent {
1505
1487
  [attr.aria-checked]="checked()"
1506
1488
  [disabled]="isDisabled()"
1507
1489
  [class]="trackClass()"
1508
- (click)="checked.set(!checked())"
1490
+ (click)="toggle()"
1509
1491
  (blur)="onTouched()"
1510
1492
  >
1511
1493
  <span [class]="thumbClass()"></span>
@@ -1529,14 +1511,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
1529
1511
  [attr.aria-checked]="checked()"
1530
1512
  [disabled]="isDisabled()"
1531
1513
  [class]="trackClass()"
1532
- (click)="checked.set(!checked())"
1514
+ (click)="toggle()"
1533
1515
  (blur)="onTouched()"
1534
1516
  >
1535
1517
  <span [class]="thumbClass()"></span>
1536
1518
  </button>
1537
1519
  `,
1538
1520
  }]
1539
- }], ctorParameters: () => [], propDecorators: { checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
1521
+ }], propDecorators: { checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
1540
1522
 
1541
1523
  const toggleVariants = cva('inline-flex items-center justify-center rounded-sm text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50', {
1542
1524
  variants: {
@@ -1565,19 +1547,7 @@ class SnyToggleDirective {
1565
1547
  isDisabled = computed(() => this._disabledByCva(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
1566
1548
  _onChange = () => { };
1567
1549
  onTouched = () => { };
1568
- _writing = false;
1569
- constructor() {
1570
- effect(() => {
1571
- const val = this.pressed();
1572
- if (this._writing) {
1573
- this._writing = false;
1574
- return;
1575
- }
1576
- this._onChange(val);
1577
- });
1578
- }
1579
1550
  writeValue(val) {
1580
- this._writing = true;
1581
1551
  this.pressed.set(val ?? false);
1582
1552
  }
1583
1553
  registerOnChange(fn) {
@@ -1592,7 +1562,9 @@ class SnyToggleDirective {
1592
1562
  toggle() {
1593
1563
  if (this.isDisabled())
1594
1564
  return;
1595
- this.pressed.set(!this.pressed());
1565
+ const newVal = !this.pressed();
1566
+ this.pressed.set(newVal);
1567
+ this._onChange(newVal);
1596
1568
  }
1597
1569
  computedClass = computed(() => cn(toggleVariants({ variant: this.variant(), size: this.size() }), this.pressed() ? 'bg-accent text-accent-foreground' : '', this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
1598
1570
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyToggleDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
@@ -1616,7 +1588,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
1616
1588
  '(blur)': 'onTouched()',
1617
1589
  },
1618
1590
  }]
1619
- }], ctorParameters: () => [], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], pressed: [{ type: i0.Input, args: [{ isSignal: true, alias: "pressed", required: false }] }, { type: i0.Output, args: ["pressedChange"] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
1591
+ }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], pressed: [{ type: i0.Input, args: [{ isSignal: true, alias: "pressed", required: false }] }, { type: i0.Output, args: ["pressedChange"] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
1620
1592
 
1621
1593
  const sliderTrackVariants = cva('relative w-full rounded-full bg-secondary cursor-pointer', {
1622
1594
  variants: {
@@ -1651,19 +1623,7 @@ class SnySliderComponent {
1651
1623
  upHandler = null;
1652
1624
  _onChange = () => { };
1653
1625
  onTouched = () => { };
1654
- _writing = false;
1655
- constructor() {
1656
- effect(() => {
1657
- const val = this.value();
1658
- if (this._writing) {
1659
- this._writing = false;
1660
- return;
1661
- }
1662
- this._onChange(val);
1663
- });
1664
- }
1665
1626
  writeValue(val) {
1666
- this._writing = true;
1667
1627
  this.value.set(val ?? 0);
1668
1628
  }
1669
1629
  registerOnChange(fn) {
@@ -1693,7 +1653,9 @@ class SnySliderComponent {
1693
1653
  const percent = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
1694
1654
  const raw = this.min() + percent * (this.max() - this.min());
1695
1655
  const stepped = Math.round(raw / this.step()) * this.step();
1696
- this.value.set(Math.max(this.min(), Math.min(this.max(), stepped)));
1656
+ const clamped = Math.max(this.min(), Math.min(this.max(), stepped));
1657
+ this.value.set(clamped);
1658
+ this._onChange(clamped);
1697
1659
  }
1698
1660
  onTrackMousedown(event) {
1699
1661
  if (this.isDisabled())
@@ -1730,26 +1692,31 @@ class SnySliderComponent {
1730
1692
  if (this.isDisabled())
1731
1693
  return;
1732
1694
  const step = this.step();
1695
+ let newVal;
1733
1696
  switch (event.key) {
1734
1697
  case 'ArrowRight':
1735
1698
  case 'ArrowUp':
1736
1699
  event.preventDefault();
1737
- this.value.set(Math.min(this.max(), this.value() + step));
1700
+ newVal = Math.min(this.max(), this.value() + step);
1738
1701
  break;
1739
1702
  case 'ArrowLeft':
1740
1703
  case 'ArrowDown':
1741
1704
  event.preventDefault();
1742
- this.value.set(Math.max(this.min(), this.value() - step));
1705
+ newVal = Math.max(this.min(), this.value() - step);
1743
1706
  break;
1744
1707
  case 'Home':
1745
1708
  event.preventDefault();
1746
- this.value.set(this.min());
1709
+ newVal = this.min();
1747
1710
  break;
1748
1711
  case 'End':
1749
1712
  event.preventDefault();
1750
- this.value.set(this.max());
1713
+ newVal = this.max();
1751
1714
  break;
1752
1715
  }
1716
+ if (newVal !== undefined) {
1717
+ this.value.set(newVal);
1718
+ this._onChange(newVal);
1719
+ }
1753
1720
  }
1754
1721
  removeListeners() {
1755
1722
  if (this.moveHandler) {
@@ -1828,7 +1795,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
1828
1795
  </div>
1829
1796
  `,
1830
1797
  }]
1831
- }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], trackRef: [{ type: i0.ViewChild, args: ['trackEl', { isSignal: true }] }] } });
1798
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], trackRef: [{ type: i0.ViewChild, args: ['trackEl', { isSignal: true }] }] } });
1832
1799
 
1833
1800
  const loaderVariants = cva('inline-flex items-center justify-center text-current', {
1834
1801
  variants: {
@@ -2074,19 +2041,7 @@ class SnySelectComponent {
2074
2041
  resizeHandler = null;
2075
2042
  _onChange = () => { };
2076
2043
  onTouched = () => { };
2077
- _writing = false;
2078
- constructor() {
2079
- effect(() => {
2080
- const val = this.value();
2081
- if (this._writing) {
2082
- this._writing = false;
2083
- return;
2084
- }
2085
- this._onChange(val);
2086
- });
2087
- }
2088
2044
  writeValue(val) {
2089
- this._writing = true;
2090
2045
  this.value.set(val ?? '');
2091
2046
  }
2092
2047
  registerOnChange(fn) {
@@ -2164,6 +2119,7 @@ class SnySelectComponent {
2164
2119
  }
2165
2120
  select(opt) {
2166
2121
  this.value.set(opt.value);
2122
+ this._onChange(opt.value);
2167
2123
  this.close();
2168
2124
  }
2169
2125
  onTriggerKeydown(event) {
@@ -2228,7 +2184,7 @@ class SnySelectComponent {
2228
2184
  #dropdownEl
2229
2185
  class="fixed z-50 rounded-sm border border-border bg-popover text-popover-foreground shadow-md"
2230
2186
  >
2231
- <ul role="listbox" class="max-h-60 overflow-auto p-1">
2187
+ <ul role="listbox" class="max-h-60 overflow-auto p-1 sny-scrollbar">
2232
2188
  @for (opt of options(); track opt.value; let i = $index) {
2233
2189
  <li
2234
2190
  role="option"
@@ -2286,7 +2242,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
2286
2242
  #dropdownEl
2287
2243
  class="fixed z-50 rounded-sm border border-border bg-popover text-popover-foreground shadow-md"
2288
2244
  >
2289
- <ul role="listbox" class="max-h-60 overflow-auto p-1">
2245
+ <ul role="listbox" class="max-h-60 overflow-auto p-1 sny-scrollbar">
2290
2246
  @for (opt of options(); track opt.value; let i = $index) {
2291
2247
  <li
2292
2248
  role="option"
@@ -2308,7 +2264,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
2308
2264
  }
2309
2265
  `,
2310
2266
  }]
2311
- }], ctorParameters: () => [], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], triggerRef: [{ type: i0.ViewChild, args: ['triggerEl', { isSignal: true }] }], dropdownRef: [{ type: i0.ViewChild, args: ['dropdownEl', { isSignal: true }] }], onDocumentClick: [{
2267
+ }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], triggerRef: [{ type: i0.ViewChild, args: ['triggerEl', { isSignal: true }] }], dropdownRef: [{ type: i0.ViewChild, args: ['dropdownEl', { isSignal: true }] }], onDocumentClick: [{
2312
2268
  type: HostListener,
2313
2269
  args: ['document:click', ['$event']]
2314
2270
  }] } });
@@ -2461,226 +2417,1366 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
2461
2417
  }]
2462
2418
  }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
2463
2419
 
2464
- class SnySheetRef {
2465
- cdkRef;
2466
- constructor(cdkRef) {
2467
- this.cdkRef = cdkRef;
2468
- }
2469
- close(result) {
2470
- this.cdkRef.close(result);
2471
- }
2472
- get closed() {
2473
- return this.cdkRef.closed;
2474
- }
2475
- }
2476
-
2477
- const DEFAULT_SHEET_CONFIG = {
2478
- side: 'right',
2479
- closeOnBackdrop: true,
2480
- closeOnEsc: true,
2481
- };
2482
- const SHEET_PANEL_CLASS = {
2483
- right: 'sny-sheet-right',
2484
- left: 'sny-sheet-left',
2485
- top: 'sny-sheet-top',
2486
- bottom: 'sny-sheet-bottom',
2487
- };
2488
-
2489
- const SNY_SHEET_DATA = new InjectionToken('SNY_SHEET_DATA');
2490
- class SnySheetService {
2491
- cdkDialog = inject(Dialog);
2492
- injector = inject(Injector);
2493
- open(component, config = {}) {
2494
- const merged = { ...DEFAULT_SHEET_CONFIG, ...config };
2495
- const side = merged.side ?? 'right';
2496
- const disableClose = !merged.closeOnBackdrop || !merged.closeOnEsc;
2497
- const overlay = this._getOverlayConfig(side);
2498
- const cdkRef = this.cdkDialog.open(component, {
2499
- disableClose,
2500
- hasBackdrop: true,
2501
- backdropClass: 'sny-dialog-backdrop',
2502
- panelClass: ['sny-sheet-panel', SHEET_PANEL_CLASS[side]],
2503
- positionStrategy: overlay.positionStrategy,
2504
- width: overlay.width,
2505
- maxWidth: overlay.maxWidth,
2506
- height: overlay.height,
2507
- maxHeight: overlay.maxHeight,
2508
- ariaLabelledBy: merged.ariaLabelledBy,
2509
- ariaDescribedBy: merged.ariaDescribedBy,
2510
- data: merged.data,
2511
- providers: merged.data != null
2512
- ? [{ provide: SNY_SHEET_DATA, useValue: merged.data }]
2513
- : [],
2514
- });
2515
- if (disableClose) {
2516
- if (merged.closeOnBackdrop) {
2517
- const sub = cdkRef.backdropClick.subscribe(() => cdkRef.close());
2518
- cdkRef.closed.subscribe(() => sub.unsubscribe());
2519
- }
2520
- if (merged.closeOnEsc) {
2521
- const sub = cdkRef.keydownEvents.subscribe(event => {
2522
- if (event.key === 'Escape')
2523
- cdkRef.close();
2524
- });
2525
- cdkRef.closed.subscribe(() => sub.unsubscribe());
2526
- }
2527
- }
2528
- return new SnySheetRef(cdkRef);
2529
- }
2530
- closeAll() {
2531
- this.cdkDialog.closeAll();
2532
- }
2533
- _getOverlayConfig(side) {
2534
- const strategy = createGlobalPositionStrategy(this.injector);
2535
- switch (side) {
2536
- case 'right':
2537
- return {
2538
- positionStrategy: strategy.top('0').right('0'),
2539
- width: '75%',
2540
- maxWidth: '24rem',
2541
- height: '100vh',
2542
- maxHeight: '100vh',
2543
- };
2544
- case 'left':
2545
- return {
2546
- positionStrategy: strategy.top('0').left('0'),
2547
- width: '75%',
2548
- maxWidth: '24rem',
2549
- height: '100vh',
2550
- maxHeight: '100vh',
2551
- };
2552
- case 'top':
2553
- return {
2554
- positionStrategy: strategy.top('0').centerHorizontally(),
2555
- width: '100vw',
2556
- maxWidth: '100vw',
2557
- };
2558
- case 'bottom':
2559
- return {
2560
- positionStrategy: strategy.bottom('0').centerHorizontally(),
2561
- width: '100vw',
2562
- maxWidth: '100vw',
2563
- };
2564
- }
2565
- }
2566
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2567
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetService, providedIn: 'root' });
2568
- }
2569
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetService, decorators: [{
2570
- type: Injectable,
2571
- args: [{ providedIn: 'root' }]
2572
- }] });
2573
-
2574
- class SnySheetHeaderDirective {
2575
- class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
2576
- computedClass = computed(() => cn('flex flex-col space-y-2', this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
2577
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetHeaderDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2578
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnySheetHeaderDirective, isStandalone: true, selector: "[snySheetHeader]", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "computedClass()" } }, ngImport: i0 });
2579
- }
2580
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetHeaderDirective, decorators: [{
2581
- type: Directive,
2582
- args: [{
2583
- selector: '[snySheetHeader]',
2584
- standalone: true,
2585
- host: { '[class]': 'computedClass()' },
2586
- }]
2587
- }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
2588
- class SnySheetTitleDirective {
2589
- class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
2590
- computedClass = computed(() => cn('text-lg font-semibold text-foreground', this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
2591
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetTitleDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2592
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnySheetTitleDirective, isStandalone: true, selector: "[snySheetTitle]", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "computedClass()" } }, ngImport: i0 });
2593
- }
2594
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetTitleDirective, decorators: [{
2595
- type: Directive,
2596
- args: [{
2597
- selector: '[snySheetTitle]',
2598
- standalone: true,
2599
- host: { '[class]': 'computedClass()' },
2600
- }]
2601
- }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
2602
- class SnySheetDescriptionDirective {
2603
- class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
2604
- computedClass = computed(() => cn('text-sm text-muted-foreground', this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
2605
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetDescriptionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2606
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnySheetDescriptionDirective, isStandalone: true, selector: "[snySheetDescription]", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "computedClass()" } }, ngImport: i0 });
2607
- }
2608
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetDescriptionDirective, decorators: [{
2609
- type: Directive,
2610
- args: [{
2611
- selector: '[snySheetDescription]',
2612
- standalone: true,
2613
- host: { '[class]': 'computedClass()' },
2614
- }]
2615
- }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
2616
- class SnySheetContentDirective {
2617
- class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
2618
- computedClass = computed(() => cn('py-4', this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
2619
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2620
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnySheetContentDirective, isStandalone: true, selector: "[snySheetContent]", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "computedClass()" } }, ngImport: i0 });
2621
- }
2622
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetContentDirective, decorators: [{
2623
- type: Directive,
2624
- args: [{
2625
- selector: '[snySheetContent]',
2626
- standalone: true,
2627
- host: { '[class]': 'computedClass()' },
2628
- }]
2629
- }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
2630
- class SnySheetCloseDirective {
2631
- class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
2632
- computedClass = computed(() => cn('absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2', this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
2633
- dialogRef = inject(DialogRef, { optional: true });
2634
- onClick() {
2635
- this.dialogRef?.close();
2636
- }
2637
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetCloseDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2638
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnySheetCloseDirective, isStandalone: true, selector: "[snySheetClose]", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "onClick()" }, properties: { "class": "computedClass()" } }, ngImport: i0 });
2639
- }
2640
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetCloseDirective, decorators: [{
2641
- type: Directive,
2642
- args: [{
2643
- selector: '[snySheetClose]',
2644
- standalone: true,
2645
- host: {
2646
- '[class]': 'computedClass()',
2647
- '(click)': 'onClick()',
2648
- },
2649
- }]
2650
- }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
2651
-
2652
- const alertVariants = cva('relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground', {
2420
+ const paginationItemVariants = cva('inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50', {
2653
2421
  variants: {
2654
2422
  variant: {
2655
- default: 'bg-background text-foreground border-border',
2656
- destructive: 'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive bg-destructive/10',
2657
- success: 'border-green-500/50 text-green-700 dark:text-green-400 dark:border-green-500 [&>svg]:text-green-600 bg-green-50 dark:bg-green-950/30',
2658
- warning: 'border-yellow-500/50 text-yellow-700 dark:text-yellow-400 dark:border-yellow-500 [&>svg]:text-yellow-600 bg-yellow-50 dark:bg-yellow-950/30',
2659
- info: 'border-blue-500/50 text-blue-700 dark:text-blue-400 dark:border-blue-500 [&>svg]:text-blue-600 bg-blue-50 dark:bg-blue-950/30',
2423
+ default: 'bg-background hover:bg-accent hover:text-accent-foreground',
2424
+ outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
2425
+ ghost: 'hover:bg-accent hover:text-accent-foreground',
2426
+ },
2427
+ size: {
2428
+ sm: 'h-8 w-8 text-xs',
2429
+ md: 'h-9 w-9',
2430
+ lg: 'h-10 w-10',
2431
+ },
2432
+ active: {
2433
+ true: 'bg-primary text-primary-foreground hover:bg-primary/90 hover:text-primary-foreground',
2434
+ false: '',
2660
2435
  },
2661
2436
  },
2662
2437
  defaultVariants: {
2663
2438
  variant: 'default',
2439
+ size: 'md',
2440
+ active: false,
2664
2441
  },
2665
2442
  });
2666
2443
 
2667
- class SnyAlertDirective {
2668
- variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
2669
- dismissible = input(false, ...(ngDevMode ? [{ debugName: "dismissible" }] : /* istanbul ignore next */ []));
2670
- class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
2671
- visible = signal(true, ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
2672
- role = computed(() => {
2673
- const v = this.variant();
2674
- return v === 'destructive' || v === 'warning' || v === 'info' ? 'alert' : 'status';
2675
- }, ...(ngDevMode ? [{ debugName: "role" }] : /* istanbul ignore next */ []));
2676
- ariaLive = computed(() => {
2677
- const v = this.variant();
2678
- return v === 'destructive' || v === 'warning' ? 'assertive' : 'polite';
2679
- }, ...(ngDevMode ? [{ debugName: "ariaLive" }] : /* istanbul ignore next */ []));
2680
- computedClass = computed(() => cn(alertVariants({ variant: this.variant() }), this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
2681
- dismiss() {
2682
- this.visible.set(false);
2683
- }
2444
+ function computePageRange(totalPages, currentPage, siblingCount, boundaryCount) {
2445
+ const range = (start, end) => Array.from({ length: end - start + 1 }, (_, i) => start + i);
2446
+ const startPages = range(1, Math.min(boundaryCount, totalPages));
2447
+ const endPages = range(Math.max(totalPages - boundaryCount + 1, boundaryCount + 1), totalPages);
2448
+ const siblingsStart = Math.max(Math.min(currentPage - siblingCount, totalPages - boundaryCount - siblingCount * 2 - 1), boundaryCount + 2);
2449
+ const siblingsEnd = Math.min(Math.max(currentPage + siblingCount, boundaryCount + siblingCount * 2 + 2), endPages.length > 0 ? endPages[0] - 2 : totalPages - 1);
2450
+ const result = [...startPages];
2451
+ if (siblingsStart > boundaryCount + 2) {
2452
+ result.push('ellipsis');
2453
+ }
2454
+ else if (boundaryCount + 1 < totalPages - boundaryCount) {
2455
+ result.push(boundaryCount + 1);
2456
+ }
2457
+ result.push(...range(siblingsStart, siblingsEnd));
2458
+ if (siblingsEnd < totalPages - boundaryCount - 1) {
2459
+ result.push('ellipsis');
2460
+ }
2461
+ else if (totalPages - boundaryCount > boundaryCount) {
2462
+ result.push(totalPages - boundaryCount);
2463
+ }
2464
+ result.push(...endPages);
2465
+ return [...new Set(result)].sort((a, b) => {
2466
+ if (a === 'ellipsis')
2467
+ return 0;
2468
+ if (b === 'ellipsis')
2469
+ return 0;
2470
+ return a - b;
2471
+ });
2472
+ }
2473
+ class SnyPaginationComponent {
2474
+ currentPage = model(1, ...(ngDevMode ? [{ debugName: "currentPage" }] : /* istanbul ignore next */ []));
2475
+ totalPages = input.required(...(ngDevMode ? [{ debugName: "totalPages" }] : /* istanbul ignore next */ []));
2476
+ siblingCount = input(1, ...(ngDevMode ? [{ debugName: "siblingCount" }] : /* istanbul ignore next */ []));
2477
+ boundaryCount = input(1, ...(ngDevMode ? [{ debugName: "boundaryCount" }] : /* istanbul ignore next */ []));
2478
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
2479
+ variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
2480
+ class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
2481
+ pages = computed(() => computePageRange(this.totalPages(), this.currentPage(), this.siblingCount(), this.boundaryCount()), ...(ngDevMode ? [{ debugName: "pages" }] : /* istanbul ignore next */ []));
2482
+ hasPrev = computed(() => this.currentPage() > 1, ...(ngDevMode ? [{ debugName: "hasPrev" }] : /* istanbul ignore next */ []));
2483
+ hasNext = computed(() => this.currentPage() < this.totalPages(), ...(ngDevMode ? [{ debugName: "hasNext" }] : /* istanbul ignore next */ []));
2484
+ goToPage(page) {
2485
+ if (page === 'ellipsis')
2486
+ return;
2487
+ this.currentPage.set(page);
2488
+ }
2489
+ prev() {
2490
+ if (this.hasPrev())
2491
+ this.currentPage.update((p) => p - 1);
2492
+ }
2493
+ next() {
2494
+ if (this.hasNext())
2495
+ this.currentPage.update((p) => p + 1);
2496
+ }
2497
+ pageClass(page) {
2498
+ return cn(paginationItemVariants({
2499
+ variant: this.variant(),
2500
+ size: this.size(),
2501
+ active: page === this.currentPage(),
2502
+ }));
2503
+ }
2504
+ navBtnClass() {
2505
+ return cn(paginationItemVariants({ variant: this.variant(), size: this.size(), active: false }));
2506
+ }
2507
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyPaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2508
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: SnyPaginationComponent, isStandalone: true, selector: "sny-pagination", inputs: { currentPage: { classPropertyName: "currentPage", publicName: "currentPage", isSignal: true, isRequired: false, transformFunction: null }, totalPages: { classPropertyName: "totalPages", publicName: "totalPages", isSignal: true, isRequired: true, transformFunction: null }, siblingCount: { classPropertyName: "siblingCount", publicName: "siblingCount", isSignal: true, isRequired: false, transformFunction: null }, boundaryCount: { classPropertyName: "boundaryCount", publicName: "boundaryCount", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { currentPage: "currentPageChange" }, host: { attributes: { "role": "navigation", "aria-label": "Pagination" } }, ngImport: i0, template: `
2509
+ <div class="flex items-center gap-1">
2510
+ <button
2511
+ [class]="navBtnClass()"
2512
+ [disabled]="!hasPrev()"
2513
+ [attr.aria-label]="'Go to previous page'"
2514
+ (click)="prev()"
2515
+ >
2516
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6"/></svg>
2517
+ </button>
2518
+
2519
+ @for (page of pages(); track $index) {
2520
+ @if (page === 'ellipsis') {
2521
+ <span class="flex h-9 w-9 items-center justify-center" aria-hidden="true">...</span>
2522
+ } @else {
2523
+ <button
2524
+ [class]="pageClass(page)"
2525
+ [attr.aria-label]="'Page ' + page"
2526
+ [attr.aria-current]="page === currentPage() ? 'page' : null"
2527
+ (click)="goToPage(page)"
2528
+ >
2529
+ {{ page }}
2530
+ </button>
2531
+ }
2532
+ }
2533
+
2534
+ <button
2535
+ [class]="navBtnClass()"
2536
+ [disabled]="!hasNext()"
2537
+ [attr.aria-label]="'Go to next page'"
2538
+ (click)="next()"
2539
+ >
2540
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
2541
+ </button>
2542
+ </div>
2543
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
2544
+ }
2545
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyPaginationComponent, decorators: [{
2546
+ type: Component,
2547
+ args: [{
2548
+ selector: 'sny-pagination',
2549
+ standalone: true,
2550
+ changeDetection: ChangeDetectionStrategy.OnPush,
2551
+ host: {
2552
+ 'role': 'navigation',
2553
+ 'aria-label': 'Pagination',
2554
+ },
2555
+ template: `
2556
+ <div class="flex items-center gap-1">
2557
+ <button
2558
+ [class]="navBtnClass()"
2559
+ [disabled]="!hasPrev()"
2560
+ [attr.aria-label]="'Go to previous page'"
2561
+ (click)="prev()"
2562
+ >
2563
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6"/></svg>
2564
+ </button>
2565
+
2566
+ @for (page of pages(); track $index) {
2567
+ @if (page === 'ellipsis') {
2568
+ <span class="flex h-9 w-9 items-center justify-center" aria-hidden="true">...</span>
2569
+ } @else {
2570
+ <button
2571
+ [class]="pageClass(page)"
2572
+ [attr.aria-label]="'Page ' + page"
2573
+ [attr.aria-current]="page === currentPage() ? 'page' : null"
2574
+ (click)="goToPage(page)"
2575
+ >
2576
+ {{ page }}
2577
+ </button>
2578
+ }
2579
+ }
2580
+
2581
+ <button
2582
+ [class]="navBtnClass()"
2583
+ [disabled]="!hasNext()"
2584
+ [attr.aria-label]="'Go to next page'"
2585
+ (click)="next()"
2586
+ >
2587
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
2588
+ </button>
2589
+ </div>
2590
+ `,
2591
+ }]
2592
+ }], propDecorators: { currentPage: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentPage", required: false }] }, { type: i0.Output, args: ["currentPageChange"] }], totalPages: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalPages", required: true }] }], siblingCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "siblingCount", required: false }] }], boundaryCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "boundaryCount", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
2593
+
2594
+ const dropdownContentVariants = cva('z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md', {
2595
+ variants: {},
2596
+ defaultVariants: {},
2597
+ });
2598
+ const dropdownItemVariants = cva('relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors data-[active]:bg-accent data-[active]:text-accent-foreground', {
2599
+ variants: {
2600
+ variant: {
2601
+ default: '',
2602
+ destructive: 'text-destructive data-[active]:bg-destructive/10 data-[active]:text-destructive',
2603
+ },
2604
+ },
2605
+ defaultVariants: {
2606
+ variant: 'default',
2607
+ },
2608
+ });
2609
+
2610
+ const SNY_DROPDOWN = new InjectionToken('SnyDropdown');
2611
+ class SnyDropdownDirective {
2612
+ elementRef = inject(ElementRef);
2613
+ isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
2614
+ toggle() { this.isOpen.update((v) => !v); }
2615
+ open() { this.isOpen.set(true); }
2616
+ close() { this.isOpen.set(false); }
2617
+ onDocumentClick(event) {
2618
+ if (!this.elementRef.nativeElement.contains(event.target)) {
2619
+ this.close();
2620
+ }
2621
+ }
2622
+ onEscape() {
2623
+ this.close();
2624
+ }
2625
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyDropdownDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2626
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.5", type: SnyDropdownDirective, isStandalone: true, selector: "[snyDropdown]", host: { listeners: { "document:click": "onDocumentClick($event)", "keydown.escape": "onEscape()" }, properties: { "class": "\"relative inline-block\"" } }, providers: [{ provide: SNY_DROPDOWN, useExisting: SnyDropdownDirective }], exportAs: ["snyDropdown"], ngImport: i0 });
2627
+ }
2628
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyDropdownDirective, decorators: [{
2629
+ type: Directive,
2630
+ args: [{
2631
+ selector: '[snyDropdown]',
2632
+ standalone: true,
2633
+ exportAs: 'snyDropdown',
2634
+ providers: [{ provide: SNY_DROPDOWN, useExisting: SnyDropdownDirective }],
2635
+ host: {
2636
+ '[class]': '"relative inline-block"',
2637
+ },
2638
+ }]
2639
+ }], propDecorators: { onDocumentClick: [{
2640
+ type: HostListener,
2641
+ args: ['document:click', ['$event']]
2642
+ }], onEscape: [{
2643
+ type: HostListener,
2644
+ args: ['keydown.escape']
2645
+ }] } });
2646
+ class SnyDropdownTriggerDirective {
2647
+ dropdown = inject(SNY_DROPDOWN);
2648
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyDropdownTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2649
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.5", type: SnyDropdownTriggerDirective, isStandalone: true, selector: "[snyDropdownTrigger]", host: { listeners: { "click": "dropdown.toggle()" }, properties: { "attr.aria-expanded": "dropdown.isOpen()", "attr.aria-haspopup": "\"menu\"" } }, ngImport: i0 });
2650
+ }
2651
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyDropdownTriggerDirective, decorators: [{
2652
+ type: Directive,
2653
+ args: [{
2654
+ selector: '[snyDropdownTrigger]',
2655
+ standalone: true,
2656
+ host: {
2657
+ '(click)': 'dropdown.toggle()',
2658
+ '[attr.aria-expanded]': 'dropdown.isOpen()',
2659
+ '[attr.aria-haspopup]': '"menu"',
2660
+ },
2661
+ }]
2662
+ }] });
2663
+ class SnyDropdownContentDirective {
2664
+ dropdown = inject(SNY_DROPDOWN);
2665
+ class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
2666
+ computedClass = computed(() => cn(dropdownContentVariants(), 'absolute mt-1 left-0 animate-in fade-in-0 zoom-in-95', this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
2667
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyDropdownContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2668
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnyDropdownContentDirective, isStandalone: true, selector: "[snyDropdownContent]", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "menu" }, properties: { "class": "computedClass()", "style.display": "dropdown.isOpen() ? \"\" : \"none\"" } }, ngImport: i0 });
2669
+ }
2670
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyDropdownContentDirective, decorators: [{
2671
+ type: Directive,
2672
+ args: [{
2673
+ selector: '[snyDropdownContent]',
2674
+ standalone: true,
2675
+ host: {
2676
+ 'role': 'menu',
2677
+ '[class]': 'computedClass()',
2678
+ '[style.display]': 'dropdown.isOpen() ? "" : "none"',
2679
+ },
2680
+ }]
2681
+ }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
2682
+ class SnyMenuContentDirective {
2683
+ class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
2684
+ computedClass = computed(() => cn(dropdownContentVariants(), this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
2685
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyMenuContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2686
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnyMenuContentDirective, isStandalone: true, selector: "[snyMenuContent]", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "computedClass()" } }, ngImport: i0 });
2687
+ }
2688
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyMenuContentDirective, decorators: [{
2689
+ type: Directive,
2690
+ args: [{
2691
+ selector: '[snyMenuContent]',
2692
+ standalone: true,
2693
+ host: {
2694
+ '[class]': 'computedClass()',
2695
+ },
2696
+ }]
2697
+ }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
2698
+ class SnyMenuItemDirective {
2699
+ dropdown = inject(SNY_DROPDOWN, { optional: true });
2700
+ variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
2701
+ class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
2702
+ computedClass = computed(() => cn(dropdownItemVariants({ variant: this.variant() }), 'cursor-pointer hover:bg-accent hover:text-accent-foreground', this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
2703
+ onClick() {
2704
+ this.dropdown?.close();
2705
+ }
2706
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyMenuItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2707
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnyMenuItemDirective, isStandalone: true, selector: "[snyMenuItem]", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "menuitem" }, listeners: { "click": "onClick()" }, properties: { "class": "computedClass()" } }, ngImport: i0 });
2708
+ }
2709
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyMenuItemDirective, decorators: [{
2710
+ type: Directive,
2711
+ args: [{
2712
+ selector: '[snyMenuItem]',
2713
+ standalone: true,
2714
+ host: {
2715
+ 'role': 'menuitem',
2716
+ '[class]': 'computedClass()',
2717
+ '(click)': 'onClick()',
2718
+ },
2719
+ }]
2720
+ }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
2721
+ class SnyMenuSeparatorDirective {
2722
+ class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
2723
+ computedClass = computed(() => cn('-mx-1 my-1 h-px bg-muted', this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
2724
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyMenuSeparatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2725
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnyMenuSeparatorDirective, isStandalone: true, selector: "[snyMenuSeparator]", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "separator" }, properties: { "class": "computedClass()" } }, ngImport: i0 });
2726
+ }
2727
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyMenuSeparatorDirective, decorators: [{
2728
+ type: Directive,
2729
+ args: [{
2730
+ selector: '[snyMenuSeparator]',
2731
+ standalone: true,
2732
+ host: {
2733
+ 'role': 'separator',
2734
+ '[class]': 'computedClass()',
2735
+ },
2736
+ }]
2737
+ }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
2738
+ class SnyMenuLabelDirective {
2739
+ class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
2740
+ computedClass = computed(() => cn('px-2 py-1.5 text-sm font-semibold', this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
2741
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyMenuLabelDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2742
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnyMenuLabelDirective, isStandalone: true, selector: "[snyMenuLabel]", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "computedClass()" } }, ngImport: i0 });
2743
+ }
2744
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyMenuLabelDirective, decorators: [{
2745
+ type: Directive,
2746
+ args: [{
2747
+ selector: '[snyMenuLabel]',
2748
+ standalone: true,
2749
+ host: {
2750
+ '[class]': 'computedClass()',
2751
+ },
2752
+ }]
2753
+ }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
2754
+
2755
+ class SnyCellDefDirective {
2756
+ snyCell = input.required(...(ngDevMode ? [{ debugName: "snyCell" }] : /* istanbul ignore next */ []));
2757
+ template = inject(TemplateRef);
2758
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyCellDefDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2759
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnyCellDefDirective, isStandalone: true, selector: "[snyCell]", inputs: { snyCell: { classPropertyName: "snyCell", publicName: "snyCell", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
2760
+ }
2761
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyCellDefDirective, decorators: [{
2762
+ type: Directive,
2763
+ args: [{
2764
+ selector: '[snyCell]',
2765
+ standalone: true,
2766
+ }]
2767
+ }], propDecorators: { snyCell: [{ type: i0.Input, args: [{ isSignal: true, alias: "snyCell", required: true }] }] } });
2768
+ class SnyHeaderCellDefDirective {
2769
+ snyHeaderCell = input.required(...(ngDevMode ? [{ debugName: "snyHeaderCell" }] : /* istanbul ignore next */ []));
2770
+ template = inject(TemplateRef);
2771
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyHeaderCellDefDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2772
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnyHeaderCellDefDirective, isStandalone: true, selector: "[snyHeaderCell]", inputs: { snyHeaderCell: { classPropertyName: "snyHeaderCell", publicName: "snyHeaderCell", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
2773
+ }
2774
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyHeaderCellDefDirective, decorators: [{
2775
+ type: Directive,
2776
+ args: [{
2777
+ selector: '[snyHeaderCell]',
2778
+ standalone: true,
2779
+ }]
2780
+ }], propDecorators: { snyHeaderCell: [{ type: i0.Input, args: [{ isSignal: true, alias: "snyHeaderCell", required: true }] }] } });
2781
+ class SnyBulkActionsDefDirective {
2782
+ template = inject(TemplateRef);
2783
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyBulkActionsDefDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2784
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.5", type: SnyBulkActionsDefDirective, isStandalone: true, selector: "[snyBulkActions]", ngImport: i0 });
2785
+ }
2786
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyBulkActionsDefDirective, decorators: [{
2787
+ type: Directive,
2788
+ args: [{
2789
+ selector: '[snyBulkActions]',
2790
+ standalone: true,
2791
+ }]
2792
+ }] });
2793
+ class SnyRowExpandDefDirective {
2794
+ template = inject(TemplateRef);
2795
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyRowExpandDefDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2796
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.5", type: SnyRowExpandDefDirective, isStandalone: true, selector: "[snyRowExpand]", ngImport: i0 });
2797
+ }
2798
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyRowExpandDefDirective, decorators: [{
2799
+ type: Directive,
2800
+ args: [{
2801
+ selector: '[snyRowExpand]',
2802
+ standalone: true,
2803
+ }]
2804
+ }] });
2805
+
2806
+ const DEFAULT_PAGINATION = {
2807
+ pageSize: 10,
2808
+ pageSizeOptions: [5, 10, 25, 50],
2809
+ };
2810
+ class SnyDataTableComponent {
2811
+ // Inputs
2812
+ columns = input.required(...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
2813
+ data = input.required(...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
2814
+ variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
2815
+ density = input('normal', ...(ngDevMode ? [{ debugName: "density" }] : /* istanbul ignore next */ []));
2816
+ hoverable = input(true, ...(ngDevMode ? [{ debugName: "hoverable" }] : /* istanbul ignore next */ []));
2817
+ stickyHeader = input(false, ...(ngDevMode ? [{ debugName: "stickyHeader" }] : /* istanbul ignore next */ []));
2818
+ selectable = input(false, ...(ngDevMode ? [{ debugName: "selectable" }] : /* istanbul ignore next */ []));
2819
+ paginated = input(true, ...(ngDevMode ? [{ debugName: "paginated" }] : /* istanbul ignore next */ []));
2820
+ filterable = input(true, ...(ngDevMode ? [{ debugName: "filterable" }] : /* istanbul ignore next */ []));
2821
+ showExport = input(false, ...(ngDevMode ? [{ debugName: "showExport" }] : /* istanbul ignore next */ []));
2822
+ showColumnToggle = input(false, ...(ngDevMode ? [{ debugName: "showColumnToggle" }] : /* istanbul ignore next */ []));
2823
+ expandable = input(false, ...(ngDevMode ? [{ debugName: "expandable" }] : /* istanbul ignore next */ []));
2824
+ loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
2825
+ loadingRows = input(5, ...(ngDevMode ? [{ debugName: "loadingRows" }] : /* istanbul ignore next */ []));
2826
+ paginationConfig = input(DEFAULT_PAGINATION, ...(ngDevMode ? [{ debugName: "paginationConfig" }] : /* istanbul ignore next */ []));
2827
+ trackBy = input('', ...(ngDevMode ? [{ debugName: "trackBy" }] : /* istanbul ignore next */ []));
2828
+ noDataText = input('No data available', ...(ngDevMode ? [{ debugName: "noDataText" }] : /* istanbul ignore next */ []));
2829
+ // Model
2830
+ selectedRows = model([], ...(ngDevMode ? [{ debugName: "selectedRows" }] : /* istanbul ignore next */ []));
2831
+ // Outputs
2832
+ sortChanged = output();
2833
+ rowClicked = output();
2834
+ dataExported = output();
2835
+ // Content queries
2836
+ cellDefs = contentChildren(SnyCellDefDirective, ...(ngDevMode ? [{ debugName: "cellDefs" }] : /* istanbul ignore next */ []));
2837
+ headerCellDefs = contentChildren(SnyHeaderCellDefDirective, ...(ngDevMode ? [{ debugName: "headerCellDefs" }] : /* istanbul ignore next */ []));
2838
+ bulkActionsDef = contentChild(SnyBulkActionsDefDirective, ...(ngDevMode ? [{ debugName: "bulkActionsDef" }] : /* istanbul ignore next */ []));
2839
+ rowExpandDef = contentChild(SnyRowExpandDefDirective, ...(ngDevMode ? [{ debugName: "rowExpandDef" }] : /* istanbul ignore next */ []));
2840
+ // Internal state
2841
+ sortState = signal({ key: '', direction: null }, ...(ngDevMode ? [{ debugName: "sortState" }] : /* istanbul ignore next */ []));
2842
+ filterText = signal('', ...(ngDevMode ? [{ debugName: "filterText" }] : /* istanbul ignore next */ []));
2843
+ currentPage = signal(1, ...(ngDevMode ? [{ debugName: "currentPage" }] : /* istanbul ignore next */ []));
2844
+ pageSize = signal(10, ...(ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []));
2845
+ hiddenColumns = signal(new Set(), ...(ngDevMode ? [{ debugName: "hiddenColumns" }] : /* istanbul ignore next */ []));
2846
+ expandedRows = signal(new Set(), ...(ngDevMode ? [{ debugName: "expandedRows" }] : /* istanbul ignore next */ []));
2847
+ // Template def maps
2848
+ cellDefMap = computed(() => {
2849
+ const map = new Map();
2850
+ for (const def of this.cellDefs()) {
2851
+ map.set(def.snyCell(), def.template);
2852
+ }
2853
+ return map;
2854
+ }, ...(ngDevMode ? [{ debugName: "cellDefMap" }] : /* istanbul ignore next */ []));
2855
+ headerCellDefMap = computed(() => {
2856
+ const map = new Map();
2857
+ for (const def of this.headerCellDefs()) {
2858
+ map.set(def.snyHeaderCell(), def.template);
2859
+ }
2860
+ return map;
2861
+ }, ...(ngDevMode ? [{ debugName: "headerCellDefMap" }] : /* istanbul ignore next */ []));
2862
+ // Visible columns
2863
+ visibleColumns = computed(() => this.columns().filter((col) => col.visible !== false && !this.hiddenColumns().has(col.key)), ...(ngDevMode ? [{ debugName: "visibleColumns" }] : /* istanbul ignore next */ []));
2864
+ // Page size options
2865
+ pageSizeOptions = computed(() => this.paginationConfig().pageSizeOptions.map((n) => ({
2866
+ value: String(n),
2867
+ label: String(n),
2868
+ })), ...(ngDevMode ? [{ debugName: "pageSizeOptions" }] : /* istanbul ignore next */ []));
2869
+ pageSizeValue = computed(() => String(this.pageSize()), ...(ngDevMode ? [{ debugName: "pageSizeValue" }] : /* istanbul ignore next */ []));
2870
+ // Skeleton rows
2871
+ skeletonRows = computed(() => Array.from({ length: this.loadingRows() }, (_, i) => i), ...(ngDevMode ? [{ debugName: "skeletonRows" }] : /* istanbul ignore next */ []));
2872
+ // Bulk actions visibility
2873
+ showBulkActions = computed(() => this.selectable() &&
2874
+ this.selectedRows().length > 0 &&
2875
+ this.bulkActionsDef() != null, ...(ngDevMode ? [{ debugName: "showBulkActions" }] : /* istanbul ignore next */ []));
2876
+ // Data pipeline (filter uses all columns, not just visible)
2877
+ filteredData = computed(() => {
2878
+ const text = this.filterText().toLowerCase().trim();
2879
+ const rows = this.data();
2880
+ if (!text)
2881
+ return rows;
2882
+ const cols = this.columns().filter((c) => c.filterable !== false);
2883
+ return rows.filter((row) => cols.some((col) => String(row[col.key] ?? '').toLowerCase().includes(text)));
2884
+ }, ...(ngDevMode ? [{ debugName: "filteredData" }] : /* istanbul ignore next */ []));
2885
+ sortedData = computed(() => {
2886
+ const { key, direction } = this.sortState();
2887
+ const rows = this.filteredData();
2888
+ if (!key || !direction)
2889
+ return rows;
2890
+ return [...rows].sort((a, b) => {
2891
+ const aVal = a[key];
2892
+ const bVal = b[key];
2893
+ if (aVal == null && bVal == null)
2894
+ return 0;
2895
+ if (aVal == null)
2896
+ return direction === 'asc' ? -1 : 1;
2897
+ if (bVal == null)
2898
+ return direction === 'asc' ? 1 : -1;
2899
+ if (typeof aVal === 'number' && typeof bVal === 'number') {
2900
+ return direction === 'asc' ? aVal - bVal : bVal - aVal;
2901
+ }
2902
+ const cmp = String(aVal).localeCompare(String(bVal));
2903
+ return direction === 'asc' ? cmp : -cmp;
2904
+ });
2905
+ }, ...(ngDevMode ? [{ debugName: "sortedData" }] : /* istanbul ignore next */ []));
2906
+ totalPages = computed(() => Math.max(1, Math.ceil(this.filteredData().length / this.pageSize())), ...(ngDevMode ? [{ debugName: "totalPages" }] : /* istanbul ignore next */ []));
2907
+ paginatedData = computed(() => {
2908
+ if (!this.paginated())
2909
+ return this.sortedData();
2910
+ const start = (this.currentPage() - 1) * this.pageSize();
2911
+ return this.sortedData().slice(start, start + this.pageSize());
2912
+ }, ...(ngDevMode ? [{ debugName: "paginatedData" }] : /* istanbul ignore next */ []));
2913
+ totalColSpan = computed(() => this.visibleColumns().length +
2914
+ (this.selectable() ? 1 : 0) +
2915
+ (this.expandable() ? 1 : 0), ...(ngDevMode ? [{ debugName: "totalColSpan" }] : /* istanbul ignore next */ []));
2916
+ // Selection computed
2917
+ allSelected = computed(() => {
2918
+ const page = this.paginatedData();
2919
+ if (page.length === 0)
2920
+ return false;
2921
+ const selected = this.selectedRows();
2922
+ return page.every((row) => this.isRowInList(row, selected));
2923
+ }, ...(ngDevMode ? [{ debugName: "allSelected" }] : /* istanbul ignore next */ []));
2924
+ someSelected = computed(() => {
2925
+ const page = this.paginatedData();
2926
+ const selected = this.selectedRows();
2927
+ return page.some((row) => this.isRowInList(row, selected));
2928
+ }, ...(ngDevMode ? [{ debugName: "someSelected" }] : /* istanbul ignore next */ []));
2929
+ constructor() {
2930
+ effect(() => {
2931
+ const config = this.paginationConfig();
2932
+ untracked(() => this.pageSize.set(config.pageSize));
2933
+ });
2934
+ effect(() => {
2935
+ this.filterText();
2936
+ this.pageSize();
2937
+ this.data();
2938
+ untracked(() => this.currentPage.set(1));
2939
+ });
2940
+ }
2941
+ // Sort
2942
+ toggleSort(key) {
2943
+ const current = this.sortState();
2944
+ let direction;
2945
+ if (current.key !== key) {
2946
+ direction = 'asc';
2947
+ }
2948
+ else if (current.direction === 'asc') {
2949
+ direction = 'desc';
2950
+ }
2951
+ else if (current.direction === 'desc') {
2952
+ direction = null;
2953
+ }
2954
+ else {
2955
+ direction = 'asc';
2956
+ }
2957
+ const next = { key: direction ? key : '', direction };
2958
+ this.sortState.set(next);
2959
+ this.sortChanged.emit(next);
2960
+ }
2961
+ // Filter
2962
+ onFilterInput(event) {
2963
+ this.filterText.set(event.target.value);
2964
+ }
2965
+ // Page size
2966
+ onPageSizeChange(value) {
2967
+ this.pageSize.set(Number(value));
2968
+ }
2969
+ // Selection
2970
+ toggleSelectAll() {
2971
+ if (this.allSelected()) {
2972
+ const page = this.paginatedData();
2973
+ this.selectedRows.update((sel) => sel.filter((r) => !page.some((p) => this.rowsEqual(r, p))));
2974
+ }
2975
+ else {
2976
+ const page = this.paginatedData();
2977
+ this.selectedRows.update((sel) => {
2978
+ const newSel = [...sel];
2979
+ for (const row of page) {
2980
+ if (!this.isRowInList(row, newSel))
2981
+ newSel.push(row);
2982
+ }
2983
+ return newSel;
2984
+ });
2985
+ }
2986
+ }
2987
+ toggleRowSelection(row) {
2988
+ this.selectedRows.update((sel) => this.isRowInList(row, sel)
2989
+ ? sel.filter((r) => !this.rowsEqual(r, row))
2990
+ : [...sel, row]);
2991
+ }
2992
+ // Row click
2993
+ onRowClick(row) {
2994
+ this.rowClicked.emit(row);
2995
+ }
2996
+ // Export
2997
+ onExport() {
2998
+ this.dataExported.emit(this.filteredData());
2999
+ }
3000
+ // Column visibility
3001
+ toggleColumnVisibility(key) {
3002
+ this.hiddenColumns.update((set) => {
3003
+ const next = new Set(set);
3004
+ if (next.has(key))
3005
+ next.delete(key);
3006
+ else
3007
+ next.add(key);
3008
+ return next;
3009
+ });
3010
+ }
3011
+ // Expansion
3012
+ toggleRowExpansion(row) {
3013
+ const key = this.trackBy() ? row[this.trackBy()] : row;
3014
+ this.expandedRows.update((set) => {
3015
+ const next = new Set(set);
3016
+ if (next.has(key))
3017
+ next.delete(key);
3018
+ else
3019
+ next.add(key);
3020
+ return next;
3021
+ });
3022
+ }
3023
+ isExpanded(row) {
3024
+ const key = this.trackBy() ? row[this.trackBy()] : row;
3025
+ return this.expandedRows().has(key);
3026
+ }
3027
+ // Helpers
3028
+ isSelected(row) {
3029
+ return this.isRowInList(row, this.selectedRows());
3030
+ }
3031
+ trackByFn(row, index) {
3032
+ const key = this.trackBy();
3033
+ return key ? row[key] : index;
3034
+ }
3035
+ isRowInList(row, list) {
3036
+ return list.some((r) => this.rowsEqual(r, row));
3037
+ }
3038
+ rowsEqual(a, b) {
3039
+ const key = this.trackBy();
3040
+ if (key)
3041
+ return a[key] === b[key];
3042
+ return a === b;
3043
+ }
3044
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyDataTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3045
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: SnyDataTableComponent, isStandalone: true, selector: "sny-data-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null }, hoverable: { classPropertyName: "hoverable", publicName: "hoverable", isSignal: true, isRequired: false, transformFunction: null }, stickyHeader: { classPropertyName: "stickyHeader", publicName: "stickyHeader", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, paginated: { classPropertyName: "paginated", publicName: "paginated", isSignal: true, isRequired: false, transformFunction: null }, filterable: { classPropertyName: "filterable", publicName: "filterable", isSignal: true, isRequired: false, transformFunction: null }, showExport: { classPropertyName: "showExport", publicName: "showExport", isSignal: true, isRequired: false, transformFunction: null }, showColumnToggle: { classPropertyName: "showColumnToggle", publicName: "showColumnToggle", isSignal: true, isRequired: false, transformFunction: null }, expandable: { classPropertyName: "expandable", publicName: "expandable", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, loadingRows: { classPropertyName: "loadingRows", publicName: "loadingRows", isSignal: true, isRequired: false, transformFunction: null }, paginationConfig: { classPropertyName: "paginationConfig", publicName: "paginationConfig", isSignal: true, isRequired: false, transformFunction: null }, trackBy: { classPropertyName: "trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null }, noDataText: { classPropertyName: "noDataText", publicName: "noDataText", isSignal: true, isRequired: false, transformFunction: null }, selectedRows: { classPropertyName: "selectedRows", publicName: "selectedRows", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedRows: "selectedRowsChange", sortChanged: "sortChanged", rowClicked: "rowClicked", dataExported: "dataExported" }, queries: [{ propertyName: "cellDefs", predicate: SnyCellDefDirective, isSignal: true }, { propertyName: "headerCellDefs", predicate: SnyHeaderCellDefDirective, isSignal: true }, { propertyName: "bulkActionsDef", first: true, predicate: SnyBulkActionsDefDirective, descendants: true, isSignal: true }, { propertyName: "rowExpandDef", first: true, predicate: SnyRowExpandDefDirective, descendants: true, isSignal: true }], ngImport: i0, template: `
3046
+ <!-- Toolbar -->
3047
+ @if (filterable() || showExport() || showColumnToggle()) {
3048
+ <div class="flex items-center justify-between gap-4 mb-4 flex-wrap">
3049
+ @if (filterable()) {
3050
+ <input
3051
+ snyInput
3052
+ [value]="filterText()"
3053
+ (input)="onFilterInput($event)"
3054
+ placeholder="Filter..."
3055
+ class="w-full sm:max-w-sm"
3056
+ />
3057
+ }
3058
+ <div class="flex items-center gap-2">
3059
+ @if (showExport()) {
3060
+ <button snyBtn variant="outline" size="sm" (click)="onExport()">
3061
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="sm:mr-2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z"/><path d="M14 2v6h6"/><path d="M12 18v-6"/><path d="m9 15 3-3 3 3"/></svg>
3062
+ <span class="hidden sm:inline">Export</span>
3063
+ </button>
3064
+ }
3065
+ @if (showColumnToggle()) {
3066
+ <div snyDropdown class="relative">
3067
+ <button snyBtn variant="outline" size="sm" snyDropdownTrigger>
3068
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="sm:mr-2"><path d="M12 3v18"/><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M3 9h18"/><path d="M3 15h18"/></svg>
3069
+ <span class="hidden sm:inline">Columns</span>
3070
+ </button>
3071
+ <div snyDropdownContent class="w-48 right-0 left-auto">
3072
+ @for (col of columns(); track col.key) {
3073
+ <label snyMenuItem class="flex items-center gap-2 cursor-pointer">
3074
+ <input
3075
+ type="checkbox"
3076
+ snyCheckbox
3077
+ [checked]="!hiddenColumns().has(col.key)"
3078
+ (change)="toggleColumnVisibility(col.key)"
3079
+ (click)="$event.stopPropagation()"
3080
+ />
3081
+ {{ col.label }}
3082
+ </label>
3083
+ }
3084
+ </div>
3085
+ </div>
3086
+ }
3087
+ </div>
3088
+ </div>
3089
+ }
3090
+
3091
+ <!-- Bulk Actions Bar -->
3092
+ @if (showBulkActions()) {
3093
+ @let selected = selectedRows();
3094
+ <div class="flex items-center gap-2 mb-4 p-3 bg-muted/50 rounded-sm border border-border flex-wrap">
3095
+ <span class="text-sm font-medium text-muted-foreground mr-2">
3096
+ {{ selected.length }} selected
3097
+ </span>
3098
+ <ng-container
3099
+ [ngTemplateOutlet]="bulkActionsDef()!.template"
3100
+ [ngTemplateOutletContext]="{ $implicit: selected }"
3101
+ />
3102
+ <button
3103
+ snyBtn variant="ghost" size="sm" class="ml-auto"
3104
+ (click)="selectedRows.set([])"
3105
+ >
3106
+ Clear
3107
+ </button>
3108
+ </div>
3109
+ }
3110
+
3111
+ <!-- Table -->
3112
+ <div class="overflow-auto border border-border rounded-sm">
3113
+ <table
3114
+ snyTable
3115
+ [variant]="variant()"
3116
+ [density]="density()"
3117
+ [hoverable]="hoverable()"
3118
+ [stickyHeader]="stickyHeader()"
3119
+ >
3120
+ <thead snyTableHeader>
3121
+ <tr snyTableRow>
3122
+ @if (selectable()) {
3123
+ <th snyTableHead class="w-12">
3124
+ <input
3125
+ type="checkbox"
3126
+ snyCheckbox
3127
+ [checked]="allSelected()"
3128
+ [indeterminate]="someSelected() && !allSelected()"
3129
+ (change)="toggleSelectAll()"
3130
+ />
3131
+ </th>
3132
+ }
3133
+ @if (expandable()) {
3134
+ <th snyTableHead class="w-10"></th>
3135
+ }
3136
+ @let sort = sortState();
3137
+ @let headerDefs = headerCellDefMap();
3138
+ @for (col of visibleColumns(); track col.key) {
3139
+ <th
3140
+ snyTableHead
3141
+ [style.width]="col.width ?? null"
3142
+ [class]="col.sortable ? 'cursor-pointer select-none' : ''"
3143
+ (click)="col.sortable ? toggleSort(col.key) : null"
3144
+ >
3145
+ @if (headerDefs.has(col.key)) {
3146
+ <ng-container
3147
+ [ngTemplateOutlet]="headerDefs.get(col.key)!"
3148
+ [ngTemplateOutletContext]="{ $implicit: col }"
3149
+ />
3150
+ } @else {
3151
+ <div class="flex items-center gap-1">
3152
+ <span>{{ col.label }}</span>
3153
+ @if (col.sortable) {
3154
+ @let isActive = sort.key === col.key;
3155
+ @if (isActive && sort.direction === 'asc') {
3156
+ <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m5 12 7-7 7 7"/></svg>
3157
+ } @else if (isActive && sort.direction === 'desc') {
3158
+ <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m19 12-7 7-7-7"/></svg>
3159
+ } @else {
3160
+ <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="opacity-30"><path d="m7 15 5 5 5-5"/><path d="m7 9 5-5 5 5"/></svg>
3161
+ }
3162
+ }
3163
+ </div>
3164
+ }
3165
+ </th>
3166
+ }
3167
+ </tr>
3168
+ </thead>
3169
+ <tbody snyTableBody>
3170
+ @if (loading()) {
3171
+ @for (i of skeletonRows(); track i) {
3172
+ <tr snyTableRow>
3173
+ @if (selectable()) {
3174
+ <td snyTableCell class="w-12"><div snySkeleton class="w-4 h-4 rounded"></div></td>
3175
+ }
3176
+ @if (expandable()) {
3177
+ <td snyTableCell class="w-10"><div snySkeleton class="w-4 h-4 rounded"></div></td>
3178
+ }
3179
+ @for (col of visibleColumns(); track col.key) {
3180
+ <td snyTableCell [style.width]="col.width ?? null">
3181
+ <div snySkeleton class="w-full h-4 rounded"></div>
3182
+ </td>
3183
+ }
3184
+ </tr>
3185
+ }
3186
+ } @else if (paginatedData().length === 0) {
3187
+ <tr snyTableRow>
3188
+ <td
3189
+ snyTableCell
3190
+ [attr.colspan]="totalColSpan()"
3191
+ class="text-center text-muted-foreground py-8"
3192
+ >
3193
+ {{ noDataText() }}
3194
+ </td>
3195
+ </tr>
3196
+ } @else {
3197
+ @let cellDefs = cellDefMap();
3198
+ @let cols = visibleColumns();
3199
+ @let expandTpl = rowExpandDef();
3200
+ @for (row of paginatedData(); track trackByFn(row, $index)) {
3201
+ <tr
3202
+ snyTableRow
3203
+ [attr.data-state]="isSelected(row) ? 'selected' : null"
3204
+ (click)="onRowClick(row)"
3205
+ class="cursor-pointer"
3206
+ >
3207
+ @if (selectable()) {
3208
+ <td snyTableCell class="w-12">
3209
+ <input
3210
+ type="checkbox"
3211
+ snyCheckbox
3212
+ [checked]="isSelected(row)"
3213
+ (change)="toggleRowSelection(row)"
3214
+ (click)="$event.stopPropagation()"
3215
+ />
3216
+ </td>
3217
+ }
3218
+ @if (expandable()) {
3219
+ <td snyTableCell class="w-10">
3220
+ <button
3221
+ class="p-0.5 rounded hover:bg-accent transition-transform duration-150"
3222
+ [class.rotate-90]="isExpanded(row)"
3223
+ (click)="toggleRowExpansion(row); $event.stopPropagation()"
3224
+ >
3225
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
3226
+ </button>
3227
+ </td>
3228
+ }
3229
+ @for (col of cols; track col.key) {
3230
+ <td snyTableCell [style.width]="col.width ?? null">
3231
+ @if (cellDefs.has(col.key)) {
3232
+ <ng-container
3233
+ [ngTemplateOutlet]="cellDefs.get(col.key)!"
3234
+ [ngTemplateOutletContext]="{ $implicit: row[col.key], row: row }"
3235
+ />
3236
+ } @else {
3237
+ {{ row[col.key] }}
3238
+ }
3239
+ </td>
3240
+ }
3241
+ </tr>
3242
+ @if (expandable() && isExpanded(row) && expandTpl) {
3243
+ <tr snyTableRow>
3244
+ <td snyTableCell [attr.colspan]="totalColSpan()" class="bg-muted/30">
3245
+ <ng-container
3246
+ [ngTemplateOutlet]="expandTpl.template"
3247
+ [ngTemplateOutletContext]="{ $implicit: row }"
3248
+ />
3249
+ </td>
3250
+ </tr>
3251
+ }
3252
+ }
3253
+ }
3254
+ </tbody>
3255
+ </table>
3256
+ </div>
3257
+
3258
+ <!-- Footer -->
3259
+ @if (paginated()) {
3260
+ <div class="flex flex-col sm:flex-row items-start sm:items-center justify-between mt-4 gap-3 sm:gap-4">
3261
+ <span class="text-sm text-muted-foreground">
3262
+ @if (selectable()) {
3263
+ {{ selectedRows().length }} of {{ filteredData().length }} row(s) selected
3264
+ } @else {
3265
+ {{ filteredData().length }} row(s)
3266
+ }
3267
+ </span>
3268
+ <div class="flex items-center gap-3 sm:gap-4 flex-wrap">
3269
+ <div class="flex items-center gap-2">
3270
+ <span class="hidden sm:inline text-sm text-muted-foreground whitespace-nowrap">Rows per page</span>
3271
+ <sny-select
3272
+ [options]="pageSizeOptions()"
3273
+ [value]="pageSizeValue()"
3274
+ (valueChange)="onPageSizeChange($event)"
3275
+ size="sm"
3276
+ class="w-20"
3277
+ />
3278
+ </div>
3279
+ <sny-pagination
3280
+ [currentPage]="currentPage()"
3281
+ (currentPageChange)="currentPage.set($event)"
3282
+ [totalPages]="totalPages()"
3283
+ />
3284
+ </div>
3285
+ </div>
3286
+ }
3287
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: SnyTableDirective, selector: "table[snyTable]", inputs: ["variant", "density", "hoverable", "stickyHeader", "class"] }, { kind: "directive", type: SnyTableHeaderDirective, selector: "thead[snyTableHeader]", inputs: ["class"] }, { kind: "directive", type: SnyTableBodyDirective, selector: "tbody[snyTableBody]", inputs: ["class"] }, { kind: "directive", type: SnyTableRowDirective, selector: "tr[snyTableRow]", inputs: ["class"] }, { kind: "directive", type: SnyTableHeadDirective, selector: "th[snyTableHead]", inputs: ["class"] }, { kind: "directive", type: SnyTableCellDirective, selector: "td[snyTableCell]", inputs: ["class"] }, { kind: "component", type: SnyPaginationComponent, selector: "sny-pagination", inputs: ["currentPage", "totalPages", "siblingCount", "boundaryCount", "size", "variant", "class"], outputs: ["currentPageChange"] }, { kind: "directive", type: SnyCheckboxDirective, selector: "input[type=\"checkbox\"][snyCheckbox]", inputs: ["size", "class"] }, { kind: "directive", type: SnyInputDirective, selector: "input[snyInput], textarea[snyInput]", inputs: ["variant", "inputSize", "class", "ariaDescribedBy"] }, { kind: "directive", type: SnyButtonDirective, selector: "button[snyBtn], a[snyBtn]", inputs: ["variant", "size", "disabled", "loading", "class"] }, { kind: "component", type: SnySelectComponent, selector: "sny-select", inputs: ["options", "placeholder", "size", "disabled", "class", "value"], outputs: ["valueChange"] }, { kind: "directive", type: SnySkeletonDirective, selector: "[snySkeleton]", inputs: ["variant", "size", "class"] }, { kind: "directive", type: SnyDropdownDirective, selector: "[snyDropdown]", exportAs: ["snyDropdown"] }, { kind: "directive", type: SnyDropdownTriggerDirective, selector: "[snyDropdownTrigger]" }, { kind: "directive", type: SnyDropdownContentDirective, selector: "[snyDropdownContent]", inputs: ["class"] }, { kind: "directive", type: SnyMenuItemDirective, selector: "[snyMenuItem]", inputs: ["variant", "class"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3288
+ }
3289
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyDataTableComponent, decorators: [{
3290
+ type: Component,
3291
+ args: [{
3292
+ selector: 'sny-data-table',
3293
+ standalone: true,
3294
+ changeDetection: ChangeDetectionStrategy.OnPush,
3295
+ imports: [
3296
+ NgTemplateOutlet,
3297
+ SnyTableDirective,
3298
+ SnyTableHeaderDirective,
3299
+ SnyTableBodyDirective,
3300
+ SnyTableRowDirective,
3301
+ SnyTableHeadDirective,
3302
+ SnyTableCellDirective,
3303
+ SnyPaginationComponent,
3304
+ SnyCheckboxDirective,
3305
+ SnyInputDirective,
3306
+ SnyButtonDirective,
3307
+ SnySelectComponent,
3308
+ SnySkeletonDirective,
3309
+ SnyDropdownDirective,
3310
+ SnyDropdownTriggerDirective,
3311
+ SnyDropdownContentDirective,
3312
+ SnyMenuItemDirective,
3313
+ ],
3314
+ template: `
3315
+ <!-- Toolbar -->
3316
+ @if (filterable() || showExport() || showColumnToggle()) {
3317
+ <div class="flex items-center justify-between gap-4 mb-4 flex-wrap">
3318
+ @if (filterable()) {
3319
+ <input
3320
+ snyInput
3321
+ [value]="filterText()"
3322
+ (input)="onFilterInput($event)"
3323
+ placeholder="Filter..."
3324
+ class="w-full sm:max-w-sm"
3325
+ />
3326
+ }
3327
+ <div class="flex items-center gap-2">
3328
+ @if (showExport()) {
3329
+ <button snyBtn variant="outline" size="sm" (click)="onExport()">
3330
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="sm:mr-2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z"/><path d="M14 2v6h6"/><path d="M12 18v-6"/><path d="m9 15 3-3 3 3"/></svg>
3331
+ <span class="hidden sm:inline">Export</span>
3332
+ </button>
3333
+ }
3334
+ @if (showColumnToggle()) {
3335
+ <div snyDropdown class="relative">
3336
+ <button snyBtn variant="outline" size="sm" snyDropdownTrigger>
3337
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="sm:mr-2"><path d="M12 3v18"/><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M3 9h18"/><path d="M3 15h18"/></svg>
3338
+ <span class="hidden sm:inline">Columns</span>
3339
+ </button>
3340
+ <div snyDropdownContent class="w-48 right-0 left-auto">
3341
+ @for (col of columns(); track col.key) {
3342
+ <label snyMenuItem class="flex items-center gap-2 cursor-pointer">
3343
+ <input
3344
+ type="checkbox"
3345
+ snyCheckbox
3346
+ [checked]="!hiddenColumns().has(col.key)"
3347
+ (change)="toggleColumnVisibility(col.key)"
3348
+ (click)="$event.stopPropagation()"
3349
+ />
3350
+ {{ col.label }}
3351
+ </label>
3352
+ }
3353
+ </div>
3354
+ </div>
3355
+ }
3356
+ </div>
3357
+ </div>
3358
+ }
3359
+
3360
+ <!-- Bulk Actions Bar -->
3361
+ @if (showBulkActions()) {
3362
+ @let selected = selectedRows();
3363
+ <div class="flex items-center gap-2 mb-4 p-3 bg-muted/50 rounded-sm border border-border flex-wrap">
3364
+ <span class="text-sm font-medium text-muted-foreground mr-2">
3365
+ {{ selected.length }} selected
3366
+ </span>
3367
+ <ng-container
3368
+ [ngTemplateOutlet]="bulkActionsDef()!.template"
3369
+ [ngTemplateOutletContext]="{ $implicit: selected }"
3370
+ />
3371
+ <button
3372
+ snyBtn variant="ghost" size="sm" class="ml-auto"
3373
+ (click)="selectedRows.set([])"
3374
+ >
3375
+ Clear
3376
+ </button>
3377
+ </div>
3378
+ }
3379
+
3380
+ <!-- Table -->
3381
+ <div class="overflow-auto border border-border rounded-sm">
3382
+ <table
3383
+ snyTable
3384
+ [variant]="variant()"
3385
+ [density]="density()"
3386
+ [hoverable]="hoverable()"
3387
+ [stickyHeader]="stickyHeader()"
3388
+ >
3389
+ <thead snyTableHeader>
3390
+ <tr snyTableRow>
3391
+ @if (selectable()) {
3392
+ <th snyTableHead class="w-12">
3393
+ <input
3394
+ type="checkbox"
3395
+ snyCheckbox
3396
+ [checked]="allSelected()"
3397
+ [indeterminate]="someSelected() && !allSelected()"
3398
+ (change)="toggleSelectAll()"
3399
+ />
3400
+ </th>
3401
+ }
3402
+ @if (expandable()) {
3403
+ <th snyTableHead class="w-10"></th>
3404
+ }
3405
+ @let sort = sortState();
3406
+ @let headerDefs = headerCellDefMap();
3407
+ @for (col of visibleColumns(); track col.key) {
3408
+ <th
3409
+ snyTableHead
3410
+ [style.width]="col.width ?? null"
3411
+ [class]="col.sortable ? 'cursor-pointer select-none' : ''"
3412
+ (click)="col.sortable ? toggleSort(col.key) : null"
3413
+ >
3414
+ @if (headerDefs.has(col.key)) {
3415
+ <ng-container
3416
+ [ngTemplateOutlet]="headerDefs.get(col.key)!"
3417
+ [ngTemplateOutletContext]="{ $implicit: col }"
3418
+ />
3419
+ } @else {
3420
+ <div class="flex items-center gap-1">
3421
+ <span>{{ col.label }}</span>
3422
+ @if (col.sortable) {
3423
+ @let isActive = sort.key === col.key;
3424
+ @if (isActive && sort.direction === 'asc') {
3425
+ <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m5 12 7-7 7 7"/></svg>
3426
+ } @else if (isActive && sort.direction === 'desc') {
3427
+ <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m19 12-7 7-7-7"/></svg>
3428
+ } @else {
3429
+ <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="opacity-30"><path d="m7 15 5 5 5-5"/><path d="m7 9 5-5 5 5"/></svg>
3430
+ }
3431
+ }
3432
+ </div>
3433
+ }
3434
+ </th>
3435
+ }
3436
+ </tr>
3437
+ </thead>
3438
+ <tbody snyTableBody>
3439
+ @if (loading()) {
3440
+ @for (i of skeletonRows(); track i) {
3441
+ <tr snyTableRow>
3442
+ @if (selectable()) {
3443
+ <td snyTableCell class="w-12"><div snySkeleton class="w-4 h-4 rounded"></div></td>
3444
+ }
3445
+ @if (expandable()) {
3446
+ <td snyTableCell class="w-10"><div snySkeleton class="w-4 h-4 rounded"></div></td>
3447
+ }
3448
+ @for (col of visibleColumns(); track col.key) {
3449
+ <td snyTableCell [style.width]="col.width ?? null">
3450
+ <div snySkeleton class="w-full h-4 rounded"></div>
3451
+ </td>
3452
+ }
3453
+ </tr>
3454
+ }
3455
+ } @else if (paginatedData().length === 0) {
3456
+ <tr snyTableRow>
3457
+ <td
3458
+ snyTableCell
3459
+ [attr.colspan]="totalColSpan()"
3460
+ class="text-center text-muted-foreground py-8"
3461
+ >
3462
+ {{ noDataText() }}
3463
+ </td>
3464
+ </tr>
3465
+ } @else {
3466
+ @let cellDefs = cellDefMap();
3467
+ @let cols = visibleColumns();
3468
+ @let expandTpl = rowExpandDef();
3469
+ @for (row of paginatedData(); track trackByFn(row, $index)) {
3470
+ <tr
3471
+ snyTableRow
3472
+ [attr.data-state]="isSelected(row) ? 'selected' : null"
3473
+ (click)="onRowClick(row)"
3474
+ class="cursor-pointer"
3475
+ >
3476
+ @if (selectable()) {
3477
+ <td snyTableCell class="w-12">
3478
+ <input
3479
+ type="checkbox"
3480
+ snyCheckbox
3481
+ [checked]="isSelected(row)"
3482
+ (change)="toggleRowSelection(row)"
3483
+ (click)="$event.stopPropagation()"
3484
+ />
3485
+ </td>
3486
+ }
3487
+ @if (expandable()) {
3488
+ <td snyTableCell class="w-10">
3489
+ <button
3490
+ class="p-0.5 rounded hover:bg-accent transition-transform duration-150"
3491
+ [class.rotate-90]="isExpanded(row)"
3492
+ (click)="toggleRowExpansion(row); $event.stopPropagation()"
3493
+ >
3494
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
3495
+ </button>
3496
+ </td>
3497
+ }
3498
+ @for (col of cols; track col.key) {
3499
+ <td snyTableCell [style.width]="col.width ?? null">
3500
+ @if (cellDefs.has(col.key)) {
3501
+ <ng-container
3502
+ [ngTemplateOutlet]="cellDefs.get(col.key)!"
3503
+ [ngTemplateOutletContext]="{ $implicit: row[col.key], row: row }"
3504
+ />
3505
+ } @else {
3506
+ {{ row[col.key] }}
3507
+ }
3508
+ </td>
3509
+ }
3510
+ </tr>
3511
+ @if (expandable() && isExpanded(row) && expandTpl) {
3512
+ <tr snyTableRow>
3513
+ <td snyTableCell [attr.colspan]="totalColSpan()" class="bg-muted/30">
3514
+ <ng-container
3515
+ [ngTemplateOutlet]="expandTpl.template"
3516
+ [ngTemplateOutletContext]="{ $implicit: row }"
3517
+ />
3518
+ </td>
3519
+ </tr>
3520
+ }
3521
+ }
3522
+ }
3523
+ </tbody>
3524
+ </table>
3525
+ </div>
3526
+
3527
+ <!-- Footer -->
3528
+ @if (paginated()) {
3529
+ <div class="flex flex-col sm:flex-row items-start sm:items-center justify-between mt-4 gap-3 sm:gap-4">
3530
+ <span class="text-sm text-muted-foreground">
3531
+ @if (selectable()) {
3532
+ {{ selectedRows().length }} of {{ filteredData().length }} row(s) selected
3533
+ } @else {
3534
+ {{ filteredData().length }} row(s)
3535
+ }
3536
+ </span>
3537
+ <div class="flex items-center gap-3 sm:gap-4 flex-wrap">
3538
+ <div class="flex items-center gap-2">
3539
+ <span class="hidden sm:inline text-sm text-muted-foreground whitespace-nowrap">Rows per page</span>
3540
+ <sny-select
3541
+ [options]="pageSizeOptions()"
3542
+ [value]="pageSizeValue()"
3543
+ (valueChange)="onPageSizeChange($event)"
3544
+ size="sm"
3545
+ class="w-20"
3546
+ />
3547
+ </div>
3548
+ <sny-pagination
3549
+ [currentPage]="currentPage()"
3550
+ (currentPageChange)="currentPage.set($event)"
3551
+ [totalPages]="totalPages()"
3552
+ />
3553
+ </div>
3554
+ </div>
3555
+ }
3556
+ `,
3557
+ }]
3558
+ }], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], density: [{ type: i0.Input, args: [{ isSignal: true, alias: "density", required: false }] }], hoverable: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoverable", required: false }] }], stickyHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "stickyHeader", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], paginated: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginated", required: false }] }], filterable: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterable", required: false }] }], showExport: [{ type: i0.Input, args: [{ isSignal: true, alias: "showExport", required: false }] }], showColumnToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showColumnToggle", required: false }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], loadingRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingRows", required: false }] }], paginationConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginationConfig", required: false }] }], trackBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackBy", required: false }] }], noDataText: [{ type: i0.Input, args: [{ isSignal: true, alias: "noDataText", required: false }] }], selectedRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedRows", required: false }] }, { type: i0.Output, args: ["selectedRowsChange"] }], sortChanged: [{ type: i0.Output, args: ["sortChanged"] }], rowClicked: [{ type: i0.Output, args: ["rowClicked"] }], dataExported: [{ type: i0.Output, args: ["dataExported"] }], cellDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => SnyCellDefDirective), { isSignal: true }] }], headerCellDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => SnyHeaderCellDefDirective), { isSignal: true }] }], bulkActionsDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SnyBulkActionsDefDirective), { isSignal: true }] }], rowExpandDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SnyRowExpandDefDirective), { isSignal: true }] }] } });
3559
+
3560
+ class SnySheetRef {
3561
+ cdkRef;
3562
+ constructor(cdkRef) {
3563
+ this.cdkRef = cdkRef;
3564
+ }
3565
+ close(result) {
3566
+ this.cdkRef.close(result);
3567
+ }
3568
+ get closed() {
3569
+ return this.cdkRef.closed;
3570
+ }
3571
+ }
3572
+
3573
+ const DEFAULT_SHEET_CONFIG = {
3574
+ side: 'right',
3575
+ closeOnBackdrop: true,
3576
+ closeOnEsc: true,
3577
+ };
3578
+ const SHEET_PANEL_CLASS = {
3579
+ right: 'sny-sheet-right',
3580
+ left: 'sny-sheet-left',
3581
+ top: 'sny-sheet-top',
3582
+ bottom: 'sny-sheet-bottom',
3583
+ };
3584
+
3585
+ const SNY_SHEET_DATA = new InjectionToken('SNY_SHEET_DATA');
3586
+ class SnySheetService {
3587
+ cdkDialog = inject(Dialog);
3588
+ injector = inject(Injector);
3589
+ open(component, config = {}) {
3590
+ const merged = { ...DEFAULT_SHEET_CONFIG, ...config };
3591
+ const side = merged.side ?? 'right';
3592
+ const disableClose = !merged.closeOnBackdrop || !merged.closeOnEsc;
3593
+ const overlay = this._getOverlayConfig(side);
3594
+ const cdkRef = this.cdkDialog.open(component, {
3595
+ disableClose,
3596
+ hasBackdrop: true,
3597
+ backdropClass: 'sny-dialog-backdrop',
3598
+ panelClass: ['sny-sheet-panel', SHEET_PANEL_CLASS[side]],
3599
+ positionStrategy: overlay.positionStrategy,
3600
+ width: overlay.width,
3601
+ maxWidth: overlay.maxWidth,
3602
+ height: overlay.height,
3603
+ maxHeight: overlay.maxHeight,
3604
+ ariaLabelledBy: merged.ariaLabelledBy,
3605
+ ariaDescribedBy: merged.ariaDescribedBy,
3606
+ data: merged.data,
3607
+ providers: merged.data != null
3608
+ ? [{ provide: SNY_SHEET_DATA, useValue: merged.data }]
3609
+ : [],
3610
+ });
3611
+ if (disableClose) {
3612
+ if (merged.closeOnBackdrop) {
3613
+ const sub = cdkRef.backdropClick.subscribe(() => cdkRef.close());
3614
+ cdkRef.closed.subscribe(() => sub.unsubscribe());
3615
+ }
3616
+ if (merged.closeOnEsc) {
3617
+ const sub = cdkRef.keydownEvents.subscribe(event => {
3618
+ if (event.key === 'Escape')
3619
+ cdkRef.close();
3620
+ });
3621
+ cdkRef.closed.subscribe(() => sub.unsubscribe());
3622
+ }
3623
+ }
3624
+ return new SnySheetRef(cdkRef);
3625
+ }
3626
+ closeAll() {
3627
+ this.cdkDialog.closeAll();
3628
+ }
3629
+ _getOverlayConfig(side) {
3630
+ const strategy = createGlobalPositionStrategy(this.injector);
3631
+ switch (side) {
3632
+ case 'right':
3633
+ return {
3634
+ positionStrategy: strategy.top('0').right('0'),
3635
+ width: '75%',
3636
+ maxWidth: '24rem',
3637
+ height: '100vh',
3638
+ maxHeight: '100vh',
3639
+ };
3640
+ case 'left':
3641
+ return {
3642
+ positionStrategy: strategy.top('0').left('0'),
3643
+ width: '75%',
3644
+ maxWidth: '24rem',
3645
+ height: '100vh',
3646
+ maxHeight: '100vh',
3647
+ };
3648
+ case 'top':
3649
+ return {
3650
+ positionStrategy: strategy.top('0').centerHorizontally(),
3651
+ width: '100vw',
3652
+ maxWidth: '100vw',
3653
+ };
3654
+ case 'bottom':
3655
+ return {
3656
+ positionStrategy: strategy.bottom('0').centerHorizontally(),
3657
+ width: '100vw',
3658
+ maxWidth: '100vw',
3659
+ };
3660
+ }
3661
+ }
3662
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3663
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetService, providedIn: 'root' });
3664
+ }
3665
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetService, decorators: [{
3666
+ type: Injectable,
3667
+ args: [{ providedIn: 'root' }]
3668
+ }] });
3669
+
3670
+ class SnySheetHeaderDirective {
3671
+ class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
3672
+ computedClass = computed(() => cn('flex flex-col space-y-2', this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
3673
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetHeaderDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
3674
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnySheetHeaderDirective, isStandalone: true, selector: "[snySheetHeader]", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "computedClass()" } }, ngImport: i0 });
3675
+ }
3676
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetHeaderDirective, decorators: [{
3677
+ type: Directive,
3678
+ args: [{
3679
+ selector: '[snySheetHeader]',
3680
+ standalone: true,
3681
+ host: { '[class]': 'computedClass()' },
3682
+ }]
3683
+ }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
3684
+ class SnySheetTitleDirective {
3685
+ class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
3686
+ computedClass = computed(() => cn('text-lg font-semibold text-foreground', this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
3687
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetTitleDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
3688
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnySheetTitleDirective, isStandalone: true, selector: "[snySheetTitle]", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "computedClass()" } }, ngImport: i0 });
3689
+ }
3690
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetTitleDirective, decorators: [{
3691
+ type: Directive,
3692
+ args: [{
3693
+ selector: '[snySheetTitle]',
3694
+ standalone: true,
3695
+ host: { '[class]': 'computedClass()' },
3696
+ }]
3697
+ }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
3698
+ class SnySheetDescriptionDirective {
3699
+ class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
3700
+ computedClass = computed(() => cn('text-sm text-muted-foreground', this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
3701
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetDescriptionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
3702
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnySheetDescriptionDirective, isStandalone: true, selector: "[snySheetDescription]", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "computedClass()" } }, ngImport: i0 });
3703
+ }
3704
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetDescriptionDirective, decorators: [{
3705
+ type: Directive,
3706
+ args: [{
3707
+ selector: '[snySheetDescription]',
3708
+ standalone: true,
3709
+ host: { '[class]': 'computedClass()' },
3710
+ }]
3711
+ }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
3712
+ class SnySheetContentDirective {
3713
+ class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
3714
+ computedClass = computed(() => cn('py-4', this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
3715
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
3716
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnySheetContentDirective, isStandalone: true, selector: "[snySheetContent]", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "computedClass()" } }, ngImport: i0 });
3717
+ }
3718
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetContentDirective, decorators: [{
3719
+ type: Directive,
3720
+ args: [{
3721
+ selector: '[snySheetContent]',
3722
+ standalone: true,
3723
+ host: { '[class]': 'computedClass()' },
3724
+ }]
3725
+ }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
3726
+ class SnySheetCloseDirective {
3727
+ class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
3728
+ computedClass = computed(() => cn('absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2', this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
3729
+ dialogRef = inject(DialogRef, { optional: true });
3730
+ onClick() {
3731
+ this.dialogRef?.close();
3732
+ }
3733
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetCloseDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
3734
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnySheetCloseDirective, isStandalone: true, selector: "[snySheetClose]", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "onClick()" }, properties: { "class": "computedClass()" } }, ngImport: i0 });
3735
+ }
3736
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnySheetCloseDirective, decorators: [{
3737
+ type: Directive,
3738
+ args: [{
3739
+ selector: '[snySheetClose]',
3740
+ standalone: true,
3741
+ host: {
3742
+ '[class]': 'computedClass()',
3743
+ '(click)': 'onClick()',
3744
+ },
3745
+ }]
3746
+ }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
3747
+
3748
+ const alertVariants = cva('relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground', {
3749
+ variants: {
3750
+ variant: {
3751
+ default: 'bg-background text-foreground border-border',
3752
+ destructive: 'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive bg-destructive/10',
3753
+ success: 'border-green-500/50 text-green-700 dark:text-green-400 dark:border-green-500 [&>svg]:text-green-600 bg-green-50 dark:bg-green-950/30',
3754
+ warning: 'border-yellow-500/50 text-yellow-700 dark:text-yellow-400 dark:border-yellow-500 [&>svg]:text-yellow-600 bg-yellow-50 dark:bg-yellow-950/30',
3755
+ info: 'border-blue-500/50 text-blue-700 dark:text-blue-400 dark:border-blue-500 [&>svg]:text-blue-600 bg-blue-50 dark:bg-blue-950/30',
3756
+ },
3757
+ },
3758
+ defaultVariants: {
3759
+ variant: 'default',
3760
+ },
3761
+ });
3762
+
3763
+ class SnyAlertDirective {
3764
+ variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
3765
+ dismissible = input(false, ...(ngDevMode ? [{ debugName: "dismissible" }] : /* istanbul ignore next */ []));
3766
+ class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
3767
+ visible = signal(true, ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
3768
+ role = computed(() => {
3769
+ const v = this.variant();
3770
+ return v === 'destructive' || v === 'warning' || v === 'info' ? 'alert' : 'status';
3771
+ }, ...(ngDevMode ? [{ debugName: "role" }] : /* istanbul ignore next */ []));
3772
+ ariaLive = computed(() => {
3773
+ const v = this.variant();
3774
+ return v === 'destructive' || v === 'warning' ? 'assertive' : 'polite';
3775
+ }, ...(ngDevMode ? [{ debugName: "ariaLive" }] : /* istanbul ignore next */ []));
3776
+ computedClass = computed(() => cn(alertVariants({ variant: this.variant() }), this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
3777
+ dismiss() {
3778
+ this.visible.set(false);
3779
+ }
2684
3780
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyAlertDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2685
3781
  static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnyAlertDirective, isStandalone: true, selector: "[snyAlert]", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "computedClass()", "attr.role": "role()", "attr.aria-live": "ariaLive()", "style.display": "visible() ? null : \"none\"" } }, exportAs: ["snyAlert"], ngImport: i0 });
2686
3782
  }
@@ -2966,200 +4062,39 @@ class SnyTooltipDirective {
2966
4062
  top = hostRect.top + (hostRect.height - tooltipRect.height) / 2;
2967
4063
  left = hostRect.left - tooltipRect.width - gap;
2968
4064
  break;
2969
- case 'right':
2970
- top = hostRect.top + (hostRect.height - tooltipRect.height) / 2;
2971
- left = hostRect.right + gap;
2972
- break;
2973
- }
2974
- this.tooltipEl.style.top = `${top}px`;
2975
- this.tooltipEl.style.left = `${left}px`;
2976
- }
2977
- destroyTooltip() {
2978
- if (this.tooltipEl) {
2979
- this.tooltipEl.remove();
2980
- this.tooltipEl = null;
2981
- }
2982
- }
2983
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyTooltipDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2984
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnyTooltipDirective, isStandalone: true, selector: "[snyTooltip]", inputs: { snyTooltip: { classPropertyName: "snyTooltip", publicName: "snyTooltip", isSignal: true, isRequired: true, transformFunction: null }, tooltipPosition: { classPropertyName: "tooltipPosition", publicName: "tooltipPosition", isSignal: true, isRequired: false, transformFunction: null }, tooltipDelay: { classPropertyName: "tooltipDelay", publicName: "tooltipDelay", isSignal: true, isRequired: false, transformFunction: null }, tooltipDisabled: { classPropertyName: "tooltipDisabled", publicName: "tooltipDisabled", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "mouseenter": "show()", "mouseleave": "hide()", "focus": "show()", "blur": "hide()", "keydown.escape": "hide()" }, properties: { "attr.aria-describedby": "isOpen() ? tooltipId : null" } }, exportAs: ["snyTooltip"], ngImport: i0 });
2985
- }
2986
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyTooltipDirective, decorators: [{
2987
- type: Directive,
2988
- args: [{
2989
- selector: '[snyTooltip]',
2990
- standalone: true,
2991
- exportAs: 'snyTooltip',
2992
- host: {
2993
- '(mouseenter)': 'show()',
2994
- '(mouseleave)': 'hide()',
2995
- '(focus)': 'show()',
2996
- '(blur)': 'hide()',
2997
- '(keydown.escape)': 'hide()',
2998
- '[attr.aria-describedby]': 'isOpen() ? tooltipId : null',
2999
- },
3000
- }]
3001
- }], ctorParameters: () => [], propDecorators: { snyTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "snyTooltip", required: true }] }], tooltipPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltipPosition", required: false }] }], tooltipDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltipDelay", required: false }] }], tooltipDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltipDisabled", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
3002
-
3003
- const dropdownContentVariants = cva('z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md', {
3004
- variants: {},
3005
- defaultVariants: {},
3006
- });
3007
- const dropdownItemVariants = cva('relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors data-[active]:bg-accent data-[active]:text-accent-foreground', {
3008
- variants: {
3009
- variant: {
3010
- default: '',
3011
- destructive: 'text-destructive data-[active]:bg-destructive/10 data-[active]:text-destructive',
3012
- },
3013
- },
3014
- defaultVariants: {
3015
- variant: 'default',
3016
- },
3017
- });
3018
-
3019
- const SNY_DROPDOWN = new InjectionToken('SnyDropdown');
3020
- class SnyDropdownDirective {
3021
- elementRef = inject(ElementRef);
3022
- isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
3023
- toggle() { this.isOpen.update((v) => !v); }
3024
- open() { this.isOpen.set(true); }
3025
- close() { this.isOpen.set(false); }
3026
- onDocumentClick(event) {
3027
- if (!this.elementRef.nativeElement.contains(event.target)) {
3028
- this.close();
3029
- }
3030
- }
3031
- onEscape() {
3032
- this.close();
3033
- }
3034
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyDropdownDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
3035
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.5", type: SnyDropdownDirective, isStandalone: true, selector: "[snyDropdown]", host: { listeners: { "document:click": "onDocumentClick($event)", "keydown.escape": "onEscape()" }, properties: { "class": "\"relative inline-block\"" } }, providers: [{ provide: SNY_DROPDOWN, useExisting: SnyDropdownDirective }], exportAs: ["snyDropdown"], ngImport: i0 });
3036
- }
3037
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyDropdownDirective, decorators: [{
3038
- type: Directive,
3039
- args: [{
3040
- selector: '[snyDropdown]',
3041
- standalone: true,
3042
- exportAs: 'snyDropdown',
3043
- providers: [{ provide: SNY_DROPDOWN, useExisting: SnyDropdownDirective }],
3044
- host: {
3045
- '[class]': '"relative inline-block"',
3046
- },
3047
- }]
3048
- }], propDecorators: { onDocumentClick: [{
3049
- type: HostListener,
3050
- args: ['document:click', ['$event']]
3051
- }], onEscape: [{
3052
- type: HostListener,
3053
- args: ['keydown.escape']
3054
- }] } });
3055
- class SnyDropdownTriggerDirective {
3056
- dropdown = inject(SNY_DROPDOWN);
3057
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyDropdownTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
3058
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.5", type: SnyDropdownTriggerDirective, isStandalone: true, selector: "[snyDropdownTrigger]", host: { listeners: { "click": "dropdown.toggle()" }, properties: { "attr.aria-expanded": "dropdown.isOpen()", "attr.aria-haspopup": "\"menu\"" } }, ngImport: i0 });
3059
- }
3060
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyDropdownTriggerDirective, decorators: [{
3061
- type: Directive,
3062
- args: [{
3063
- selector: '[snyDropdownTrigger]',
3064
- standalone: true,
3065
- host: {
3066
- '(click)': 'dropdown.toggle()',
3067
- '[attr.aria-expanded]': 'dropdown.isOpen()',
3068
- '[attr.aria-haspopup]': '"menu"',
3069
- },
3070
- }]
3071
- }] });
3072
- class SnyDropdownContentDirective {
3073
- dropdown = inject(SNY_DROPDOWN);
3074
- class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
3075
- computedClass = computed(() => cn(dropdownContentVariants(), 'absolute mt-1 left-0 animate-in fade-in-0 zoom-in-95', this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
3076
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyDropdownContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
3077
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnyDropdownContentDirective, isStandalone: true, selector: "[snyDropdownContent]", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "menu" }, properties: { "class": "computedClass()", "style.display": "dropdown.isOpen() ? \"\" : \"none\"" } }, ngImport: i0 });
3078
- }
3079
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyDropdownContentDirective, decorators: [{
3080
- type: Directive,
3081
- args: [{
3082
- selector: '[snyDropdownContent]',
3083
- standalone: true,
3084
- host: {
3085
- 'role': 'menu',
3086
- '[class]': 'computedClass()',
3087
- '[style.display]': 'dropdown.isOpen() ? "" : "none"',
3088
- },
3089
- }]
3090
- }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
3091
- class SnyMenuContentDirective {
3092
- class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
3093
- computedClass = computed(() => cn(dropdownContentVariants(), this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
3094
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyMenuContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
3095
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnyMenuContentDirective, isStandalone: true, selector: "[snyMenuContent]", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "computedClass()" } }, ngImport: i0 });
3096
- }
3097
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyMenuContentDirective, decorators: [{
3098
- type: Directive,
3099
- args: [{
3100
- selector: '[snyMenuContent]',
3101
- standalone: true,
3102
- host: {
3103
- '[class]': 'computedClass()',
3104
- },
3105
- }]
3106
- }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
3107
- class SnyMenuItemDirective {
3108
- dropdown = inject(SNY_DROPDOWN, { optional: true });
3109
- variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
3110
- class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
3111
- computedClass = computed(() => cn(dropdownItemVariants({ variant: this.variant() }), 'cursor-pointer hover:bg-accent hover:text-accent-foreground', this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
3112
- onClick() {
3113
- this.dropdown?.close();
4065
+ case 'right':
4066
+ top = hostRect.top + (hostRect.height - tooltipRect.height) / 2;
4067
+ left = hostRect.right + gap;
4068
+ break;
4069
+ }
4070
+ this.tooltipEl.style.top = `${top}px`;
4071
+ this.tooltipEl.style.left = `${left}px`;
3114
4072
  }
3115
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyMenuItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
3116
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnyMenuItemDirective, isStandalone: true, selector: "[snyMenuItem]", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "menuitem" }, listeners: { "click": "onClick()" }, properties: { "class": "computedClass()" } }, ngImport: i0 });
3117
- }
3118
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyMenuItemDirective, decorators: [{
3119
- type: Directive,
3120
- args: [{
3121
- selector: '[snyMenuItem]',
3122
- standalone: true,
3123
- host: {
3124
- 'role': 'menuitem',
3125
- '[class]': 'computedClass()',
3126
- '(click)': 'onClick()',
3127
- },
3128
- }]
3129
- }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
3130
- class SnyMenuSeparatorDirective {
3131
- class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
3132
- computedClass = computed(() => cn('-mx-1 my-1 h-px bg-muted', this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
3133
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyMenuSeparatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
3134
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnyMenuSeparatorDirective, isStandalone: true, selector: "[snyMenuSeparator]", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "separator" }, properties: { "class": "computedClass()" } }, ngImport: i0 });
3135
- }
3136
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyMenuSeparatorDirective, decorators: [{
3137
- type: Directive,
3138
- args: [{
3139
- selector: '[snyMenuSeparator]',
3140
- standalone: true,
3141
- host: {
3142
- 'role': 'separator',
3143
- '[class]': 'computedClass()',
3144
- },
3145
- }]
3146
- }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
3147
- class SnyMenuLabelDirective {
3148
- class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
3149
- computedClass = computed(() => cn('px-2 py-1.5 text-sm font-semibold', this.class()), ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
3150
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyMenuLabelDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
3151
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnyMenuLabelDirective, isStandalone: true, selector: "[snyMenuLabel]", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "computedClass()" } }, ngImport: i0 });
4073
+ destroyTooltip() {
4074
+ if (this.tooltipEl) {
4075
+ this.tooltipEl.remove();
4076
+ this.tooltipEl = null;
4077
+ }
4078
+ }
4079
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyTooltipDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
4080
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SnyTooltipDirective, isStandalone: true, selector: "[snyTooltip]", inputs: { snyTooltip: { classPropertyName: "snyTooltip", publicName: "snyTooltip", isSignal: true, isRequired: true, transformFunction: null }, tooltipPosition: { classPropertyName: "tooltipPosition", publicName: "tooltipPosition", isSignal: true, isRequired: false, transformFunction: null }, tooltipDelay: { classPropertyName: "tooltipDelay", publicName: "tooltipDelay", isSignal: true, isRequired: false, transformFunction: null }, tooltipDisabled: { classPropertyName: "tooltipDisabled", publicName: "tooltipDisabled", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "mouseenter": "show()", "mouseleave": "hide()", "focus": "show()", "blur": "hide()", "keydown.escape": "hide()" }, properties: { "attr.aria-describedby": "isOpen() ? tooltipId : null" } }, exportAs: ["snyTooltip"], ngImport: i0 });
3152
4081
  }
3153
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyMenuLabelDirective, decorators: [{
4082
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyTooltipDirective, decorators: [{
3154
4083
  type: Directive,
3155
4084
  args: [{
3156
- selector: '[snyMenuLabel]',
4085
+ selector: '[snyTooltip]',
3157
4086
  standalone: true,
4087
+ exportAs: 'snyTooltip',
3158
4088
  host: {
3159
- '[class]': 'computedClass()',
4089
+ '(mouseenter)': 'show()',
4090
+ '(mouseleave)': 'hide()',
4091
+ '(focus)': 'show()',
4092
+ '(blur)': 'hide()',
4093
+ '(keydown.escape)': 'hide()',
4094
+ '[attr.aria-describedby]': 'isOpen() ? tooltipId : null',
3160
4095
  },
3161
4096
  }]
3162
- }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
4097
+ }], ctorParameters: () => [], propDecorators: { snyTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "snyTooltip", required: true }] }], tooltipPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltipPosition", required: false }] }], tooltipDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltipDelay", required: false }] }], tooltipDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltipDisabled", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
3163
4098
 
3164
4099
  const fileInputVariants = cva('flex w-full cursor-pointer items-center gap-2 rounded-md border bg-background px-3 py-2 text-sm ring-offset-background transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50', {
3165
4100
  variants: {
@@ -3197,19 +4132,7 @@ class SnyFileInputComponent {
3197
4132
  isDragOver = signal(false, ...(ngDevMode ? [{ debugName: "isDragOver" }] : /* istanbul ignore next */ []));
3198
4133
  _onChange = () => { };
3199
4134
  onTouched = () => { };
3200
- _writing = false;
3201
- constructor() {
3202
- effect(() => {
3203
- const val = this.value();
3204
- if (this._writing) {
3205
- this._writing = false;
3206
- return;
3207
- }
3208
- this._onChange(val);
3209
- });
3210
- }
3211
4135
  writeValue(val) {
3212
- this._writing = true;
3213
4136
  this.value.set(val ?? null);
3214
4137
  }
3215
4138
  registerOnChange(fn) {
@@ -3255,6 +4178,7 @@ class SnyFileInputComponent {
3255
4178
  }
3256
4179
  clear() {
3257
4180
  this.value.set(null);
4181
+ this._onChange(null);
3258
4182
  const inputEl = this.fileInputRef()?.nativeElement;
3259
4183
  if (inputEl)
3260
4184
  inputEl.value = '';
@@ -3270,6 +4194,7 @@ class SnyFileInputComponent {
3270
4194
  }
3271
4195
  }
3272
4196
  this.value.set(files);
4197
+ this._onChange(files);
3273
4198
  this.fileChange.emit(files);
3274
4199
  }
3275
4200
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyFileInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -3333,7 +4258,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
3333
4258
  </label>
3334
4259
  `,
3335
4260
  }]
3336
- }], ctorParameters: () => [], propDecorators: { accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], maxSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSize", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], fileChange: [{ type: i0.Output, args: ["fileChange"] }], error: [{ type: i0.Output, args: ["error"] }], fileInputRef: [{ type: i0.ViewChild, args: ['fileInput', { isSignal: true }] }] } });
4261
+ }], propDecorators: { accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], maxSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSize", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], fileChange: [{ type: i0.Output, args: ["fileChange"] }], error: [{ type: i0.Output, args: ["error"] }], fileInputRef: [{ type: i0.ViewChild, args: ['fileInput', { isSignal: true }] }] } });
3337
4262
 
3338
4263
  const fieldsetVariants = cva('space-y-4', {
3339
4264
  variants: {
@@ -3426,19 +4351,7 @@ class SnyRatingComponent {
3426
4351
  hoverValue = signal(null, ...(ngDevMode ? [{ debugName: "hoverValue" }] : /* istanbul ignore next */ []));
3427
4352
  _onChange = () => { };
3428
4353
  onTouched = () => { };
3429
- _writing = false;
3430
- constructor() {
3431
- effect(() => {
3432
- const val = this.value();
3433
- if (this._writing) {
3434
- this._writing = false;
3435
- return;
3436
- }
3437
- this._onChange(val);
3438
- });
3439
- }
3440
4354
  writeValue(val) {
3441
- this._writing = true;
3442
4355
  this.value.set(val ?? 0);
3443
4356
  }
3444
4357
  registerOnChange(fn) {
@@ -3484,6 +4397,7 @@ class SnyRatingComponent {
3484
4397
  if (this.isDisabled())
3485
4398
  return;
3486
4399
  this.value.set(index);
4400
+ this._onChange(index);
3487
4401
  }
3488
4402
  onStarHover(index) {
3489
4403
  if (this.isDisabled())
@@ -3497,26 +4411,31 @@ class SnyRatingComponent {
3497
4411
  if (this.isDisabled())
3498
4412
  return;
3499
4413
  const step = this.half() ? 0.5 : 1;
4414
+ let newVal;
3500
4415
  switch (event.key) {
3501
4416
  case 'ArrowRight':
3502
4417
  case 'ArrowUp':
3503
4418
  event.preventDefault();
3504
- this.value.update((v) => Math.min(this.max(), v + step));
4419
+ newVal = Math.min(this.max(), this.value() + step);
3505
4420
  break;
3506
4421
  case 'ArrowLeft':
3507
4422
  case 'ArrowDown':
3508
4423
  event.preventDefault();
3509
- this.value.update((v) => Math.max(0, v - step));
4424
+ newVal = Math.max(0, this.value() - step);
3510
4425
  break;
3511
4426
  case 'Home':
3512
4427
  event.preventDefault();
3513
- this.value.set(0);
4428
+ newVal = 0;
3514
4429
  break;
3515
4430
  case 'End':
3516
4431
  event.preventDefault();
3517
- this.value.set(this.max());
4432
+ newVal = this.max();
3518
4433
  break;
3519
4434
  }
4435
+ if (newVal !== undefined) {
4436
+ this.value.set(newVal);
4437
+ this._onChange(newVal);
4438
+ }
3520
4439
  }
3521
4440
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyRatingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3522
4441
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: SnyRatingComponent, isStandalone: true, selector: "sny-rating", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, ratingVariant: { classPropertyName: "ratingVariant", publicName: "ratingVariant", isSignal: true, isRequired: false, transformFunction: null }, half: { classPropertyName: "half", publicName: "half", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { attributes: { "role": "slider", "tabindex": "0" }, listeners: { "keydown": "onKeydown($event)", "mouseleave": "onMouseLeave()", "blur": "onTouched()" }, properties: { "attr.aria-valuenow": "value()", "attr.aria-valuemin": "0", "attr.aria-valuemax": "max()", "attr.aria-label": "\"Rating\"", "attr.aria-readonly": "readonly() || null", "class": "computedClass()" } }, providers: [
@@ -3579,7 +4498,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
3579
4498
  }
3580
4499
  `,
3581
4500
  }]
3582
- }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], ratingVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "ratingVariant", required: false }] }], half: [{ type: i0.Input, args: [{ isSignal: true, alias: "half", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
4501
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], ratingVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "ratingVariant", required: false }] }], half: [{ type: i0.Input, args: [{ isSignal: true, alias: "half", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
3583
4502
 
3584
4503
  class SnyNavbarDirective {
3585
4504
  variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
@@ -3744,180 +4663,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
3744
4663
  }]
3745
4664
  }], propDecorators: { side: [{ type: i0.Input, args: [{ isSignal: true, alias: "side", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
3746
4665
 
3747
- const paginationItemVariants = cva('inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50', {
3748
- variants: {
3749
- variant: {
3750
- default: 'bg-background hover:bg-accent hover:text-accent-foreground',
3751
- outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
3752
- ghost: 'hover:bg-accent hover:text-accent-foreground',
3753
- },
3754
- size: {
3755
- sm: 'h-8 w-8 text-xs',
3756
- md: 'h-9 w-9',
3757
- lg: 'h-10 w-10',
3758
- },
3759
- active: {
3760
- true: 'bg-primary text-primary-foreground hover:bg-primary/90 hover:text-primary-foreground',
3761
- false: '',
3762
- },
3763
- },
3764
- defaultVariants: {
3765
- variant: 'default',
3766
- size: 'md',
3767
- active: false,
3768
- },
3769
- });
3770
-
3771
- function computePageRange(totalPages, currentPage, siblingCount, boundaryCount) {
3772
- const range = (start, end) => Array.from({ length: end - start + 1 }, (_, i) => start + i);
3773
- const startPages = range(1, Math.min(boundaryCount, totalPages));
3774
- const endPages = range(Math.max(totalPages - boundaryCount + 1, boundaryCount + 1), totalPages);
3775
- const siblingsStart = Math.max(Math.min(currentPage - siblingCount, totalPages - boundaryCount - siblingCount * 2 - 1), boundaryCount + 2);
3776
- const siblingsEnd = Math.min(Math.max(currentPage + siblingCount, boundaryCount + siblingCount * 2 + 2), endPages.length > 0 ? endPages[0] - 2 : totalPages - 1);
3777
- const result = [...startPages];
3778
- if (siblingsStart > boundaryCount + 2) {
3779
- result.push('ellipsis');
3780
- }
3781
- else if (boundaryCount + 1 < totalPages - boundaryCount) {
3782
- result.push(boundaryCount + 1);
3783
- }
3784
- result.push(...range(siblingsStart, siblingsEnd));
3785
- if (siblingsEnd < totalPages - boundaryCount - 1) {
3786
- result.push('ellipsis');
3787
- }
3788
- else if (totalPages - boundaryCount > boundaryCount) {
3789
- result.push(totalPages - boundaryCount);
3790
- }
3791
- result.push(...endPages);
3792
- return [...new Set(result)].sort((a, b) => {
3793
- if (a === 'ellipsis')
3794
- return 0;
3795
- if (b === 'ellipsis')
3796
- return 0;
3797
- return a - b;
3798
- });
3799
- }
3800
- class SnyPaginationComponent {
3801
- currentPage = model(1, ...(ngDevMode ? [{ debugName: "currentPage" }] : /* istanbul ignore next */ []));
3802
- totalPages = input.required(...(ngDevMode ? [{ debugName: "totalPages" }] : /* istanbul ignore next */ []));
3803
- siblingCount = input(1, ...(ngDevMode ? [{ debugName: "siblingCount" }] : /* istanbul ignore next */ []));
3804
- boundaryCount = input(1, ...(ngDevMode ? [{ debugName: "boundaryCount" }] : /* istanbul ignore next */ []));
3805
- size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
3806
- variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
3807
- class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
3808
- pages = computed(() => computePageRange(this.totalPages(), this.currentPage(), this.siblingCount(), this.boundaryCount()), ...(ngDevMode ? [{ debugName: "pages" }] : /* istanbul ignore next */ []));
3809
- hasPrev = computed(() => this.currentPage() > 1, ...(ngDevMode ? [{ debugName: "hasPrev" }] : /* istanbul ignore next */ []));
3810
- hasNext = computed(() => this.currentPage() < this.totalPages(), ...(ngDevMode ? [{ debugName: "hasNext" }] : /* istanbul ignore next */ []));
3811
- goToPage(page) {
3812
- if (page === 'ellipsis')
3813
- return;
3814
- this.currentPage.set(page);
3815
- }
3816
- prev() {
3817
- if (this.hasPrev())
3818
- this.currentPage.update((p) => p - 1);
3819
- }
3820
- next() {
3821
- if (this.hasNext())
3822
- this.currentPage.update((p) => p + 1);
3823
- }
3824
- pageClass(page) {
3825
- return cn(paginationItemVariants({
3826
- variant: this.variant(),
3827
- size: this.size(),
3828
- active: page === this.currentPage(),
3829
- }));
3830
- }
3831
- navBtnClass() {
3832
- return cn(paginationItemVariants({ variant: this.variant(), size: this.size(), active: false }));
3833
- }
3834
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyPaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3835
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: SnyPaginationComponent, isStandalone: true, selector: "sny-pagination", inputs: { currentPage: { classPropertyName: "currentPage", publicName: "currentPage", isSignal: true, isRequired: false, transformFunction: null }, totalPages: { classPropertyName: "totalPages", publicName: "totalPages", isSignal: true, isRequired: true, transformFunction: null }, siblingCount: { classPropertyName: "siblingCount", publicName: "siblingCount", isSignal: true, isRequired: false, transformFunction: null }, boundaryCount: { classPropertyName: "boundaryCount", publicName: "boundaryCount", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { currentPage: "currentPageChange" }, host: { attributes: { "role": "navigation", "aria-label": "Pagination" } }, ngImport: i0, template: `
3836
- <div class="flex items-center gap-1">
3837
- <button
3838
- [class]="navBtnClass()"
3839
- [disabled]="!hasPrev()"
3840
- [attr.aria-label]="'Go to previous page'"
3841
- (click)="prev()"
3842
- >
3843
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6"/></svg>
3844
- </button>
3845
-
3846
- @for (page of pages(); track $index) {
3847
- @if (page === 'ellipsis') {
3848
- <span class="flex h-9 w-9 items-center justify-center" aria-hidden="true">...</span>
3849
- } @else {
3850
- <button
3851
- [class]="pageClass(page)"
3852
- [attr.aria-label]="'Page ' + page"
3853
- [attr.aria-current]="page === currentPage() ? 'page' : null"
3854
- (click)="goToPage(page)"
3855
- >
3856
- {{ page }}
3857
- </button>
3858
- }
3859
- }
3860
-
3861
- <button
3862
- [class]="navBtnClass()"
3863
- [disabled]="!hasNext()"
3864
- [attr.aria-label]="'Go to next page'"
3865
- (click)="next()"
3866
- >
3867
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
3868
- </button>
3869
- </div>
3870
- `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
3871
- }
3872
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SnyPaginationComponent, decorators: [{
3873
- type: Component,
3874
- args: [{
3875
- selector: 'sny-pagination',
3876
- standalone: true,
3877
- changeDetection: ChangeDetectionStrategy.OnPush,
3878
- host: {
3879
- 'role': 'navigation',
3880
- 'aria-label': 'Pagination',
3881
- },
3882
- template: `
3883
- <div class="flex items-center gap-1">
3884
- <button
3885
- [class]="navBtnClass()"
3886
- [disabled]="!hasPrev()"
3887
- [attr.aria-label]="'Go to previous page'"
3888
- (click)="prev()"
3889
- >
3890
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6"/></svg>
3891
- </button>
3892
-
3893
- @for (page of pages(); track $index) {
3894
- @if (page === 'ellipsis') {
3895
- <span class="flex h-9 w-9 items-center justify-center" aria-hidden="true">...</span>
3896
- } @else {
3897
- <button
3898
- [class]="pageClass(page)"
3899
- [attr.aria-label]="'Page ' + page"
3900
- [attr.aria-current]="page === currentPage() ? 'page' : null"
3901
- (click)="goToPage(page)"
3902
- >
3903
- {{ page }}
3904
- </button>
3905
- }
3906
- }
3907
-
3908
- <button
3909
- [class]="navBtnClass()"
3910
- [disabled]="!hasNext()"
3911
- [attr.aria-label]="'Go to next page'"
3912
- (click)="next()"
3913
- >
3914
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
3915
- </button>
3916
- </div>
3917
- `,
3918
- }]
3919
- }], propDecorators: { currentPage: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentPage", required: false }] }, { type: i0.Output, args: ["currentPageChange"] }], totalPages: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalPages", required: true }] }], siblingCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "siblingCount", required: false }] }], boundaryCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "boundaryCount", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
3920
-
3921
4666
  const dividerVariants = cva('shrink-0 bg-border', {
3922
4667
  variants: {
3923
4668
  orientation: {
@@ -5104,19 +5849,7 @@ class SnyCalendarComponent {
5104
5849
  weekDays = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];
5105
5850
  _onChange = () => { };
5106
5851
  onTouched = () => { };
5107
- _writing = false;
5108
- constructor() {
5109
- effect(() => {
5110
- const val = this.value();
5111
- if (this._writing) {
5112
- this._writing = false;
5113
- return;
5114
- }
5115
- this._onChange(val);
5116
- });
5117
- }
5118
5852
  writeValue(val) {
5119
- this._writing = true;
5120
5853
  this.value.set(val ?? null);
5121
5854
  if (val) {
5122
5855
  this.viewDate.set(new Date(val.getFullYear(), val.getMonth(), 1));
@@ -5174,6 +5907,7 @@ class SnyCalendarComponent {
5174
5907
  }
5175
5908
  selectDate(date) {
5176
5909
  this.value.set(date);
5910
+ this._onChange(date);
5177
5911
  this.onTouched();
5178
5912
  }
5179
5913
  onKeydown(event) {
@@ -5205,6 +5939,7 @@ class SnyCalendarComponent {
5205
5939
  const next = new Date(current);
5206
5940
  next.setDate(next.getDate() + offset);
5207
5941
  this.value.set(next);
5942
+ this._onChange(next);
5208
5943
  this.viewDate.set(new Date(next.getFullYear(), next.getMonth(), 1));
5209
5944
  }
5210
5945
  createDay(date, isCurrentMonth, today, selected, minDate, maxDate) {
@@ -5311,7 +6046,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
5311
6046
  </div>
5312
6047
  `,
5313
6048
  }]
5314
- }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
6049
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
5315
6050
 
5316
6051
  class SnyValidatorDirective {
5317
6052
  control = input(null, ...(ngDevMode ? [{ debugName: "control" }] : /* istanbul ignore next */ []));
@@ -5372,5 +6107,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
5372
6107
  * Generated bundle index. Do not edit.
5373
6108
  */
5374
6109
 
5375
- export { SNY_ACCORDION, SNY_ACCORDION_ITEM, SNY_CAROUSEL, SNY_CHAT_BUBBLE, SNY_CONFIG, SNY_DIALOG_DATA, SNY_DRAWER, SNY_DROPDOWN, SNY_FAB, SNY_SHEET_DATA, SNY_STEPS, SNY_TABLE, SNY_TABS, SNY_TIMELINE, SnyAccordionContentDirective, SnyAccordionDirective, SnyAccordionItemDirective, SnyAccordionTriggerDirective, SnyAlertDescriptionDirective, SnyAlertDirective, SnyAlertTitleDirective, SnyAvatarComponent, SnyBadgeDirective, SnyBreadcrumbDirective, SnyBreadcrumbItemDirective, SnyBreadcrumbLinkDirective, SnyBreadcrumbListDirective, SnyBreadcrumbPageDirective, SnyBreadcrumbSeparatorDirective, SnyButtonDirective, SnyButtonGroupDirective, SnyCalendarComponent, SnyCardContentDirective, SnyCardDescriptionDirective, SnyCardDirective, SnyCardFooterDirective, SnyCardHeaderDirective, SnyCardTitleDirective, SnyCarouselContentDirective, SnyCarouselDirective, SnyCarouselItemDirective, SnyCarouselNextDirective, SnyCarouselPrevDirective, SnyChatBubbleAvatarDirective, SnyChatBubbleBodyDirective, SnyChatBubbleContentDirective, SnyChatBubbleDirective, SnyChatBubbleFooterDirective, SnyChatBubbleHeaderDirective, SnyCheckboxDirective, SnyComboboxComponent, SnyDialogCloseDirective, SnyDialogContentDirective, SnyDialogDescriptionDirective, SnyDialogFooterDirective, SnyDialogHeaderDirective, SnyDialogRef, SnyDialogService, SnyDialogTitleDirective, SnyDiffComponent, SnyDividerComponent, SnyDockDirective, SnyDockItemDirective, SnyDrawerContentDirective, SnyDrawerLayoutComponent, SnyDrawerLayoutDirective, SnyDrawerSideDirective, SnyDropdownContentDirective, SnyDropdownDirective, SnyDropdownTriggerDirective, SnyFabActionDirective, SnyFabDirective, SnyFabTriggerDirective, SnyFieldsetContentDirective, SnyFieldsetDirective, SnyFieldsetLegendDirective, SnyFileInputComponent, SnyIndicatorBadgeDirective, SnyIndicatorDirective, SnyInputDirective, SnyKbdDirective, SnyLabelDirective, SnyLinkDirective, SnyListDirective, SnyListItemActionDirective, SnyListItemContentDirective, SnyListItemDirective, SnyListItemIconDirective, SnyLoaderComponent, SnyMenuContentDirective, SnyMenuItemDirective, SnyMenuLabelDirective, SnyMenuSeparatorDirective, SnyNavbarBrandDirective, SnyNavbarContentDirective, SnyNavbarDirective, SnyNavbarEndDirective, SnyPaginationComponent, SnyProgressComponent, SnyRadialProgressComponent, SnyRadioDirective, SnyRatingComponent, SnySelectComponent, SnySheetCloseDirective, SnySheetContentDirective, SnySheetDescriptionDirective, SnySheetHeaderDirective, SnySheetRef, SnySheetService, SnySheetTitleDirective, SnySkeletonDirective, SnySliderComponent, SnyStatDescriptionDirective, SnyStatDirective, SnyStatFigureDirective, SnyStatTitleDirective, SnyStatValueDirective, SnyStatusDirective, SnyStepDirective, SnyStepsDirective, SnySwitchComponent, SnyTableBodyDirective, SnyTableCaptionDirective, SnyTableCellDirective, SnyTableDirective, SnyTableFooterDirective, SnyTableHeadDirective, SnyTableHeaderDirective, SnyTableRowDirective, SnyTabsContentDirective, SnyTabsDirective, SnyTabsListDirective, SnyTabsTriggerDirective, SnyTextareaDirective, SnyTimelineDirective, SnyTimelineEndDirective, SnyTimelineItemDirective, SnyTimelineMiddleDirective, SnyTimelineStartDirective, SnyToastService, SnyToasterComponent, SnyToggleDirective, SnyTooltipDirective, SnyValidatorDirective, SnyValidatorHintDirective, ThemeService, alertVariants, avatarVariants, badgeVariants, buttonGroupVariants, buttonVariants, cardVariants, checkboxVariants, cn, comboboxTriggerVariants, dividerVariants, dropdownContentVariants, dropdownItemVariants, fieldsetVariants, fileInputVariants, inputVariants, kbdVariants, labelVariants, linkVariants, loaderVariants, paginationItemVariants, progressBarVariants, progressTrackVariants, provideSonnyUI, radioVariants, ratingVariants, selectTriggerVariants, skeletonVariants, sliderTrackVariants, statusVariants, switchTrackVariants, tableCellVariants, tableVariants, tabsListVariants, tabsTriggerVariants, textareaVariants, toastVariants, toggleVariants, tooltipVariants };
6110
+ export { SNY_ACCORDION, SNY_ACCORDION_ITEM, SNY_CAROUSEL, SNY_CHAT_BUBBLE, SNY_CONFIG, SNY_DIALOG_DATA, SNY_DRAWER, SNY_DROPDOWN, SNY_FAB, SNY_SHEET_DATA, SNY_STEPS, SNY_TABLE, SNY_TABS, SNY_TIMELINE, SnyAccordionContentDirective, SnyAccordionDirective, SnyAccordionItemDirective, SnyAccordionTriggerDirective, SnyAlertDescriptionDirective, SnyAlertDirective, SnyAlertTitleDirective, SnyAvatarComponent, SnyBadgeDirective, SnyBreadcrumbDirective, SnyBreadcrumbItemDirective, SnyBreadcrumbLinkDirective, SnyBreadcrumbListDirective, SnyBreadcrumbPageDirective, SnyBreadcrumbSeparatorDirective, SnyBulkActionsDefDirective, SnyButtonDirective, SnyButtonGroupDirective, SnyCalendarComponent, SnyCardContentDirective, SnyCardDescriptionDirective, SnyCardDirective, SnyCardFooterDirective, SnyCardHeaderDirective, SnyCardTitleDirective, SnyCarouselContentDirective, SnyCarouselDirective, SnyCarouselItemDirective, SnyCarouselNextDirective, SnyCarouselPrevDirective, SnyCellDefDirective, SnyChatBubbleAvatarDirective, SnyChatBubbleBodyDirective, SnyChatBubbleContentDirective, SnyChatBubbleDirective, SnyChatBubbleFooterDirective, SnyChatBubbleHeaderDirective, SnyCheckboxDirective, SnyComboboxComponent, SnyDataTableComponent, SnyDialogCloseDirective, SnyDialogContentDirective, SnyDialogDescriptionDirective, SnyDialogFooterDirective, SnyDialogHeaderDirective, SnyDialogRef, SnyDialogService, SnyDialogTitleDirective, SnyDiffComponent, SnyDividerComponent, SnyDockDirective, SnyDockItemDirective, SnyDrawerContentDirective, SnyDrawerLayoutComponent, SnyDrawerLayoutDirective, SnyDrawerSideDirective, SnyDropdownContentDirective, SnyDropdownDirective, SnyDropdownTriggerDirective, SnyFabActionDirective, SnyFabDirective, SnyFabTriggerDirective, SnyFieldsetContentDirective, SnyFieldsetDirective, SnyFieldsetLegendDirective, SnyFileInputComponent, SnyHeaderCellDefDirective, SnyIndicatorBadgeDirective, SnyIndicatorDirective, SnyInputDirective, SnyKbdDirective, SnyLabelDirective, SnyLinkDirective, SnyListDirective, SnyListItemActionDirective, SnyListItemContentDirective, SnyListItemDirective, SnyListItemIconDirective, SnyLoaderComponent, SnyMenuContentDirective, SnyMenuItemDirective, SnyMenuLabelDirective, SnyMenuSeparatorDirective, SnyNavbarBrandDirective, SnyNavbarContentDirective, SnyNavbarDirective, SnyNavbarEndDirective, SnyPaginationComponent, SnyProgressComponent, SnyRadialProgressComponent, SnyRadioDirective, SnyRatingComponent, SnyRowExpandDefDirective, SnySelectComponent, SnySheetCloseDirective, SnySheetContentDirective, SnySheetDescriptionDirective, SnySheetHeaderDirective, SnySheetRef, SnySheetService, SnySheetTitleDirective, SnySkeletonDirective, SnySliderComponent, SnyStatDescriptionDirective, SnyStatDirective, SnyStatFigureDirective, SnyStatTitleDirective, SnyStatValueDirective, SnyStatusDirective, SnyStepDirective, SnyStepsDirective, SnySwitchComponent, SnyTableBodyDirective, SnyTableCaptionDirective, SnyTableCellDirective, SnyTableDirective, SnyTableFooterDirective, SnyTableHeadDirective, SnyTableHeaderDirective, SnyTableRowDirective, SnyTabsContentDirective, SnyTabsDirective, SnyTabsListDirective, SnyTabsTriggerDirective, SnyTextareaDirective, SnyTimelineDirective, SnyTimelineEndDirective, SnyTimelineItemDirective, SnyTimelineMiddleDirective, SnyTimelineStartDirective, SnyToastService, SnyToasterComponent, SnyToggleDirective, SnyTooltipDirective, SnyValidatorDirective, SnyValidatorHintDirective, ThemeService, alertVariants, avatarVariants, badgeVariants, buttonGroupVariants, buttonVariants, cardVariants, checkboxVariants, cn, comboboxTriggerVariants, dividerVariants, dropdownContentVariants, dropdownItemVariants, fieldsetVariants, fileInputVariants, inputVariants, kbdVariants, labelVariants, linkVariants, loaderVariants, paginationItemVariants, progressBarVariants, progressTrackVariants, provideSonnyUI, radioVariants, ratingVariants, selectTriggerVariants, skeletonVariants, sliderTrackVariants, statusVariants, switchTrackVariants, tableCellVariants, tableVariants, tabsListVariants, tabsTriggerVariants, textareaVariants, toastVariants, toggleVariants, tooltipVariants };
5376
6111
  //# sourceMappingURL=sonny-ui-core.mjs.map