@raintonic/formaui 0.2.0 → 0.2.1

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.
Files changed (99) hide show
  1. package/CHANGELOG.md +7 -7
  2. package/README.md +145 -145
  3. package/fesm2022/raintonic-formaui-cdk-drag-drop.mjs.map +1 -1
  4. package/fesm2022/raintonic-formaui-cdk-form-field.mjs.map +1 -1
  5. package/fesm2022/raintonic-formaui-cdk-overlay.mjs +0 -26
  6. package/fesm2022/raintonic-formaui-cdk-overlay.mjs.map +1 -1
  7. package/fesm2022/raintonic-formaui-cdk-virtual-scroll.mjs +2 -2
  8. package/fesm2022/raintonic-formaui-cdk-virtual-scroll.mjs.map +1 -1
  9. package/fesm2022/raintonic-formaui-components-accordion.mjs +2 -2
  10. package/fesm2022/raintonic-formaui-components-accordion.mjs.map +1 -1
  11. package/fesm2022/raintonic-formaui-components-alert.mjs.map +1 -1
  12. package/fesm2022/raintonic-formaui-components-autocomplete.mjs.map +1 -1
  13. package/fesm2022/raintonic-formaui-components-avatar.mjs.map +1 -1
  14. package/fesm2022/raintonic-formaui-components-badge.mjs +2 -2
  15. package/fesm2022/raintonic-formaui-components-badge.mjs.map +1 -1
  16. package/fesm2022/raintonic-formaui-components-big-menu.mjs +2 -2
  17. package/fesm2022/raintonic-formaui-components-big-menu.mjs.map +1 -1
  18. package/fesm2022/raintonic-formaui-components-breadcrumb.mjs +4 -4
  19. package/fesm2022/raintonic-formaui-components-breadcrumb.mjs.map +1 -1
  20. package/fesm2022/raintonic-formaui-components-button-group.mjs.map +1 -1
  21. package/fesm2022/raintonic-formaui-components-button.mjs.map +1 -1
  22. package/fesm2022/raintonic-formaui-components-card.mjs.map +1 -1
  23. package/fesm2022/raintonic-formaui-components-checkbox.mjs +2 -2
  24. package/fesm2022/raintonic-formaui-components-checkbox.mjs.map +1 -1
  25. package/fesm2022/raintonic-formaui-components-data-table.mjs.map +1 -1
  26. package/fesm2022/raintonic-formaui-components-date-picker.mjs +4 -4
  27. package/fesm2022/raintonic-formaui-components-date-picker.mjs.map +1 -1
  28. package/fesm2022/raintonic-formaui-components-divider.mjs +2 -2
  29. package/fesm2022/raintonic-formaui-components-divider.mjs.map +1 -1
  30. package/fesm2022/raintonic-formaui-components-drawer.mjs +2 -2
  31. package/fesm2022/raintonic-formaui-components-drawer.mjs.map +1 -1
  32. package/fesm2022/raintonic-formaui-components-dynamic-form.mjs.map +1 -1
  33. package/fesm2022/raintonic-formaui-components-empty-state.mjs +2 -2
  34. package/fesm2022/raintonic-formaui-components-empty-state.mjs.map +1 -1
  35. package/fesm2022/raintonic-formaui-components-file-upload.mjs +2 -2
  36. package/fesm2022/raintonic-formaui-components-file-upload.mjs.map +1 -1
  37. package/fesm2022/raintonic-formaui-components-form-field.mjs.map +1 -1
  38. package/fesm2022/raintonic-formaui-components-icon.mjs.map +1 -1
  39. package/fesm2022/raintonic-formaui-components-input.mjs.map +1 -1
  40. package/fesm2022/raintonic-formaui-components-list.mjs +4 -4
  41. package/fesm2022/raintonic-formaui-components-list.mjs.map +1 -1
  42. package/fesm2022/raintonic-formaui-components-menu.mjs.map +1 -1
  43. package/fesm2022/raintonic-formaui-components-number-input.mjs +2 -2
  44. package/fesm2022/raintonic-formaui-components-number-input.mjs.map +1 -1
  45. package/fesm2022/raintonic-formaui-components-paginator.mjs +2 -2
  46. package/fesm2022/raintonic-formaui-components-paginator.mjs.map +1 -1
  47. package/fesm2022/raintonic-formaui-components-password-input.mjs +2 -2
  48. package/fesm2022/raintonic-formaui-components-password-input.mjs.map +1 -1
  49. package/fesm2022/raintonic-formaui-components-popover.mjs +2 -2
  50. package/fesm2022/raintonic-formaui-components-popover.mjs.map +1 -1
  51. package/fesm2022/raintonic-formaui-components-progressbar.mjs.map +1 -1
  52. package/fesm2022/raintonic-formaui-components-radio.mjs +4 -4
  53. package/fesm2022/raintonic-formaui-components-radio.mjs.map +1 -1
  54. package/fesm2022/raintonic-formaui-components-select.mjs +24 -24
  55. package/fesm2022/raintonic-formaui-components-select.mjs.map +1 -1
  56. package/fesm2022/raintonic-formaui-components-side-panel.mjs +2 -2
  57. package/fesm2022/raintonic-formaui-components-side-panel.mjs.map +1 -1
  58. package/fesm2022/raintonic-formaui-components-sidebar.mjs +2 -2
  59. package/fesm2022/raintonic-formaui-components-sidebar.mjs.map +1 -1
  60. package/fesm2022/raintonic-formaui-components-skeleton.mjs +2 -2
  61. package/fesm2022/raintonic-formaui-components-skeleton.mjs.map +1 -1
  62. package/fesm2022/raintonic-formaui-components-slider.mjs +2 -2
  63. package/fesm2022/raintonic-formaui-components-slider.mjs.map +1 -1
  64. package/fesm2022/raintonic-formaui-components-spinner.mjs +2 -2
  65. package/fesm2022/raintonic-formaui-components-spinner.mjs.map +1 -1
  66. package/fesm2022/raintonic-formaui-components-stepper.mjs +2 -2
  67. package/fesm2022/raintonic-formaui-components-stepper.mjs.map +1 -1
  68. package/fesm2022/raintonic-formaui-components-tab.mjs +10 -10
  69. package/fesm2022/raintonic-formaui-components-tab.mjs.map +1 -1
  70. package/fesm2022/raintonic-formaui-components-tag.mjs +2 -2
  71. package/fesm2022/raintonic-formaui-components-tag.mjs.map +1 -1
  72. package/fesm2022/raintonic-formaui-components-time-picker.mjs +4 -4
  73. package/fesm2022/raintonic-formaui-components-time-picker.mjs.map +1 -1
  74. package/fesm2022/raintonic-formaui-components-toggle.mjs.map +1 -1
  75. package/fesm2022/raintonic-formaui-components-toolbar.mjs.map +1 -1
  76. package/fesm2022/raintonic-formaui-components-tooltip.mjs.map +1 -1
  77. package/fesm2022/raintonic-formaui-components-tree-select.mjs +2 -2
  78. package/fesm2022/raintonic-formaui-components-tree-select.mjs.map +1 -1
  79. package/fesm2022/raintonic-formaui-components-tree-table.mjs +2 -2
  80. package/fesm2022/raintonic-formaui-components-tree-table.mjs.map +1 -1
  81. package/fesm2022/raintonic-formaui-components-tree.mjs +4 -4
  82. package/fesm2022/raintonic-formaui-components-tree.mjs.map +1 -1
  83. package/fesm2022/raintonic-formaui-core.mjs.map +1 -1
  84. package/fesm2022/raintonic-formaui-services-dialog.mjs +36 -36
  85. package/fesm2022/raintonic-formaui-services-dialog.mjs.map +1 -1
  86. package/fesm2022/raintonic-formaui-services-notification.mjs +2 -2
  87. package/fesm2022/raintonic-formaui-services-notification.mjs.map +1 -1
  88. package/fesm2022/raintonic-formaui-services-theme.mjs.map +1 -1
  89. package/fesm2022/raintonic-formaui-test-utils.mjs.map +1 -1
  90. package/fesm2022/raintonic-formaui.mjs.map +1 -1
  91. package/llms-full.txt +3 -97
  92. package/llms.txt +3 -3
  93. package/package.json +1 -1
  94. package/styles/index.scss +3 -3
  95. package/styles/partials/components/_button.scss +367 -0
  96. package/styles/partials/components/_dialog.scss +180 -0
  97. package/styles/partials/components/_overlay.scss +87 -0
  98. package/types/raintonic-formaui-cdk-overlay.d.ts +0 -1
  99. package/types/raintonic-formaui-cdk-overlay.d.ts.map +1 -1
@@ -135,7 +135,7 @@ class FuiVirtualScrollViewportComponent {
135
135
  });
136
136
  }
137
137
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiVirtualScrollViewportComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
138
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.6", type: FuiVirtualScrollViewportComponent, isStandalone: true, selector: "fui-virtual-scroll-viewport", inputs: { itemSize: { classPropertyName: "itemSize", publicName: "itemSize", isSignal: true, isRequired: true, transformFunction: null }, minBufferPx: { classPropertyName: "minBufferPx", publicName: "minBufferPx", isSignal: true, isRequired: false, transformFunction: null }, maxBufferPx: { classPropertyName: "maxBufferPx", publicName: "maxBufferPx", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { scrolledIndexChange: "scrolledIndexChange", renderedRangeChange: "renderedRangeChange" }, host: { attributes: { "role": "list" }, listeners: { "scroll": "_onScroll()" }, properties: { "class.fui-virtual-scroll-viewport--horizontal": "orientation() === \"horizontal\"" }, classAttribute: "fui-virtual-scroll-viewport" }, viewQueries: [{ propertyName: "_contentWrapper", first: true, predicate: ["contentWrapper"], descendants: true, static: true }], ngImport: i0, template: "<!-- Spacer that creates the full scrollbar height -->\n<div\n class=\"fui-virtual-scroll-viewport__spacer\"\n [style.height.px]=\"orientation() === 'vertical' ? _totalContentSize() : null\"\n [style.width.px]=\"orientation() === 'horizontal' ? _totalContentSize() : null\"\n></div>\n\n<!-- Content wrapper - positioned via transform to show correct items -->\n<div class=\"fui-virtual-scroll-viewport__content\" #contentWrapper>\n <ng-content></ng-content>\n</div>\n", styles: [".fui-virtual-scroll-viewport{display:block;position:relative;overflow:auto;contain:strict}.fui-virtual-scroll-viewport__spacer{position:absolute;top:0;left:0;width:1px}.fui-virtual-scroll-viewport__content{position:absolute;top:0;left:0;width:100%;will-change:transform;contain:content}.fui-virtual-scroll-viewport--horizontal .fui-virtual-scroll-viewport__spacer{height:1px;width:auto}.fui-virtual-scroll-viewport--horizontal .fui-virtual-scroll-viewport__content{display:flex;flex-direction:row;height:100%;width:auto}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
138
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.6", type: FuiVirtualScrollViewportComponent, isStandalone: true, selector: "fui-virtual-scroll-viewport", inputs: { itemSize: { classPropertyName: "itemSize", publicName: "itemSize", isSignal: true, isRequired: true, transformFunction: null }, minBufferPx: { classPropertyName: "minBufferPx", publicName: "minBufferPx", isSignal: true, isRequired: false, transformFunction: null }, maxBufferPx: { classPropertyName: "maxBufferPx", publicName: "maxBufferPx", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { scrolledIndexChange: "scrolledIndexChange", renderedRangeChange: "renderedRangeChange" }, host: { attributes: { "role": "list" }, listeners: { "scroll": "_onScroll()" }, properties: { "class.fui-virtual-scroll-viewport--horizontal": "orientation() === \"horizontal\"" }, classAttribute: "fui-virtual-scroll-viewport" }, viewQueries: [{ propertyName: "_contentWrapper", first: true, predicate: ["contentWrapper"], descendants: true, static: true }], ngImport: i0, template: "<!-- Spacer that creates the full scrollbar height -->\r\n<div\r\n class=\"fui-virtual-scroll-viewport__spacer\"\r\n [style.height.px]=\"orientation() === 'vertical' ? _totalContentSize() : null\"\r\n [style.width.px]=\"orientation() === 'horizontal' ? _totalContentSize() : null\"\r\n></div>\r\n\r\n<!-- Content wrapper - positioned via transform to show correct items -->\r\n<div class=\"fui-virtual-scroll-viewport__content\" #contentWrapper>\r\n <ng-content></ng-content>\r\n</div>\r\n", styles: [".fui-virtual-scroll-viewport{display:block;position:relative;overflow:auto;contain:strict}.fui-virtual-scroll-viewport__spacer{position:absolute;top:0;left:0;width:1px}.fui-virtual-scroll-viewport__content{position:absolute;top:0;left:0;width:100%;will-change:transform;contain:content}.fui-virtual-scroll-viewport--horizontal .fui-virtual-scroll-viewport__spacer{height:1px;width:auto}.fui-virtual-scroll-viewport--horizontal .fui-virtual-scroll-viewport__content{display:flex;flex-direction:row;height:100%;width:auto}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
139
139
  }
140
140
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiVirtualScrollViewportComponent, decorators: [{
141
141
  type: Component,
@@ -144,7 +144,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
144
144
  role: 'list',
145
145
  '[class.fui-virtual-scroll-viewport--horizontal]': 'orientation() === "horizontal"',
146
146
  '(scroll)': '_onScroll()',
147
- }, template: "<!-- Spacer that creates the full scrollbar height -->\n<div\n class=\"fui-virtual-scroll-viewport__spacer\"\n [style.height.px]=\"orientation() === 'vertical' ? _totalContentSize() : null\"\n [style.width.px]=\"orientation() === 'horizontal' ? _totalContentSize() : null\"\n></div>\n\n<!-- Content wrapper - positioned via transform to show correct items -->\n<div class=\"fui-virtual-scroll-viewport__content\" #contentWrapper>\n <ng-content></ng-content>\n</div>\n", styles: [".fui-virtual-scroll-viewport{display:block;position:relative;overflow:auto;contain:strict}.fui-virtual-scroll-viewport__spacer{position:absolute;top:0;left:0;width:1px}.fui-virtual-scroll-viewport__content{position:absolute;top:0;left:0;width:100%;will-change:transform;contain:content}.fui-virtual-scroll-viewport--horizontal .fui-virtual-scroll-viewport__spacer{height:1px;width:auto}.fui-virtual-scroll-viewport--horizontal .fui-virtual-scroll-viewport__content{display:flex;flex-direction:row;height:100%;width:auto}\n"] }]
147
+ }, template: "<!-- Spacer that creates the full scrollbar height -->\r\n<div\r\n class=\"fui-virtual-scroll-viewport__spacer\"\r\n [style.height.px]=\"orientation() === 'vertical' ? _totalContentSize() : null\"\r\n [style.width.px]=\"orientation() === 'horizontal' ? _totalContentSize() : null\"\r\n></div>\r\n\r\n<!-- Content wrapper - positioned via transform to show correct items -->\r\n<div class=\"fui-virtual-scroll-viewport__content\" #contentWrapper>\r\n <ng-content></ng-content>\r\n</div>\r\n", styles: [".fui-virtual-scroll-viewport{display:block;position:relative;overflow:auto;contain:strict}.fui-virtual-scroll-viewport__spacer{position:absolute;top:0;left:0;width:1px}.fui-virtual-scroll-viewport__content{position:absolute;top:0;left:0;width:100%;will-change:transform;contain:content}.fui-virtual-scroll-viewport--horizontal .fui-virtual-scroll-viewport__spacer{height:1px;width:auto}.fui-virtual-scroll-viewport--horizontal .fui-virtual-scroll-viewport__content{display:flex;flex-direction:row;height:100%;width:auto}\n"] }]
148
148
  }], propDecorators: { itemSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemSize", required: true }] }], minBufferPx: [{ type: i0.Input, args: [{ isSignal: true, alias: "minBufferPx", required: false }] }], maxBufferPx: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxBufferPx", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], scrolledIndexChange: [{ type: i0.Output, args: ["scrolledIndexChange"] }], renderedRangeChange: [{ type: i0.Output, args: ["renderedRangeChange"] }], _contentWrapper: [{
149
149
  type: ViewChild,
150
150
  args: ['contentWrapper', { static: true }]
@@ -1 +1 @@
1
- {"version":3,"file":"raintonic-formaui-cdk-virtual-scroll.mjs","sources":["../../../lib/cdk/virtual-scroll/virtual-scroll.utils.ts","../../../lib/cdk/virtual-scroll/fui-virtual-scroll-viewport.component.ts","../../../lib/cdk/virtual-scroll/fui-virtual-scroll-viewport.component.html","../../../lib/cdk/virtual-scroll/fui-virtual-for.directive.ts","../../../lib/cdk/virtual-scroll/raintonic-formaui-cdk-virtual-scroll.ts"],"sourcesContent":["import { FuiListRange } from './virtual-scroll.types';\n\n/**\n * Clamps a value between min and max bounds.\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, value));\n}\n\n/**\n * Checks if two FuiListRange objects are equal.\n */\nexport function rangesEqual(a: FuiListRange, b: FuiListRange): boolean {\n return a.start === b.start && a.end === b.end;\n}\n\n/**\n * Calculates the rendered range given scroll parameters.\n */\nexport function calculateRenderedRange(\n scrollOffset: number,\n viewportSize: number,\n itemSize: number,\n totalItems: number,\n minBufferPx: number,\n maxBufferPx: number,\n): FuiListRange {\n if (totalItems === 0 || itemSize === 0) {\n return { start: 0, end: 0 };\n }\n\n const firstVisibleIndex = Math.floor(scrollOffset / itemSize);\n const lastVisibleIndex = Math.ceil((scrollOffset + viewportSize) / itemSize);\n\n const bufferBefore = Math.ceil(minBufferPx / itemSize);\n const bufferAfter = Math.ceil(maxBufferPx / itemSize);\n\n const start = Math.max(0, firstVisibleIndex - bufferBefore);\n const end = Math.min(totalItems, lastVisibleIndex + bufferAfter);\n\n return { start, end };\n}\n","import {\n AfterViewInit,\n ChangeDetectionStrategy,\n Component,\n computed,\n ElementRef,\n inject,\n input,\n NgZone,\n OnDestroy,\n OnInit,\n output,\n signal,\n ViewChild,\n ViewEncapsulation,\n} from '@angular/core';\nimport { FuiListRange, FuiVirtualScrollOrientation } from './virtual-scroll.types';\nimport { calculateRenderedRange, rangesEqual } from './virtual-scroll.utils';\n\n@Component({\n selector: 'fui-virtual-scroll-viewport',\n standalone: true,\n templateUrl: './fui-virtual-scroll-viewport.component.html',\n styleUrls: ['./fui-virtual-scroll-viewport.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'fui-virtual-scroll-viewport',\n role: 'list',\n '[class.fui-virtual-scroll-viewport--horizontal]': 'orientation() === \"horizontal\"',\n '(scroll)': '_onScroll()',\n },\n})\nexport class FuiVirtualScrollViewportComponent implements OnInit, OnDestroy, AfterViewInit {\n /** Fixed size of each item in pixels */\n readonly itemSize = input.required<number>();\n\n /** Minimum buffer in pixels to render before the visible area */\n readonly minBufferPx = input(200);\n\n /** Maximum buffer in pixels to render after the visible area */\n readonly maxBufferPx = input(400);\n\n /** Scroll orientation */\n readonly orientation = input<FuiVirtualScrollOrientation>('vertical');\n\n /** Emits the first visible index on scroll */\n readonly scrolledIndexChange = output<number>();\n\n /** Emits the rendered range when it changes */\n readonly renderedRangeChange = output<FuiListRange>();\n\n /** Current rendered range (shared with fuiVirtualFor directive) */\n readonly _renderedRange = signal({ start: 0, end: 0 });\n\n /** Total number of items in the data source */\n readonly _totalItems = signal(0);\n\n /** Total content size in pixels */\n readonly _totalContentSize = computed(() => this._totalItems() * this.itemSize());\n\n @ViewChild('contentWrapper', { static: true }) _contentWrapper!: ElementRef<HTMLElement>;\n\n private readonly _elementRef = inject(ElementRef<HTMLElement>);\n private readonly _ngZone = inject(NgZone);\n\n private _rafId: number | null = null;\n private _lastScrollOffset = 0;\n\n ngOnInit(): void {\n this._ngZone.runOutsideAngular(() => {\n this._updateRenderedRange();\n });\n }\n\n ngAfterViewInit(): void {\n this._updateRenderedRange();\n }\n\n ngOnDestroy(): void {\n if (this._rafId !== null) {\n cancelAnimationFrame(this._rafId);\n this._rafId = null;\n }\n }\n\n /** Scroll event handler - throttled via requestAnimationFrame */\n _onScroll(): void {\n if (this._rafId !== null) {\n return;\n }\n this._rafId = requestAnimationFrame(() => {\n this._rafId = null;\n this._updateRenderedRange();\n });\n }\n\n /** Scrolls the viewport to bring the given index into view */\n scrollToIndex(index: number, behavior: ScrollBehavior = 'auto'): void {\n const offset = index * this.itemSize();\n this.scrollToOffset(offset, behavior);\n }\n\n /** Scrolls the viewport to a specific pixel offset */\n scrollToOffset(offset: number, behavior: ScrollBehavior = 'auto'): void {\n const el = this._elementRef.nativeElement;\n const isHorizontal = this.orientation() === 'horizontal';\n\n if (isHorizontal) {\n el.scrollTo({ left: offset, behavior });\n } else {\n el.scrollTo({ top: offset, behavior });\n }\n }\n\n /** Returns the current rendered range */\n getRenderedRange(): FuiListRange {\n return this._renderedRange();\n }\n\n /** Measures and returns the viewport size (height or width depending on orientation) */\n measureViewportSize(): number {\n const el = this._elementRef.nativeElement;\n return this.orientation() === 'horizontal' ? el.clientWidth : el.clientHeight;\n }\n\n /** Called by fuiVirtualFor to set the total item count */\n _setTotalItems(count: number): void {\n this._totalItems.set(count);\n this._updateRenderedRange();\n }\n\n /** Recalculates which items should be rendered based on current scroll position */\n private _updateRenderedRange(): void {\n const el = this._elementRef.nativeElement;\n const isHorizontal = this.orientation() === 'horizontal';\n\n const scrollOffset = isHorizontal ? el.scrollLeft : el.scrollTop;\n const viewportSize = isHorizontal ? el.clientWidth : el.clientHeight;\n\n this._lastScrollOffset = scrollOffset;\n\n const newRange = calculateRenderedRange(\n scrollOffset,\n viewportSize,\n this.itemSize(),\n this._totalItems(),\n this.minBufferPx(),\n this.maxBufferPx(),\n );\n\n const currentRange = this._renderedRange();\n\n if (!rangesEqual(currentRange, newRange)) {\n this._ngZone.run(() => {\n this._renderedRange.set(newRange);\n this.renderedRangeChange.emit(newRange);\n });\n }\n\n // Update content wrapper transform\n const contentOffset = newRange.start * this.itemSize();\n if (this._contentWrapper) {\n const transform = isHorizontal ? `translateX(${contentOffset}px)` : `translateY(${contentOffset}px)`;\n this._contentWrapper.nativeElement.style.transform = transform;\n }\n\n // Emit scrolled index (first visible, not buffered)\n const firstVisibleIndex = this.itemSize() > 0 ? Math.floor(scrollOffset / this.itemSize()) : 0;\n this._ngZone.run(() => {\n this.scrolledIndexChange.emit(firstVisibleIndex);\n });\n }\n}\n","<!-- Spacer that creates the full scrollbar height -->\n<div\n class=\"fui-virtual-scroll-viewport__spacer\"\n [style.height.px]=\"orientation() === 'vertical' ? _totalContentSize() : null\"\n [style.width.px]=\"orientation() === 'horizontal' ? _totalContentSize() : null\"\n></div>\n\n<!-- Content wrapper - positioned via transform to show correct items -->\n<div class=\"fui-virtual-scroll-viewport__content\" #contentWrapper>\n <ng-content></ng-content>\n</div>\n","import {\n Directive,\n DoCheck,\n effect,\n EmbeddedViewRef,\n inject,\n input,\n OnDestroy,\n TemplateRef,\n TrackByFunction,\n ViewContainerRef,\n} from '@angular/core';\nimport { FuiVirtualScrollViewportComponent } from './fui-virtual-scroll-viewport.component';\nimport { FuiVirtualForContext } from './virtual-scroll.types';\n\n/** Maximum number of detached views to keep in the recycling cache */\nconst MAX_VIEW_CACHE_SIZE = 20;\n\n@Directive({\n selector: '[fuiVirtualFor][fuiVirtualForOf]',\n standalone: true,\n})\nexport class FuiVirtualForDirective<T> implements OnDestroy, DoCheck {\n /** The data array to iterate over */\n readonly fuiVirtualForOf = input.required<T[]>();\n\n /** Optional trackBy function for identity tracking */\n readonly fuiVirtualForTrackBy = input<TrackByFunction<T>>();\n\n private readonly _viewport = inject(FuiVirtualScrollViewportComponent);\n private readonly _viewContainerRef = inject(ViewContainerRef);\n private readonly _templateRef = inject(TemplateRef<FuiVirtualForContext<T>>);\n\n /** Pool of detached views available for reuse */\n private _viewCache: EmbeddedViewRef<FuiVirtualForContext<T>>[] = [];\n\n /** Currently attached views in the container */\n private _renderedViews: EmbeddedViewRef<FuiVirtualForContext<T>>[] = [];\n\n /** Previous data reference for change detection */\n private _previousData: T[] | null = null;\n\n constructor() {\n // React to data changes\n effect(() => {\n const data = this.fuiVirtualForOf();\n this._viewport._setTotalItems(data ? data.length : 0);\n });\n\n // React to rendered range changes\n effect(() => {\n const range = this._viewport._renderedRange();\n this._renderRange(range.start, range.end);\n });\n }\n\n ngDoCheck(): void {\n // Check if data reference changed (for cases where array is replaced)\n const data = this.fuiVirtualForOf();\n if (data !== this._previousData) {\n this._previousData = data;\n this._viewport._setTotalItems(data ? data.length : 0);\n }\n }\n\n ngOnDestroy(): void {\n this._detachAllViews();\n this._destroyCache();\n }\n\n /**\n * Renders items within the given range [start, end).\n * Recycles views from the cache when possible.\n */\n private _renderRange(start: number, end: number): void {\n const data = this.fuiVirtualForOf();\n if (!data) {\n this._detachAllViews();\n return;\n }\n\n const count = data.length;\n\n // Detach all current views and push to cache\n this._detachAllViews();\n\n // Create or reuse views for the new range\n for (let i = start; i < end; i++) {\n const item = data[i];\n if (item === undefined) continue;\n\n const context: FuiVirtualForContext<T> = {\n $implicit: item,\n index: i,\n count,\n first: i === 0,\n last: i === count - 1,\n even: i % 2 === 0,\n odd: i % 2 !== 0,\n };\n\n let view: EmbeddedViewRef<FuiVirtualForContext<T>>;\n\n if (this._viewCache.length > 0) {\n // Reuse a cached view\n view = this._viewCache.pop()!;\n this._updateContext(view, context);\n this._viewContainerRef.insert(view);\n } else {\n // Create a new view\n view = this._viewContainerRef.createEmbeddedView(this._templateRef, context);\n }\n\n this._renderedViews.push(view);\n }\n\n // Trim excess cache\n while (this._viewCache.length > MAX_VIEW_CACHE_SIZE) {\n const view = this._viewCache.pop()!;\n view.destroy();\n }\n }\n\n /** Updates the context of an existing embedded view */\n private _updateContext(view: EmbeddedViewRef<FuiVirtualForContext<T>>, context: FuiVirtualForContext<T>): void {\n view.context.$implicit = context.$implicit;\n view.context.index = context.index;\n view.context.count = context.count;\n view.context.first = context.first;\n view.context.last = context.last;\n view.context.even = context.even;\n view.context.odd = context.odd;\n view.markForCheck();\n }\n\n /** Detaches all rendered views and moves them to the cache */\n private _detachAllViews(): void {\n for (let i = this._viewContainerRef.length - 1; i >= 0; i--) {\n const view = this._viewContainerRef.detach(i) as EmbeddedViewRef<FuiVirtualForContext<T>>;\n if (view) {\n this._viewCache.push(view);\n }\n }\n this._renderedViews = [];\n }\n\n /** Destroys all cached views */\n private _destroyCache(): void {\n for (const view of this._viewCache) {\n view.destroy();\n }\n this._viewCache = [];\n }\n\n /** Static method for Angular's type inference in templates */\n static ngTemplateContextGuard<T>(_dir: FuiVirtualForDirective<T>, _ctx: unknown): _ctx is FuiVirtualForContext<T> {\n return true;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"raintonic-formaui-cdk-virtual-scroll.mjs","sources":["../../../lib/cdk/virtual-scroll/virtual-scroll.utils.ts","../../../lib/cdk/virtual-scroll/fui-virtual-scroll-viewport.component.ts","../../../lib/cdk/virtual-scroll/fui-virtual-scroll-viewport.component.html","../../../lib/cdk/virtual-scroll/fui-virtual-for.directive.ts","../../../lib/cdk/virtual-scroll/raintonic-formaui-cdk-virtual-scroll.ts"],"sourcesContent":["import { FuiListRange } from './virtual-scroll.types';\r\n\r\n/**\r\n * Clamps a value between min and max bounds.\r\n */\r\nexport function clamp(value: number, min: number, max: number): number {\r\n return Math.max(min, Math.min(max, value));\r\n}\r\n\r\n/**\r\n * Checks if two FuiListRange objects are equal.\r\n */\r\nexport function rangesEqual(a: FuiListRange, b: FuiListRange): boolean {\r\n return a.start === b.start && a.end === b.end;\r\n}\r\n\r\n/**\r\n * Calculates the rendered range given scroll parameters.\r\n */\r\nexport function calculateRenderedRange(\r\n scrollOffset: number,\r\n viewportSize: number,\r\n itemSize: number,\r\n totalItems: number,\r\n minBufferPx: number,\r\n maxBufferPx: number,\r\n): FuiListRange {\r\n if (totalItems === 0 || itemSize === 0) {\r\n return { start: 0, end: 0 };\r\n }\r\n\r\n const firstVisibleIndex = Math.floor(scrollOffset / itemSize);\r\n const lastVisibleIndex = Math.ceil((scrollOffset + viewportSize) / itemSize);\r\n\r\n const bufferBefore = Math.ceil(minBufferPx / itemSize);\r\n const bufferAfter = Math.ceil(maxBufferPx / itemSize);\r\n\r\n const start = Math.max(0, firstVisibleIndex - bufferBefore);\r\n const end = Math.min(totalItems, lastVisibleIndex + bufferAfter);\r\n\r\n return { start, end };\r\n}\r\n","import {\r\n AfterViewInit,\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n ElementRef,\r\n inject,\r\n input,\r\n NgZone,\r\n OnDestroy,\r\n OnInit,\r\n output,\r\n signal,\r\n ViewChild,\r\n ViewEncapsulation,\r\n} from '@angular/core';\r\nimport { FuiListRange, FuiVirtualScrollOrientation } from './virtual-scroll.types';\r\nimport { calculateRenderedRange, rangesEqual } from './virtual-scroll.utils';\r\n\r\n@Component({\r\n selector: 'fui-virtual-scroll-viewport',\r\n standalone: true,\r\n templateUrl: './fui-virtual-scroll-viewport.component.html',\r\n styleUrls: ['./fui-virtual-scroll-viewport.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.None,\r\n host: {\r\n class: 'fui-virtual-scroll-viewport',\r\n role: 'list',\r\n '[class.fui-virtual-scroll-viewport--horizontal]': 'orientation() === \"horizontal\"',\r\n '(scroll)': '_onScroll()',\r\n },\r\n})\r\nexport class FuiVirtualScrollViewportComponent implements OnInit, OnDestroy, AfterViewInit {\r\n /** Fixed size of each item in pixels */\r\n readonly itemSize = input.required<number>();\r\n\r\n /** Minimum buffer in pixels to render before the visible area */\r\n readonly minBufferPx = input(200);\r\n\r\n /** Maximum buffer in pixels to render after the visible area */\r\n readonly maxBufferPx = input(400);\r\n\r\n /** Scroll orientation */\r\n readonly orientation = input<FuiVirtualScrollOrientation>('vertical');\r\n\r\n /** Emits the first visible index on scroll */\r\n readonly scrolledIndexChange = output<number>();\r\n\r\n /** Emits the rendered range when it changes */\r\n readonly renderedRangeChange = output<FuiListRange>();\r\n\r\n /** Current rendered range (shared with fuiVirtualFor directive) */\r\n readonly _renderedRange = signal({ start: 0, end: 0 });\r\n\r\n /** Total number of items in the data source */\r\n readonly _totalItems = signal(0);\r\n\r\n /** Total content size in pixels */\r\n readonly _totalContentSize = computed(() => this._totalItems() * this.itemSize());\r\n\r\n @ViewChild('contentWrapper', { static: true }) _contentWrapper!: ElementRef<HTMLElement>;\r\n\r\n private readonly _elementRef = inject(ElementRef<HTMLElement>);\r\n private readonly _ngZone = inject(NgZone);\r\n\r\n private _rafId: number | null = null;\r\n private _lastScrollOffset = 0;\r\n\r\n ngOnInit(): void {\r\n this._ngZone.runOutsideAngular(() => {\r\n this._updateRenderedRange();\r\n });\r\n }\r\n\r\n ngAfterViewInit(): void {\r\n this._updateRenderedRange();\r\n }\r\n\r\n ngOnDestroy(): void {\r\n if (this._rafId !== null) {\r\n cancelAnimationFrame(this._rafId);\r\n this._rafId = null;\r\n }\r\n }\r\n\r\n /** Scroll event handler - throttled via requestAnimationFrame */\r\n _onScroll(): void {\r\n if (this._rafId !== null) {\r\n return;\r\n }\r\n this._rafId = requestAnimationFrame(() => {\r\n this._rafId = null;\r\n this._updateRenderedRange();\r\n });\r\n }\r\n\r\n /** Scrolls the viewport to bring the given index into view */\r\n scrollToIndex(index: number, behavior: ScrollBehavior = 'auto'): void {\r\n const offset = index * this.itemSize();\r\n this.scrollToOffset(offset, behavior);\r\n }\r\n\r\n /** Scrolls the viewport to a specific pixel offset */\r\n scrollToOffset(offset: number, behavior: ScrollBehavior = 'auto'): void {\r\n const el = this._elementRef.nativeElement;\r\n const isHorizontal = this.orientation() === 'horizontal';\r\n\r\n if (isHorizontal) {\r\n el.scrollTo({ left: offset, behavior });\r\n } else {\r\n el.scrollTo({ top: offset, behavior });\r\n }\r\n }\r\n\r\n /** Returns the current rendered range */\r\n getRenderedRange(): FuiListRange {\r\n return this._renderedRange();\r\n }\r\n\r\n /** Measures and returns the viewport size (height or width depending on orientation) */\r\n measureViewportSize(): number {\r\n const el = this._elementRef.nativeElement;\r\n return this.orientation() === 'horizontal' ? el.clientWidth : el.clientHeight;\r\n }\r\n\r\n /** Called by fuiVirtualFor to set the total item count */\r\n _setTotalItems(count: number): void {\r\n this._totalItems.set(count);\r\n this._updateRenderedRange();\r\n }\r\n\r\n /** Recalculates which items should be rendered based on current scroll position */\r\n private _updateRenderedRange(): void {\r\n const el = this._elementRef.nativeElement;\r\n const isHorizontal = this.orientation() === 'horizontal';\r\n\r\n const scrollOffset = isHorizontal ? el.scrollLeft : el.scrollTop;\r\n const viewportSize = isHorizontal ? el.clientWidth : el.clientHeight;\r\n\r\n this._lastScrollOffset = scrollOffset;\r\n\r\n const newRange = calculateRenderedRange(\r\n scrollOffset,\r\n viewportSize,\r\n this.itemSize(),\r\n this._totalItems(),\r\n this.minBufferPx(),\r\n this.maxBufferPx(),\r\n );\r\n\r\n const currentRange = this._renderedRange();\r\n\r\n if (!rangesEqual(currentRange, newRange)) {\r\n this._ngZone.run(() => {\r\n this._renderedRange.set(newRange);\r\n this.renderedRangeChange.emit(newRange);\r\n });\r\n }\r\n\r\n // Update content wrapper transform\r\n const contentOffset = newRange.start * this.itemSize();\r\n if (this._contentWrapper) {\r\n const transform = isHorizontal ? `translateX(${contentOffset}px)` : `translateY(${contentOffset}px)`;\r\n this._contentWrapper.nativeElement.style.transform = transform;\r\n }\r\n\r\n // Emit scrolled index (first visible, not buffered)\r\n const firstVisibleIndex = this.itemSize() > 0 ? Math.floor(scrollOffset / this.itemSize()) : 0;\r\n this._ngZone.run(() => {\r\n this.scrolledIndexChange.emit(firstVisibleIndex);\r\n });\r\n }\r\n}\r\n","<!-- Spacer that creates the full scrollbar height -->\r\n<div\r\n class=\"fui-virtual-scroll-viewport__spacer\"\r\n [style.height.px]=\"orientation() === 'vertical' ? _totalContentSize() : null\"\r\n [style.width.px]=\"orientation() === 'horizontal' ? _totalContentSize() : null\"\r\n></div>\r\n\r\n<!-- Content wrapper - positioned via transform to show correct items -->\r\n<div class=\"fui-virtual-scroll-viewport__content\" #contentWrapper>\r\n <ng-content></ng-content>\r\n</div>\r\n","import {\r\n Directive,\r\n DoCheck,\r\n effect,\r\n EmbeddedViewRef,\r\n inject,\r\n input,\r\n OnDestroy,\r\n TemplateRef,\r\n TrackByFunction,\r\n ViewContainerRef,\r\n} from '@angular/core';\r\nimport { FuiVirtualScrollViewportComponent } from './fui-virtual-scroll-viewport.component';\r\nimport { FuiVirtualForContext } from './virtual-scroll.types';\r\n\r\n/** Maximum number of detached views to keep in the recycling cache */\r\nconst MAX_VIEW_CACHE_SIZE = 20;\r\n\r\n@Directive({\r\n selector: '[fuiVirtualFor][fuiVirtualForOf]',\r\n standalone: true,\r\n})\r\nexport class FuiVirtualForDirective<T> implements OnDestroy, DoCheck {\r\n /** The data array to iterate over */\r\n readonly fuiVirtualForOf = input.required<T[]>();\r\n\r\n /** Optional trackBy function for identity tracking */\r\n readonly fuiVirtualForTrackBy = input<TrackByFunction<T>>();\r\n\r\n private readonly _viewport = inject(FuiVirtualScrollViewportComponent);\r\n private readonly _viewContainerRef = inject(ViewContainerRef);\r\n private readonly _templateRef = inject(TemplateRef<FuiVirtualForContext<T>>);\r\n\r\n /** Pool of detached views available for reuse */\r\n private _viewCache: EmbeddedViewRef<FuiVirtualForContext<T>>[] = [];\r\n\r\n /** Currently attached views in the container */\r\n private _renderedViews: EmbeddedViewRef<FuiVirtualForContext<T>>[] = [];\r\n\r\n /** Previous data reference for change detection */\r\n private _previousData: T[] | null = null;\r\n\r\n constructor() {\r\n // React to data changes\r\n effect(() => {\r\n const data = this.fuiVirtualForOf();\r\n this._viewport._setTotalItems(data ? data.length : 0);\r\n });\r\n\r\n // React to rendered range changes\r\n effect(() => {\r\n const range = this._viewport._renderedRange();\r\n this._renderRange(range.start, range.end);\r\n });\r\n }\r\n\r\n ngDoCheck(): void {\r\n // Check if data reference changed (for cases where array is replaced)\r\n const data = this.fuiVirtualForOf();\r\n if (data !== this._previousData) {\r\n this._previousData = data;\r\n this._viewport._setTotalItems(data ? data.length : 0);\r\n }\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this._detachAllViews();\r\n this._destroyCache();\r\n }\r\n\r\n /**\r\n * Renders items within the given range [start, end).\r\n * Recycles views from the cache when possible.\r\n */\r\n private _renderRange(start: number, end: number): void {\r\n const data = this.fuiVirtualForOf();\r\n if (!data) {\r\n this._detachAllViews();\r\n return;\r\n }\r\n\r\n const count = data.length;\r\n\r\n // Detach all current views and push to cache\r\n this._detachAllViews();\r\n\r\n // Create or reuse views for the new range\r\n for (let i = start; i < end; i++) {\r\n const item = data[i];\r\n if (item === undefined) continue;\r\n\r\n const context: FuiVirtualForContext<T> = {\r\n $implicit: item,\r\n index: i,\r\n count,\r\n first: i === 0,\r\n last: i === count - 1,\r\n even: i % 2 === 0,\r\n odd: i % 2 !== 0,\r\n };\r\n\r\n let view: EmbeddedViewRef<FuiVirtualForContext<T>>;\r\n\r\n if (this._viewCache.length > 0) {\r\n // Reuse a cached view\r\n view = this._viewCache.pop()!;\r\n this._updateContext(view, context);\r\n this._viewContainerRef.insert(view);\r\n } else {\r\n // Create a new view\r\n view = this._viewContainerRef.createEmbeddedView(this._templateRef, context);\r\n }\r\n\r\n this._renderedViews.push(view);\r\n }\r\n\r\n // Trim excess cache\r\n while (this._viewCache.length > MAX_VIEW_CACHE_SIZE) {\r\n const view = this._viewCache.pop()!;\r\n view.destroy();\r\n }\r\n }\r\n\r\n /** Updates the context of an existing embedded view */\r\n private _updateContext(view: EmbeddedViewRef<FuiVirtualForContext<T>>, context: FuiVirtualForContext<T>): void {\r\n view.context.$implicit = context.$implicit;\r\n view.context.index = context.index;\r\n view.context.count = context.count;\r\n view.context.first = context.first;\r\n view.context.last = context.last;\r\n view.context.even = context.even;\r\n view.context.odd = context.odd;\r\n view.markForCheck();\r\n }\r\n\r\n /** Detaches all rendered views and moves them to the cache */\r\n private _detachAllViews(): void {\r\n for (let i = this._viewContainerRef.length - 1; i >= 0; i--) {\r\n const view = this._viewContainerRef.detach(i) as EmbeddedViewRef<FuiVirtualForContext<T>>;\r\n if (view) {\r\n this._viewCache.push(view);\r\n }\r\n }\r\n this._renderedViews = [];\r\n }\r\n\r\n /** Destroys all cached views */\r\n private _destroyCache(): void {\r\n for (const view of this._viewCache) {\r\n view.destroy();\r\n }\r\n this._viewCache = [];\r\n }\r\n\r\n /** Static method for Angular's type inference in templates */\r\n static ngTemplateContextGuard<T>(_dir: FuiVirtualForDirective<T>, _ctx: unknown): _ctx is FuiVirtualForContext<T> {\r\n return true;\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -117,7 +117,7 @@ class FuiExpansionPanelComponent {
117
117
  }
118
118
  }
119
119
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiExpansionPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
120
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: FuiExpansionPanelComponent, isStandalone: true, selector: "fui-expansion-panel", inputs: { expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, hideToggle: { classPropertyName: "hideToggle", publicName: "hideToggle", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { opened: "opened", closed: "closed", expandedChange: "expandedChange", afterExpand: "afterExpand", afterCollapse: "afterCollapse" }, host: { properties: { "class.fui-expansion-panel--expanded": "_expanded()", "class.fui-expansion-panel--disabled": "disabled()", "class.fui-expansion-panel--animating": "_animating()" }, classAttribute: "fui-expansion-panel" }, ngImport: i0, template: "<div\n class=\"fui-expansion-panel__header\"\n (click)=\"toggle()\"\n (keydown.enter)=\"toggle()\"\n (keydown.space)=\"toggle(); $event.preventDefault()\"\n role=\"button\"\n [attr.aria-expanded]=\"_expanded()\"\n [attr.aria-controls]=\"_contentId\"\n [attr.id]=\"_headerId\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n>\n <div class=\"fui-expansion-panel__header-content\">\n <ng-content select=\"[panelTitle]\"></ng-content>\n <ng-content select=\"[panelDescription]\"></ng-content>\n </div>\n @if (!hideToggle()) {\n <fui-icon\n class=\"fui-expansion-panel__toggle-icon\"\n [class.fui-expansion-panel__toggle-icon--expanded]=\"_expanded()\"\n name=\"caret-down\"\n size=\"sm\"\n ></fui-icon>\n }\n</div>\n\n<div\n class=\"fui-expansion-panel__body\"\n [attr.id]=\"_contentId\"\n [attr.aria-labelledby]=\"_headerId\"\n role=\"region\"\n [class.fui-expansion-panel__body--expanded]=\"_expanded()\"\n (transitionend)=\"_onBodyTransitionEnd($event)\"\n>\n <div class=\"fui-expansion-panel__body-inner\">\n @if (_expanded() || _hasBeenOpened()) {\n <ng-content></ng-content>\n }\n </div>\n</div>\n", styles: ["@keyframes fui-skeleton-pulse{0%{opacity:1}50%{opacity:.4}to{opacity:1}}@keyframes fui-spin{to{transform:rotate(360deg)}}@keyframes fui-shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-2px)}20%,40%,60%,80%{transform:translate(2px)}}.fui-motion-fade-in{transition:opacity var(--fui-duration-fast-02) var(--fui-ease-entrance) 0ms}.fui-motion-fade-out{transition:opacity var(--fui-duration-fast-01) var(--fui-ease-exit) 0ms}.fui-motion-slide-in-bottom{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-bottom.fui-motion-entering{transform:translateY(1rem)}.fui-motion-slide-in-top{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-top.fui-motion-entering{transform:translateY(-1rem)}.fui-motion-scale-in{transition:transform,opacity var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:scale(1);opacity:1}.fui-motion-scale-in.fui-motion-entering{transform:scale(.95);opacity:0}.fui-no-motion{transition:none!important;animation:none!important}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}@keyframes fui-pulse{0%{transform:scale(1);opacity:1}50%{transform:scale(1.05)}to{transform:scale(1);opacity:1}}@keyframes fui-slide-in{0%{transform:translate(120%)}to{transform:translate(0)}}.fui-slide-in{animation:fui-slide-in var(--fui-duration-moderate-01) var(--fui-ease-entrance)}.fui-expansion-panel{display:block;background-color:var(--fui-surface-card, var(--fui-surface-01));border-bottom:1px solid var(--fui-border-color)}.fui-expansion-panel:first-child{border-top-left-radius:var(--fui-border-radius-sm);border-top-right-radius:var(--fui-border-radius-sm)}.fui-expansion-panel:last-child{border-bottom:none;border-bottom-left-radius:var(--fui-border-radius-sm);border-bottom-right-radius:var(--fui-border-radius-sm)}.fui-expansion-panel__header{display:flex;align-items:center;justify-content:space-between;padding:var(--fui-padding-16, 1rem) var(--fui-padding-24, 1.5rem);cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-03);font-weight:var(--fui-font-weight-medium, 500);color:var(--fui-text-primary);background:transparent;border:none;outline:none;transition:background-color var(--fui-duration-fast-02) var(--fui-ease-standard) 0ms}.fui-expansion-panel__header:hover{background-color:var(--fui-surface-hover, rgba(0, 0, 0, .04))}.fui-expansion-panel__header:focus-visible{outline:2px solid var(--fui-primary);outline-offset:0px}.fui-expansion-panel__header-content{display:flex;flex-direction:column;flex:1;min-width:0;gap:var(--fui-gap-4, .25rem)}.fui-expansion-panel__header-content [panelTitle]{font-weight:var(--fui-font-weight-medium, 500);color:var(--fui-text-primary)}.fui-expansion-panel__header-content [panelDescription]{font-size:var(--fui-font-size-02);font-weight:var(--fui-font-weight-regular, 400);color:var(--fui-text-secondary)}.fui-expansion-panel__toggle-icon{flex-shrink:0;margin-left:var(--fui-gap-16, 1rem);color:var(--fui-text-secondary);transition:transform var(--fui-duration-fast-02) var(--fui-ease-standard) 0ms}.fui-expansion-panel__toggle-icon--expanded{transform:rotate(180deg)}.fui-expansion-panel__body{max-height:0;overflow:hidden;transition:max-height var(--fui-duration-moderate-02) var(--fui-ease-standard) 0ms}.fui-expansion-panel__body--expanded{max-height:1000px}.fui-expansion-panel__body-inner{padding:0 var(--fui-padding-24, 1.5rem) var(--fui-padding-16, 1rem);font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-02);color:var(--fui-text-primary)}.fui-expansion-panel--expanded .fui-expansion-panel__header{font-weight:var(--fui-font-weight-semibold, 600)}.fui-expansion-panel--disabled{opacity:var(--fui-opacity-disabled, .5)}.fui-expansion-panel--disabled .fui-expansion-panel__header{cursor:not-allowed;pointer-events:none}.fui-accordion--flat .fui-expansion-panel{border-bottom:none;background-color:transparent;border-radius:0}.fui-accordion--flat .fui-expansion-panel__header,.fui-accordion--flat .fui-expansion-panel__body-inner{padding-left:0;padding-right:0}@media(prefers-reduced-motion:reduce){.fui-expansion-panel__toggle-icon,.fui-expansion-panel__body,.fui-expansion-panel__header{transition:none}}\n"], dependencies: [{ kind: "component", type: FuiIconComponent, selector: "fui-icon", inputs: ["name", "size", "weight", "color", "ariaLabel", "spin", "pulse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
120
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: FuiExpansionPanelComponent, isStandalone: true, selector: "fui-expansion-panel", inputs: { expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, hideToggle: { classPropertyName: "hideToggle", publicName: "hideToggle", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { opened: "opened", closed: "closed", expandedChange: "expandedChange", afterExpand: "afterExpand", afterCollapse: "afterCollapse" }, host: { properties: { "class.fui-expansion-panel--expanded": "_expanded()", "class.fui-expansion-panel--disabled": "disabled()", "class.fui-expansion-panel--animating": "_animating()" }, classAttribute: "fui-expansion-panel" }, ngImport: i0, template: "<div\r\n class=\"fui-expansion-panel__header\"\r\n (click)=\"toggle()\"\r\n (keydown.enter)=\"toggle()\"\r\n (keydown.space)=\"toggle(); $event.preventDefault()\"\r\n role=\"button\"\r\n [attr.aria-expanded]=\"_expanded()\"\r\n [attr.aria-controls]=\"_contentId\"\r\n [attr.id]=\"_headerId\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n>\r\n <div class=\"fui-expansion-panel__header-content\">\r\n <ng-content select=\"[panelTitle]\"></ng-content>\r\n <ng-content select=\"[panelDescription]\"></ng-content>\r\n </div>\r\n @if (!hideToggle()) {\r\n <fui-icon\r\n class=\"fui-expansion-panel__toggle-icon\"\r\n [class.fui-expansion-panel__toggle-icon--expanded]=\"_expanded()\"\r\n name=\"caret-down\"\r\n size=\"sm\"\r\n ></fui-icon>\r\n }\r\n</div>\r\n\r\n<div\r\n class=\"fui-expansion-panel__body\"\r\n [attr.id]=\"_contentId\"\r\n [attr.aria-labelledby]=\"_headerId\"\r\n role=\"region\"\r\n [class.fui-expansion-panel__body--expanded]=\"_expanded()\"\r\n (transitionend)=\"_onBodyTransitionEnd($event)\"\r\n>\r\n <div class=\"fui-expansion-panel__body-inner\">\r\n @if (_expanded() || _hasBeenOpened()) {\r\n <ng-content></ng-content>\r\n }\r\n </div>\r\n</div>\r\n", styles: ["@keyframes fui-skeleton-pulse{0%{opacity:1}50%{opacity:.4}to{opacity:1}}@keyframes fui-spin{to{transform:rotate(360deg)}}@keyframes fui-shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-2px)}20%,40%,60%,80%{transform:translate(2px)}}.fui-motion-fade-in{transition:opacity var(--fui-duration-fast-02) var(--fui-ease-entrance) 0ms}.fui-motion-fade-out{transition:opacity var(--fui-duration-fast-01) var(--fui-ease-exit) 0ms}.fui-motion-slide-in-bottom{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-bottom.fui-motion-entering{transform:translateY(1rem)}.fui-motion-slide-in-top{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-top.fui-motion-entering{transform:translateY(-1rem)}.fui-motion-scale-in{transition:transform,opacity var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:scale(1);opacity:1}.fui-motion-scale-in.fui-motion-entering{transform:scale(.95);opacity:0}.fui-no-motion{transition:none!important;animation:none!important}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}@keyframes fui-pulse{0%{transform:scale(1);opacity:1}50%{transform:scale(1.05)}to{transform:scale(1);opacity:1}}@keyframes fui-slide-in{0%{transform:translate(120%)}to{transform:translate(0)}}.fui-slide-in{animation:fui-slide-in var(--fui-duration-moderate-01) var(--fui-ease-entrance)}.fui-expansion-panel{display:block;background-color:var(--fui-surface-card, var(--fui-surface-01));border-bottom:1px solid var(--fui-border-color)}.fui-expansion-panel:first-child{border-top-left-radius:var(--fui-border-radius-sm);border-top-right-radius:var(--fui-border-radius-sm)}.fui-expansion-panel:last-child{border-bottom:none;border-bottom-left-radius:var(--fui-border-radius-sm);border-bottom-right-radius:var(--fui-border-radius-sm)}.fui-expansion-panel__header{display:flex;align-items:center;justify-content:space-between;padding:var(--fui-padding-16, 1rem) var(--fui-padding-24, 1.5rem);cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-03);font-weight:var(--fui-font-weight-medium, 500);color:var(--fui-text-primary);background:transparent;border:none;outline:none;transition:background-color var(--fui-duration-fast-02) var(--fui-ease-standard) 0ms}.fui-expansion-panel__header:hover{background-color:var(--fui-surface-hover, rgba(0, 0, 0, .04))}.fui-expansion-panel__header:focus-visible{outline:2px solid var(--fui-primary);outline-offset:0px}.fui-expansion-panel__header-content{display:flex;flex-direction:column;flex:1;min-width:0;gap:var(--fui-gap-4, .25rem)}.fui-expansion-panel__header-content [panelTitle]{font-weight:var(--fui-font-weight-medium, 500);color:var(--fui-text-primary)}.fui-expansion-panel__header-content [panelDescription]{font-size:var(--fui-font-size-02);font-weight:var(--fui-font-weight-regular, 400);color:var(--fui-text-secondary)}.fui-expansion-panel__toggle-icon{flex-shrink:0;margin-left:var(--fui-gap-16, 1rem);color:var(--fui-text-secondary);transition:transform var(--fui-duration-fast-02) var(--fui-ease-standard) 0ms}.fui-expansion-panel__toggle-icon--expanded{transform:rotate(180deg)}.fui-expansion-panel__body{max-height:0;overflow:hidden;transition:max-height var(--fui-duration-moderate-02) var(--fui-ease-standard) 0ms}.fui-expansion-panel__body--expanded{max-height:1000px}.fui-expansion-panel__body-inner{padding:0 var(--fui-padding-24, 1.5rem) var(--fui-padding-16, 1rem);font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-02);color:var(--fui-text-primary)}.fui-expansion-panel--expanded .fui-expansion-panel__header{font-weight:var(--fui-font-weight-semibold, 600)}.fui-expansion-panel--disabled{opacity:var(--fui-opacity-disabled, .5)}.fui-expansion-panel--disabled .fui-expansion-panel__header{cursor:not-allowed;pointer-events:none}.fui-accordion--flat .fui-expansion-panel{border-bottom:none;background-color:transparent;border-radius:0}.fui-accordion--flat .fui-expansion-panel__header,.fui-accordion--flat .fui-expansion-panel__body-inner{padding-left:0;padding-right:0}@media(prefers-reduced-motion:reduce){.fui-expansion-panel__toggle-icon,.fui-expansion-panel__body,.fui-expansion-panel__header{transition:none}}\n"], dependencies: [{ kind: "component", type: FuiIconComponent, selector: "fui-icon", inputs: ["name", "size", "weight", "color", "ariaLabel", "spin", "pulse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
121
121
  }
122
122
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiExpansionPanelComponent, decorators: [{
123
123
  type: Component,
@@ -126,7 +126,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
126
126
  '[class.fui-expansion-panel--expanded]': '_expanded()',
127
127
  '[class.fui-expansion-panel--disabled]': 'disabled()',
128
128
  '[class.fui-expansion-panel--animating]': '_animating()',
129
- }, template: "<div\n class=\"fui-expansion-panel__header\"\n (click)=\"toggle()\"\n (keydown.enter)=\"toggle()\"\n (keydown.space)=\"toggle(); $event.preventDefault()\"\n role=\"button\"\n [attr.aria-expanded]=\"_expanded()\"\n [attr.aria-controls]=\"_contentId\"\n [attr.id]=\"_headerId\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n>\n <div class=\"fui-expansion-panel__header-content\">\n <ng-content select=\"[panelTitle]\"></ng-content>\n <ng-content select=\"[panelDescription]\"></ng-content>\n </div>\n @if (!hideToggle()) {\n <fui-icon\n class=\"fui-expansion-panel__toggle-icon\"\n [class.fui-expansion-panel__toggle-icon--expanded]=\"_expanded()\"\n name=\"caret-down\"\n size=\"sm\"\n ></fui-icon>\n }\n</div>\n\n<div\n class=\"fui-expansion-panel__body\"\n [attr.id]=\"_contentId\"\n [attr.aria-labelledby]=\"_headerId\"\n role=\"region\"\n [class.fui-expansion-panel__body--expanded]=\"_expanded()\"\n (transitionend)=\"_onBodyTransitionEnd($event)\"\n>\n <div class=\"fui-expansion-panel__body-inner\">\n @if (_expanded() || _hasBeenOpened()) {\n <ng-content></ng-content>\n }\n </div>\n</div>\n", styles: ["@keyframes fui-skeleton-pulse{0%{opacity:1}50%{opacity:.4}to{opacity:1}}@keyframes fui-spin{to{transform:rotate(360deg)}}@keyframes fui-shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-2px)}20%,40%,60%,80%{transform:translate(2px)}}.fui-motion-fade-in{transition:opacity var(--fui-duration-fast-02) var(--fui-ease-entrance) 0ms}.fui-motion-fade-out{transition:opacity var(--fui-duration-fast-01) var(--fui-ease-exit) 0ms}.fui-motion-slide-in-bottom{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-bottom.fui-motion-entering{transform:translateY(1rem)}.fui-motion-slide-in-top{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-top.fui-motion-entering{transform:translateY(-1rem)}.fui-motion-scale-in{transition:transform,opacity var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:scale(1);opacity:1}.fui-motion-scale-in.fui-motion-entering{transform:scale(.95);opacity:0}.fui-no-motion{transition:none!important;animation:none!important}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}@keyframes fui-pulse{0%{transform:scale(1);opacity:1}50%{transform:scale(1.05)}to{transform:scale(1);opacity:1}}@keyframes fui-slide-in{0%{transform:translate(120%)}to{transform:translate(0)}}.fui-slide-in{animation:fui-slide-in var(--fui-duration-moderate-01) var(--fui-ease-entrance)}.fui-expansion-panel{display:block;background-color:var(--fui-surface-card, var(--fui-surface-01));border-bottom:1px solid var(--fui-border-color)}.fui-expansion-panel:first-child{border-top-left-radius:var(--fui-border-radius-sm);border-top-right-radius:var(--fui-border-radius-sm)}.fui-expansion-panel:last-child{border-bottom:none;border-bottom-left-radius:var(--fui-border-radius-sm);border-bottom-right-radius:var(--fui-border-radius-sm)}.fui-expansion-panel__header{display:flex;align-items:center;justify-content:space-between;padding:var(--fui-padding-16, 1rem) var(--fui-padding-24, 1.5rem);cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-03);font-weight:var(--fui-font-weight-medium, 500);color:var(--fui-text-primary);background:transparent;border:none;outline:none;transition:background-color var(--fui-duration-fast-02) var(--fui-ease-standard) 0ms}.fui-expansion-panel__header:hover{background-color:var(--fui-surface-hover, rgba(0, 0, 0, .04))}.fui-expansion-panel__header:focus-visible{outline:2px solid var(--fui-primary);outline-offset:0px}.fui-expansion-panel__header-content{display:flex;flex-direction:column;flex:1;min-width:0;gap:var(--fui-gap-4, .25rem)}.fui-expansion-panel__header-content [panelTitle]{font-weight:var(--fui-font-weight-medium, 500);color:var(--fui-text-primary)}.fui-expansion-panel__header-content [panelDescription]{font-size:var(--fui-font-size-02);font-weight:var(--fui-font-weight-regular, 400);color:var(--fui-text-secondary)}.fui-expansion-panel__toggle-icon{flex-shrink:0;margin-left:var(--fui-gap-16, 1rem);color:var(--fui-text-secondary);transition:transform var(--fui-duration-fast-02) var(--fui-ease-standard) 0ms}.fui-expansion-panel__toggle-icon--expanded{transform:rotate(180deg)}.fui-expansion-panel__body{max-height:0;overflow:hidden;transition:max-height var(--fui-duration-moderate-02) var(--fui-ease-standard) 0ms}.fui-expansion-panel__body--expanded{max-height:1000px}.fui-expansion-panel__body-inner{padding:0 var(--fui-padding-24, 1.5rem) var(--fui-padding-16, 1rem);font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-02);color:var(--fui-text-primary)}.fui-expansion-panel--expanded .fui-expansion-panel__header{font-weight:var(--fui-font-weight-semibold, 600)}.fui-expansion-panel--disabled{opacity:var(--fui-opacity-disabled, .5)}.fui-expansion-panel--disabled .fui-expansion-panel__header{cursor:not-allowed;pointer-events:none}.fui-accordion--flat .fui-expansion-panel{border-bottom:none;background-color:transparent;border-radius:0}.fui-accordion--flat .fui-expansion-panel__header,.fui-accordion--flat .fui-expansion-panel__body-inner{padding-left:0;padding-right:0}@media(prefers-reduced-motion:reduce){.fui-expansion-panel__toggle-icon,.fui-expansion-panel__body,.fui-expansion-panel__header{transition:none}}\n"] }]
129
+ }, template: "<div\r\n class=\"fui-expansion-panel__header\"\r\n (click)=\"toggle()\"\r\n (keydown.enter)=\"toggle()\"\r\n (keydown.space)=\"toggle(); $event.preventDefault()\"\r\n role=\"button\"\r\n [attr.aria-expanded]=\"_expanded()\"\r\n [attr.aria-controls]=\"_contentId\"\r\n [attr.id]=\"_headerId\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n>\r\n <div class=\"fui-expansion-panel__header-content\">\r\n <ng-content select=\"[panelTitle]\"></ng-content>\r\n <ng-content select=\"[panelDescription]\"></ng-content>\r\n </div>\r\n @if (!hideToggle()) {\r\n <fui-icon\r\n class=\"fui-expansion-panel__toggle-icon\"\r\n [class.fui-expansion-panel__toggle-icon--expanded]=\"_expanded()\"\r\n name=\"caret-down\"\r\n size=\"sm\"\r\n ></fui-icon>\r\n }\r\n</div>\r\n\r\n<div\r\n class=\"fui-expansion-panel__body\"\r\n [attr.id]=\"_contentId\"\r\n [attr.aria-labelledby]=\"_headerId\"\r\n role=\"region\"\r\n [class.fui-expansion-panel__body--expanded]=\"_expanded()\"\r\n (transitionend)=\"_onBodyTransitionEnd($event)\"\r\n>\r\n <div class=\"fui-expansion-panel__body-inner\">\r\n @if (_expanded() || _hasBeenOpened()) {\r\n <ng-content></ng-content>\r\n }\r\n </div>\r\n</div>\r\n", styles: ["@keyframes fui-skeleton-pulse{0%{opacity:1}50%{opacity:.4}to{opacity:1}}@keyframes fui-spin{to{transform:rotate(360deg)}}@keyframes fui-shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-2px)}20%,40%,60%,80%{transform:translate(2px)}}.fui-motion-fade-in{transition:opacity var(--fui-duration-fast-02) var(--fui-ease-entrance) 0ms}.fui-motion-fade-out{transition:opacity var(--fui-duration-fast-01) var(--fui-ease-exit) 0ms}.fui-motion-slide-in-bottom{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-bottom.fui-motion-entering{transform:translateY(1rem)}.fui-motion-slide-in-top{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-top.fui-motion-entering{transform:translateY(-1rem)}.fui-motion-scale-in{transition:transform,opacity var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:scale(1);opacity:1}.fui-motion-scale-in.fui-motion-entering{transform:scale(.95);opacity:0}.fui-no-motion{transition:none!important;animation:none!important}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}@keyframes fui-pulse{0%{transform:scale(1);opacity:1}50%{transform:scale(1.05)}to{transform:scale(1);opacity:1}}@keyframes fui-slide-in{0%{transform:translate(120%)}to{transform:translate(0)}}.fui-slide-in{animation:fui-slide-in var(--fui-duration-moderate-01) var(--fui-ease-entrance)}.fui-expansion-panel{display:block;background-color:var(--fui-surface-card, var(--fui-surface-01));border-bottom:1px solid var(--fui-border-color)}.fui-expansion-panel:first-child{border-top-left-radius:var(--fui-border-radius-sm);border-top-right-radius:var(--fui-border-radius-sm)}.fui-expansion-panel:last-child{border-bottom:none;border-bottom-left-radius:var(--fui-border-radius-sm);border-bottom-right-radius:var(--fui-border-radius-sm)}.fui-expansion-panel__header{display:flex;align-items:center;justify-content:space-between;padding:var(--fui-padding-16, 1rem) var(--fui-padding-24, 1.5rem);cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-03);font-weight:var(--fui-font-weight-medium, 500);color:var(--fui-text-primary);background:transparent;border:none;outline:none;transition:background-color var(--fui-duration-fast-02) var(--fui-ease-standard) 0ms}.fui-expansion-panel__header:hover{background-color:var(--fui-surface-hover, rgba(0, 0, 0, .04))}.fui-expansion-panel__header:focus-visible{outline:2px solid var(--fui-primary);outline-offset:0px}.fui-expansion-panel__header-content{display:flex;flex-direction:column;flex:1;min-width:0;gap:var(--fui-gap-4, .25rem)}.fui-expansion-panel__header-content [panelTitle]{font-weight:var(--fui-font-weight-medium, 500);color:var(--fui-text-primary)}.fui-expansion-panel__header-content [panelDescription]{font-size:var(--fui-font-size-02);font-weight:var(--fui-font-weight-regular, 400);color:var(--fui-text-secondary)}.fui-expansion-panel__toggle-icon{flex-shrink:0;margin-left:var(--fui-gap-16, 1rem);color:var(--fui-text-secondary);transition:transform var(--fui-duration-fast-02) var(--fui-ease-standard) 0ms}.fui-expansion-panel__toggle-icon--expanded{transform:rotate(180deg)}.fui-expansion-panel__body{max-height:0;overflow:hidden;transition:max-height var(--fui-duration-moderate-02) var(--fui-ease-standard) 0ms}.fui-expansion-panel__body--expanded{max-height:1000px}.fui-expansion-panel__body-inner{padding:0 var(--fui-padding-24, 1.5rem) var(--fui-padding-16, 1rem);font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-02);color:var(--fui-text-primary)}.fui-expansion-panel--expanded .fui-expansion-panel__header{font-weight:var(--fui-font-weight-semibold, 600)}.fui-expansion-panel--disabled{opacity:var(--fui-opacity-disabled, .5)}.fui-expansion-panel--disabled .fui-expansion-panel__header{cursor:not-allowed;pointer-events:none}.fui-accordion--flat .fui-expansion-panel{border-bottom:none;background-color:transparent;border-radius:0}.fui-accordion--flat .fui-expansion-panel__header,.fui-accordion--flat .fui-expansion-panel__body-inner{padding-left:0;padding-right:0}@media(prefers-reduced-motion:reduce){.fui-expansion-panel__toggle-icon,.fui-expansion-panel__body,.fui-expansion-panel__header{transition:none}}\n"] }]
130
130
  }], ctorParameters: () => [], propDecorators: { expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], hideToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideToggle", required: false }] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], expandedChange: [{ type: i0.Output, args: ["expandedChange"] }], afterExpand: [{ type: i0.Output, args: ["afterExpand"] }], afterCollapse: [{ type: i0.Output, args: ["afterCollapse"] }] } });
131
131
 
132
132
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"raintonic-formaui-components-accordion.mjs","sources":["../../../lib/components/accordion/accordion.types.ts","../../../lib/components/accordion/expansion-panel.component.ts","../../../lib/components/accordion/expansion-panel.component.html","../../../lib/components/accordion/accordion.component.ts","../../../lib/components/accordion/raintonic-formaui-components-accordion.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\n\nexport type AccordionDisplayMode = 'default' | 'flat';\n\nexport interface AccordionExpandedChange {\n source: unknown;\n expanded: boolean;\n}\n\nexport const FUI_ACCORDION = new InjectionToken<unknown>('FUI_ACCORDION');\n","import {\n Component,\n ChangeDetectionStrategy,\n ViewEncapsulation,\n input,\n output,\n signal,\n effect,\n inject,\n booleanAttribute,\n WritableSignal,\n ElementRef,\n} from '@angular/core';\nimport { FuiIconComponent } from '@raintonic/formaui/components/icon';\nimport { FUI_ACCORDION, AccordionDisplayMode } from './accordion.types';\n\nlet nextPanelId = 0;\n\n/**\n * # ExpansionPanel Component\n *\n * A collapsible panel that can be used standalone or within an `fui-accordion`.\n * Supports lazy rendering of content (only rendered after first open).\n *\n * ## Usage\n *\n * ### Standalone\n * ```html\n * <fui-expansion-panel>\n * <span panelTitle>Panel Title</span>\n * <p>Panel content here</p>\n * </fui-expansion-panel>\n * ```\n *\n * ### Inside Accordion\n * ```html\n * <fui-accordion>\n * <fui-expansion-panel>\n * <span panelTitle>First</span>\n * Content 1\n * </fui-expansion-panel>\n * <fui-expansion-panel>\n * <span panelTitle>Second</span>\n * Content 2\n * </fui-expansion-panel>\n * </fui-accordion>\n * ```\n */\n@Component({\n selector: 'fui-expansion-panel',\n standalone: true,\n imports: [FuiIconComponent],\n templateUrl: './expansion-panel.component.html',\n styleUrls: ['./expansion-panel.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'fui-expansion-panel',\n '[class.fui-expansion-panel--expanded]': '_expanded()',\n '[class.fui-expansion-panel--disabled]': 'disabled()',\n '[class.fui-expansion-panel--animating]': '_animating()',\n },\n})\nexport class FuiExpansionPanelComponent {\n // Inputs\n readonly expanded = input<boolean, unknown>(false, { transform: booleanAttribute });\n readonly disabled = input<boolean, unknown>(false, { transform: booleanAttribute });\n readonly hideToggle = input<boolean, unknown>(false, { transform: booleanAttribute });\n\n // Outputs\n readonly opened = output();\n readonly closed = output();\n readonly expandedChange = output<boolean>();\n readonly afterExpand = output();\n readonly afterCollapse = output();\n\n // Internal state\n readonly _expanded: WritableSignal<boolean> = signal(false);\n readonly _animating: WritableSignal<boolean> = signal(false);\n readonly _hasBeenOpened: WritableSignal<boolean> = signal(false);\n\n // ARIA IDs\n private readonly _panelId = nextPanelId++;\n readonly _headerId = `fui-expansion-panel-header-${this._panelId}`;\n readonly _contentId = `fui-expansion-panel-content-${this._panelId}`;\n\n // Parent accordion (optional)\n private readonly _accordion = inject(FUI_ACCORDION, { optional: true }) as {\n multi: () => boolean;\n displayMode: () => AccordionDisplayMode;\n _closeOtherPanels: (panel: FuiExpansionPanelComponent) => void;\n } | null;\n\n private readonly _elementRef = inject(ElementRef);\n\n constructor() {\n // Sync expanded input to internal state\n effect(() => {\n const inputExpanded = this.expanded();\n this._expanded.set(inputExpanded);\n if (inputExpanded) {\n this._hasBeenOpened.set(true);\n }\n });\n }\n\n /** Toggles the expanded state of the panel. */\n toggle(): void {\n if (this.disabled()) {\n return;\n }\n if (this._expanded()) {\n this.close();\n } else {\n this.open();\n }\n }\n\n /** Opens the panel. */\n open(): void {\n if (this.disabled() || this._expanded()) {\n return;\n }\n\n this._hasBeenOpened.set(true);\n this._animating.set(true);\n this._expanded.set(true);\n this.expandedChange.emit(true);\n this.opened.emit();\n\n // Notify parent accordion to close other panels if in single mode\n if (this._accordion) {\n this._accordion._closeOtherPanels(this);\n }\n }\n\n /** Closes the panel. */\n close(): void {\n if (this.disabled() || !this._expanded()) {\n return;\n }\n\n this._animating.set(true);\n this._expanded.set(false);\n this.expandedChange.emit(false);\n this.closed.emit();\n }\n\n /** Called when the body transition ends. */\n _onBodyTransitionEnd(event: TransitionEvent): void {\n if (event.propertyName === 'max-height') {\n this._animating.set(false);\n if (this._expanded()) {\n this.afterExpand.emit();\n } else {\n this.afterCollapse.emit();\n }\n }\n }\n}\n","<div\n class=\"fui-expansion-panel__header\"\n (click)=\"toggle()\"\n (keydown.enter)=\"toggle()\"\n (keydown.space)=\"toggle(); $event.preventDefault()\"\n role=\"button\"\n [attr.aria-expanded]=\"_expanded()\"\n [attr.aria-controls]=\"_contentId\"\n [attr.id]=\"_headerId\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n>\n <div class=\"fui-expansion-panel__header-content\">\n <ng-content select=\"[panelTitle]\"></ng-content>\n <ng-content select=\"[panelDescription]\"></ng-content>\n </div>\n @if (!hideToggle()) {\n <fui-icon\n class=\"fui-expansion-panel__toggle-icon\"\n [class.fui-expansion-panel__toggle-icon--expanded]=\"_expanded()\"\n name=\"caret-down\"\n size=\"sm\"\n ></fui-icon>\n }\n</div>\n\n<div\n class=\"fui-expansion-panel__body\"\n [attr.id]=\"_contentId\"\n [attr.aria-labelledby]=\"_headerId\"\n role=\"region\"\n [class.fui-expansion-panel__body--expanded]=\"_expanded()\"\n (transitionend)=\"_onBodyTransitionEnd($event)\"\n>\n <div class=\"fui-expansion-panel__body-inner\">\n @if (_expanded() || _hasBeenOpened()) {\n <ng-content></ng-content>\n }\n </div>\n</div>\n","import {\n Component,\n ChangeDetectionStrategy,\n ViewEncapsulation,\n input,\n contentChildren,\n booleanAttribute,\n} from '@angular/core';\nimport { FuiExpansionPanelComponent } from './expansion-panel.component';\nimport { AccordionDisplayMode, FUI_ACCORDION } from './accordion.types';\n\n/**\n * # Accordion Component\n *\n * Groups multiple `fui-expansion-panel` components.\n * In single mode (default), only one panel can be expanded at a time.\n * In multi mode, multiple panels can be expanded simultaneously.\n *\n * ## Usage\n *\n * ### Single mode (default)\n * ```html\n * <fui-accordion>\n * <fui-expansion-panel>\n * <span panelTitle>Panel 1</span>\n * Content 1\n * </fui-expansion-panel>\n * <fui-expansion-panel>\n * <span panelTitle>Panel 2</span>\n * Content 2\n * </fui-expansion-panel>\n * </fui-accordion>\n * ```\n *\n * ### Multi mode\n * ```html\n * <fui-accordion [multi]=\"true\">\n * ...\n * </fui-accordion>\n * ```\n *\n * ### Flat display mode\n * ```html\n * <fui-accordion displayMode=\"flat\">\n * ...\n * </fui-accordion>\n * ```\n */\n@Component({\n selector: 'fui-accordion',\n standalone: true,\n template: '<ng-content></ng-content>',\n styleUrls: ['./accordion.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'fui-accordion',\n '[class.fui-accordion--flat]': 'displayMode() === \"flat\"',\n },\n providers: [{ provide: FUI_ACCORDION, useExisting: FuiAccordionComponent }],\n})\nexport class FuiAccordionComponent {\n // Inputs\n readonly multi = input<boolean, unknown>(false, { transform: booleanAttribute });\n readonly displayMode = input<AccordionDisplayMode>('default');\n\n // Content children\n readonly panels = contentChildren(FuiExpansionPanelComponent);\n\n /** Opens all panels. Only effective in multi mode. */\n openAll(): void {\n if (!this.multi()) {\n return;\n }\n this.panels().forEach((panel) => {\n panel.open();\n });\n }\n\n /** Closes all panels. */\n closeAll(): void {\n this.panels().forEach((panel) => {\n panel.close();\n });\n }\n\n /** Closes all panels except the specified one. Used internally by panels. */\n _closeOtherPanels(openedPanel: FuiExpansionPanelComponent): void {\n if (this.multi()) {\n return;\n }\n this.panels().forEach((panel) => {\n if (panel !== openedPanel) {\n panel.close();\n }\n });\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"raintonic-formaui-components-accordion.mjs","sources":["../../../lib/components/accordion/accordion.types.ts","../../../lib/components/accordion/expansion-panel.component.ts","../../../lib/components/accordion/expansion-panel.component.html","../../../lib/components/accordion/accordion.component.ts","../../../lib/components/accordion/raintonic-formaui-components-accordion.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\r\n\r\nexport type AccordionDisplayMode = 'default' | 'flat';\r\n\r\nexport interface AccordionExpandedChange {\r\n source: unknown;\r\n expanded: boolean;\r\n}\r\n\r\nexport const FUI_ACCORDION = new InjectionToken<unknown>('FUI_ACCORDION');\r\n","import {\r\n Component,\r\n ChangeDetectionStrategy,\r\n ViewEncapsulation,\r\n input,\r\n output,\r\n signal,\r\n effect,\r\n inject,\r\n booleanAttribute,\r\n WritableSignal,\r\n ElementRef,\r\n} from '@angular/core';\r\nimport { FuiIconComponent } from '@raintonic/formaui/components/icon';\r\nimport { FUI_ACCORDION, AccordionDisplayMode } from './accordion.types';\r\n\r\nlet nextPanelId = 0;\r\n\r\n/**\r\n * # ExpansionPanel Component\r\n *\r\n * A collapsible panel that can be used standalone or within an `fui-accordion`.\r\n * Supports lazy rendering of content (only rendered after first open).\r\n *\r\n * ## Usage\r\n *\r\n * ### Standalone\r\n * ```html\r\n * <fui-expansion-panel>\r\n * <span panelTitle>Panel Title</span>\r\n * <p>Panel content here</p>\r\n * </fui-expansion-panel>\r\n * ```\r\n *\r\n * ### Inside Accordion\r\n * ```html\r\n * <fui-accordion>\r\n * <fui-expansion-panel>\r\n * <span panelTitle>First</span>\r\n * Content 1\r\n * </fui-expansion-panel>\r\n * <fui-expansion-panel>\r\n * <span panelTitle>Second</span>\r\n * Content 2\r\n * </fui-expansion-panel>\r\n * </fui-accordion>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'fui-expansion-panel',\r\n standalone: true,\r\n imports: [FuiIconComponent],\r\n templateUrl: './expansion-panel.component.html',\r\n styleUrls: ['./expansion-panel.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.None,\r\n host: {\r\n class: 'fui-expansion-panel',\r\n '[class.fui-expansion-panel--expanded]': '_expanded()',\r\n '[class.fui-expansion-panel--disabled]': 'disabled()',\r\n '[class.fui-expansion-panel--animating]': '_animating()',\r\n },\r\n})\r\nexport class FuiExpansionPanelComponent {\r\n // Inputs\r\n readonly expanded = input<boolean, unknown>(false, { transform: booleanAttribute });\r\n readonly disabled = input<boolean, unknown>(false, { transform: booleanAttribute });\r\n readonly hideToggle = input<boolean, unknown>(false, { transform: booleanAttribute });\r\n\r\n // Outputs\r\n readonly opened = output();\r\n readonly closed = output();\r\n readonly expandedChange = output<boolean>();\r\n readonly afterExpand = output();\r\n readonly afterCollapse = output();\r\n\r\n // Internal state\r\n readonly _expanded: WritableSignal<boolean> = signal(false);\r\n readonly _animating: WritableSignal<boolean> = signal(false);\r\n readonly _hasBeenOpened: WritableSignal<boolean> = signal(false);\r\n\r\n // ARIA IDs\r\n private readonly _panelId = nextPanelId++;\r\n readonly _headerId = `fui-expansion-panel-header-${this._panelId}`;\r\n readonly _contentId = `fui-expansion-panel-content-${this._panelId}`;\r\n\r\n // Parent accordion (optional)\r\n private readonly _accordion = inject(FUI_ACCORDION, { optional: true }) as {\r\n multi: () => boolean;\r\n displayMode: () => AccordionDisplayMode;\r\n _closeOtherPanels: (panel: FuiExpansionPanelComponent) => void;\r\n } | null;\r\n\r\n private readonly _elementRef = inject(ElementRef);\r\n\r\n constructor() {\r\n // Sync expanded input to internal state\r\n effect(() => {\r\n const inputExpanded = this.expanded();\r\n this._expanded.set(inputExpanded);\r\n if (inputExpanded) {\r\n this._hasBeenOpened.set(true);\r\n }\r\n });\r\n }\r\n\r\n /** Toggles the expanded state of the panel. */\r\n toggle(): void {\r\n if (this.disabled()) {\r\n return;\r\n }\r\n if (this._expanded()) {\r\n this.close();\r\n } else {\r\n this.open();\r\n }\r\n }\r\n\r\n /** Opens the panel. */\r\n open(): void {\r\n if (this.disabled() || this._expanded()) {\r\n return;\r\n }\r\n\r\n this._hasBeenOpened.set(true);\r\n this._animating.set(true);\r\n this._expanded.set(true);\r\n this.expandedChange.emit(true);\r\n this.opened.emit();\r\n\r\n // Notify parent accordion to close other panels if in single mode\r\n if (this._accordion) {\r\n this._accordion._closeOtherPanels(this);\r\n }\r\n }\r\n\r\n /** Closes the panel. */\r\n close(): void {\r\n if (this.disabled() || !this._expanded()) {\r\n return;\r\n }\r\n\r\n this._animating.set(true);\r\n this._expanded.set(false);\r\n this.expandedChange.emit(false);\r\n this.closed.emit();\r\n }\r\n\r\n /** Called when the body transition ends. */\r\n _onBodyTransitionEnd(event: TransitionEvent): void {\r\n if (event.propertyName === 'max-height') {\r\n this._animating.set(false);\r\n if (this._expanded()) {\r\n this.afterExpand.emit();\r\n } else {\r\n this.afterCollapse.emit();\r\n }\r\n }\r\n }\r\n}\r\n","<div\r\n class=\"fui-expansion-panel__header\"\r\n (click)=\"toggle()\"\r\n (keydown.enter)=\"toggle()\"\r\n (keydown.space)=\"toggle(); $event.preventDefault()\"\r\n role=\"button\"\r\n [attr.aria-expanded]=\"_expanded()\"\r\n [attr.aria-controls]=\"_contentId\"\r\n [attr.id]=\"_headerId\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n>\r\n <div class=\"fui-expansion-panel__header-content\">\r\n <ng-content select=\"[panelTitle]\"></ng-content>\r\n <ng-content select=\"[panelDescription]\"></ng-content>\r\n </div>\r\n @if (!hideToggle()) {\r\n <fui-icon\r\n class=\"fui-expansion-panel__toggle-icon\"\r\n [class.fui-expansion-panel__toggle-icon--expanded]=\"_expanded()\"\r\n name=\"caret-down\"\r\n size=\"sm\"\r\n ></fui-icon>\r\n }\r\n</div>\r\n\r\n<div\r\n class=\"fui-expansion-panel__body\"\r\n [attr.id]=\"_contentId\"\r\n [attr.aria-labelledby]=\"_headerId\"\r\n role=\"region\"\r\n [class.fui-expansion-panel__body--expanded]=\"_expanded()\"\r\n (transitionend)=\"_onBodyTransitionEnd($event)\"\r\n>\r\n <div class=\"fui-expansion-panel__body-inner\">\r\n @if (_expanded() || _hasBeenOpened()) {\r\n <ng-content></ng-content>\r\n }\r\n </div>\r\n</div>\r\n","import {\r\n Component,\r\n ChangeDetectionStrategy,\r\n ViewEncapsulation,\r\n input,\r\n contentChildren,\r\n booleanAttribute,\r\n} from '@angular/core';\r\nimport { FuiExpansionPanelComponent } from './expansion-panel.component';\r\nimport { AccordionDisplayMode, FUI_ACCORDION } from './accordion.types';\r\n\r\n/**\r\n * # Accordion Component\r\n *\r\n * Groups multiple `fui-expansion-panel` components.\r\n * In single mode (default), only one panel can be expanded at a time.\r\n * In multi mode, multiple panels can be expanded simultaneously.\r\n *\r\n * ## Usage\r\n *\r\n * ### Single mode (default)\r\n * ```html\r\n * <fui-accordion>\r\n * <fui-expansion-panel>\r\n * <span panelTitle>Panel 1</span>\r\n * Content 1\r\n * </fui-expansion-panel>\r\n * <fui-expansion-panel>\r\n * <span panelTitle>Panel 2</span>\r\n * Content 2\r\n * </fui-expansion-panel>\r\n * </fui-accordion>\r\n * ```\r\n *\r\n * ### Multi mode\r\n * ```html\r\n * <fui-accordion [multi]=\"true\">\r\n * ...\r\n * </fui-accordion>\r\n * ```\r\n *\r\n * ### Flat display mode\r\n * ```html\r\n * <fui-accordion displayMode=\"flat\">\r\n * ...\r\n * </fui-accordion>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'fui-accordion',\r\n standalone: true,\r\n template: '<ng-content></ng-content>',\r\n styleUrls: ['./accordion.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.None,\r\n host: {\r\n class: 'fui-accordion',\r\n '[class.fui-accordion--flat]': 'displayMode() === \"flat\"',\r\n },\r\n providers: [{ provide: FUI_ACCORDION, useExisting: FuiAccordionComponent }],\r\n})\r\nexport class FuiAccordionComponent {\r\n // Inputs\r\n readonly multi = input<boolean, unknown>(false, { transform: booleanAttribute });\r\n readonly displayMode = input<AccordionDisplayMode>('default');\r\n\r\n // Content children\r\n readonly panels = contentChildren(FuiExpansionPanelComponent);\r\n\r\n /** Opens all panels. Only effective in multi mode. */\r\n openAll(): void {\r\n if (!this.multi()) {\r\n return;\r\n }\r\n this.panels().forEach((panel) => {\r\n panel.open();\r\n });\r\n }\r\n\r\n /** Closes all panels. */\r\n closeAll(): void {\r\n this.panels().forEach((panel) => {\r\n panel.close();\r\n });\r\n }\r\n\r\n /** Closes all panels except the specified one. Used internally by panels. */\r\n _closeOtherPanels(openedPanel: FuiExpansionPanelComponent): void {\r\n if (this.multi()) {\r\n return;\r\n }\r\n this.panels().forEach((panel) => {\r\n if (panel !== openedPanel) {\r\n panel.close();\r\n }\r\n });\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"raintonic-formaui-components-alert.mjs","sources":["../../../lib/components/alert/alert.types.ts","../../../lib/components/alert/alert.component.ts","../../../lib/components/alert/alert.component.html","../../../lib/components/alert/raintonic-formaui-components-alert.ts"],"sourcesContent":["export type FuiAlertVariant = 'primary' | 'success' | 'info' | 'warning' | 'error' | 'generic';\n\nexport const FUI_ALERT_VARIANTS: readonly FuiAlertVariant[] = [\n 'primary',\n 'success',\n 'info',\n 'warning',\n 'error',\n 'generic',\n] as const;\n\n/**\n * Configuration for notification display\n */\nexport interface FuiNotificationConfig {\n /**\n * Notification variant (determines color scheme and icon)\n */\n variant: FuiAlertVariant;\n\n /**\n * Title of the notification\n */\n title: string;\n\n /**\n * Description/message of the notification\n */\n description?: string;\n\n /**\n * Duration in milliseconds before auto-dismiss (default: 5000)\n * Set to 0 to disable auto-dismiss\n */\n duration?: number;\n\n /**\n * Whether to show the close button (default: true)\n */\n closeable?: boolean;\n\n /**\n * Custom icon name (overrides default variant icon)\n */\n icon?: string;\n}\n\n/**\n * Position for notification display\n */\nexport type FuiNotificationPosition =\n | 'top-left'\n | 'top-center'\n | 'top-right'\n | 'bottom-left'\n | 'bottom-center'\n | 'bottom-right';\n\nexport const FUI_NOTIFICATION_POSITIONS: readonly FuiNotificationPosition[] = [\n 'top-left',\n 'top-center',\n 'top-right',\n 'bottom-left',\n 'bottom-center',\n 'bottom-right',\n] as const;\n","import { ChangeDetectionStrategy, Component, computed, input, output, Signal } from '@angular/core';\nimport { FuiIconComponent } from '@raintonic/formaui/components/icon';\nimport { FuiAlertVariant, FUI_ALERT_VARIANTS } from './alert.types';\nimport { FuiProgressbarComponent } from '@raintonic/formaui/components/progressbar';\n\n/**\n * # FuiAlertComponent\n *\n * A flexible alert component for displaying informational messages, warnings, errors, and success notifications.\n * Can be used inline in pages or as part of the notification system.\n *\n * ## Features\n * - Multiple variants: primary, success, info, warning, error, generic\n * - Title and description support\n * - Optional close button\n * - Custom or default icons per variant\n * - Accessible with ARIA attributes\n *\n * ## Usage\n *\n * ### Basic Alert\n * ```html\n * <fui-alert\n * variant=\"success\"\n * title=\"Success!\"\n * description=\"Your changes have been saved.\"\n * ></fui-alert>\n * ```\n *\n * ### Closeable Alert\n * ```html\n * <fui-alert\n * variant=\"warning\"\n * title=\"Warning\"\n * description=\"Please review before continuing.\"\n * [closeable]=\"true\"\n * (closed)=\"onAlertClosed()\"\n * ></fui-alert>\n * ```\n *\n * ### Custom Icon\n * ```html\n * <fui-alert\n * variant=\"info\"\n * title=\"Custom Icon\"\n * icon=\"custom-icon-name\"\n * ></fui-alert>\n * ```\n */\n@Component({\n selector: 'fui-alert',\n standalone: true,\n imports: [FuiIconComponent, FuiProgressbarComponent],\n templateUrl: './alert.component.html',\n styleUrls: ['./alert.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'computedClasses()',\n '[attr.role]': 'computedRole()',\n '[attr.aria-live]': 'computedAriaLive()',\n '[attr.aria-atomic]': '\"true\"',\n },\n})\nexport class FuiAlertComponent {\n /**\n * Alert variant (determines color scheme and default icon)\n */\n readonly variant = input<FuiAlertVariant, FuiAlertVariant | string>('info', {\n transform: (v) => ((FUI_ALERT_VARIANTS as readonly string[]).includes(v) ? (v as FuiAlertVariant) : 'info'),\n });\n\n /**\n * Alert title (required)\n */\n readonly title = input.required<string>();\n\n /**\n * Progress (optional)\n * 0 = turned off\n * -1 = indeterminate\n */\n readonly progress = input(0);\n\n /**\n * Alert description (optional)\n */\n readonly description = input<string | null>(null);\n\n /**\n * Whether to show the close button\n */\n readonly closeable = input(false);\n\n /**\n * Custom icon name (overrides default variant icon)\n */\n readonly icon = input<string | null>(null);\n\n /**\n * Emits when the close button is clicked\n */\n readonly closed = output();\n\n /**\n * Computed CSS classes for the alert\n */\n readonly computedClasses: Signal<string> = computed(() => {\n const classes: string[] = ['fui-alert', `fui-alert--${this.variant()}`];\n\n return classes.join(' ');\n });\n\n /**\n * Computed ARIA role: \"alert\" for error/warning, \"status\" for info/success/primary/generic\n */\n readonly computedRole: Signal<string> = computed(() => {\n const v = this.variant();\n return v === 'error' || v === 'warning' ? 'alert' : 'status';\n });\n\n /**\n * Computed aria-live: \"assertive\" for errors, \"polite\" for everything else\n */\n readonly computedAriaLive: Signal<string> = computed(() => {\n return this.variant() === 'error' ? 'assertive' : 'polite';\n });\n\n /**\n * Computed icon name based on variant or custom icon\n */\n readonly computedIcon: Signal<string> = computed(() => {\n const icon = this.icon();\n if (icon) {\n return icon;\n }\n\n // Default icons for each variant\n const variantIcons: Record<FuiAlertVariant, string> = {\n primary: 'info',\n success: 'check-circle',\n info: 'info',\n warning: 'warning-diamond',\n error: 'smiley-sad',\n generic: 'seal-warning',\n };\n\n return variantIcons[this.variant()];\n });\n\n /**\n * Handle close button click\n */\n onClose(): void {\n this.closed.emit();\n }\n}\n","@if (progress() !== 0) {\r\n <fui-progressbar\r\n [mode]=\"progress() === -1 ? 'indeterminate' : 'determinate'\"\r\n [value]=\"progress() > 0 ? progress() : undefined\"\r\n [color]=\"\r\n variant() === 'success'\r\n ? 'success'\r\n : variant() === 'warning'\r\n ? 'warn'\r\n : variant() === 'error'\r\n ? 'warn'\r\n : 'primary'\r\n \"\r\n ></fui-progressbar>\r\n}\r\n\r\n<div class=\"fui-alert__container\">\r\n <fui-icon class=\"fui-alert__icon\" weight=\"fill\" [name]=\"computedIcon()\" size=\"md\" />\r\n\r\n <div class=\"fui-alert__content\">\r\n <div class=\"fui-alert__title fui-text-sm fui-font-medium\">{{ title() }}</div>\r\n @if (description()) {\r\n <div class=\"fui-alert__description fui-text-xs\">{{ description() }}</div>\r\n }\r\n </div>\r\n\r\n @if (closeable()) {\r\n <button type=\"button\" class=\"fui-alert__close\" (click)=\"onClose()\" aria-label=\"Close alert\">\r\n <fui-icon name=\"x\" size=\"sm\" />\r\n </button>\r\n }\r\n</div>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"raintonic-formaui-components-alert.mjs","sources":["../../../lib/components/alert/alert.types.ts","../../../lib/components/alert/alert.component.ts","../../../lib/components/alert/alert.component.html","../../../lib/components/alert/raintonic-formaui-components-alert.ts"],"sourcesContent":["export type FuiAlertVariant = 'primary' | 'success' | 'info' | 'warning' | 'error' | 'generic';\r\n\r\nexport const FUI_ALERT_VARIANTS: readonly FuiAlertVariant[] = [\r\n 'primary',\r\n 'success',\r\n 'info',\r\n 'warning',\r\n 'error',\r\n 'generic',\r\n] as const;\r\n\r\n/**\r\n * Configuration for notification display\r\n */\r\nexport interface FuiNotificationConfig {\r\n /**\r\n * Notification variant (determines color scheme and icon)\r\n */\r\n variant: FuiAlertVariant;\r\n\r\n /**\r\n * Title of the notification\r\n */\r\n title: string;\r\n\r\n /**\r\n * Description/message of the notification\r\n */\r\n description?: string;\r\n\r\n /**\r\n * Duration in milliseconds before auto-dismiss (default: 5000)\r\n * Set to 0 to disable auto-dismiss\r\n */\r\n duration?: number;\r\n\r\n /**\r\n * Whether to show the close button (default: true)\r\n */\r\n closeable?: boolean;\r\n\r\n /**\r\n * Custom icon name (overrides default variant icon)\r\n */\r\n icon?: string;\r\n}\r\n\r\n/**\r\n * Position for notification display\r\n */\r\nexport type FuiNotificationPosition =\r\n | 'top-left'\r\n | 'top-center'\r\n | 'top-right'\r\n | 'bottom-left'\r\n | 'bottom-center'\r\n | 'bottom-right';\r\n\r\nexport const FUI_NOTIFICATION_POSITIONS: readonly FuiNotificationPosition[] = [\r\n 'top-left',\r\n 'top-center',\r\n 'top-right',\r\n 'bottom-left',\r\n 'bottom-center',\r\n 'bottom-right',\r\n] as const;\r\n","import { ChangeDetectionStrategy, Component, computed, input, output, Signal } from '@angular/core';\r\nimport { FuiIconComponent } from '@raintonic/formaui/components/icon';\r\nimport { FuiAlertVariant, FUI_ALERT_VARIANTS } from './alert.types';\r\nimport { FuiProgressbarComponent } from '@raintonic/formaui/components/progressbar';\r\n\r\n/**\r\n * # FuiAlertComponent\r\n *\r\n * A flexible alert component for displaying informational messages, warnings, errors, and success notifications.\r\n * Can be used inline in pages or as part of the notification system.\r\n *\r\n * ## Features\r\n * - Multiple variants: primary, success, info, warning, error, generic\r\n * - Title and description support\r\n * - Optional close button\r\n * - Custom or default icons per variant\r\n * - Accessible with ARIA attributes\r\n *\r\n * ## Usage\r\n *\r\n * ### Basic Alert\r\n * ```html\r\n * <fui-alert\r\n * variant=\"success\"\r\n * title=\"Success!\"\r\n * description=\"Your changes have been saved.\"\r\n * ></fui-alert>\r\n * ```\r\n *\r\n * ### Closeable Alert\r\n * ```html\r\n * <fui-alert\r\n * variant=\"warning\"\r\n * title=\"Warning\"\r\n * description=\"Please review before continuing.\"\r\n * [closeable]=\"true\"\r\n * (closed)=\"onAlertClosed()\"\r\n * ></fui-alert>\r\n * ```\r\n *\r\n * ### Custom Icon\r\n * ```html\r\n * <fui-alert\r\n * variant=\"info\"\r\n * title=\"Custom Icon\"\r\n * icon=\"custom-icon-name\"\r\n * ></fui-alert>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'fui-alert',\r\n standalone: true,\r\n imports: [FuiIconComponent, FuiProgressbarComponent],\r\n templateUrl: './alert.component.html',\r\n styleUrls: ['./alert.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: {\r\n '[class]': 'computedClasses()',\r\n '[attr.role]': 'computedRole()',\r\n '[attr.aria-live]': 'computedAriaLive()',\r\n '[attr.aria-atomic]': '\"true\"',\r\n },\r\n})\r\nexport class FuiAlertComponent {\r\n /**\r\n * Alert variant (determines color scheme and default icon)\r\n */\r\n readonly variant = input<FuiAlertVariant, FuiAlertVariant | string>('info', {\r\n transform: (v) => ((FUI_ALERT_VARIANTS as readonly string[]).includes(v) ? (v as FuiAlertVariant) : 'info'),\r\n });\r\n\r\n /**\r\n * Alert title (required)\r\n */\r\n readonly title = input.required<string>();\r\n\r\n /**\r\n * Progress (optional)\r\n * 0 = turned off\r\n * -1 = indeterminate\r\n */\r\n readonly progress = input(0);\r\n\r\n /**\r\n * Alert description (optional)\r\n */\r\n readonly description = input<string | null>(null);\r\n\r\n /**\r\n * Whether to show the close button\r\n */\r\n readonly closeable = input(false);\r\n\r\n /**\r\n * Custom icon name (overrides default variant icon)\r\n */\r\n readonly icon = input<string | null>(null);\r\n\r\n /**\r\n * Emits when the close button is clicked\r\n */\r\n readonly closed = output();\r\n\r\n /**\r\n * Computed CSS classes for the alert\r\n */\r\n readonly computedClasses: Signal<string> = computed(() => {\r\n const classes: string[] = ['fui-alert', `fui-alert--${this.variant()}`];\r\n\r\n return classes.join(' ');\r\n });\r\n\r\n /**\r\n * Computed ARIA role: \"alert\" for error/warning, \"status\" for info/success/primary/generic\r\n */\r\n readonly computedRole: Signal<string> = computed(() => {\r\n const v = this.variant();\r\n return v === 'error' || v === 'warning' ? 'alert' : 'status';\r\n });\r\n\r\n /**\r\n * Computed aria-live: \"assertive\" for errors, \"polite\" for everything else\r\n */\r\n readonly computedAriaLive: Signal<string> = computed(() => {\r\n return this.variant() === 'error' ? 'assertive' : 'polite';\r\n });\r\n\r\n /**\r\n * Computed icon name based on variant or custom icon\r\n */\r\n readonly computedIcon: Signal<string> = computed(() => {\r\n const icon = this.icon();\r\n if (icon) {\r\n return icon;\r\n }\r\n\r\n // Default icons for each variant\r\n const variantIcons: Record<FuiAlertVariant, string> = {\r\n primary: 'info',\r\n success: 'check-circle',\r\n info: 'info',\r\n warning: 'warning-diamond',\r\n error: 'smiley-sad',\r\n generic: 'seal-warning',\r\n };\r\n\r\n return variantIcons[this.variant()];\r\n });\r\n\r\n /**\r\n * Handle close button click\r\n */\r\n onClose(): void {\r\n this.closed.emit();\r\n }\r\n}\r\n","@if (progress() !== 0) {\r\n <fui-progressbar\r\n [mode]=\"progress() === -1 ? 'indeterminate' : 'determinate'\"\r\n [value]=\"progress() > 0 ? progress() : undefined\"\r\n [color]=\"\r\n variant() === 'success'\r\n ? 'success'\r\n : variant() === 'warning'\r\n ? 'warn'\r\n : variant() === 'error'\r\n ? 'warn'\r\n : 'primary'\r\n \"\r\n ></fui-progressbar>\r\n}\r\n\r\n<div class=\"fui-alert__container\">\r\n <fui-icon class=\"fui-alert__icon\" weight=\"fill\" [name]=\"computedIcon()\" size=\"md\" />\r\n\r\n <div class=\"fui-alert__content\">\r\n <div class=\"fui-alert__title fui-text-sm fui-font-medium\">{{ title() }}</div>\r\n @if (description()) {\r\n <div class=\"fui-alert__description fui-text-xs\">{{ description() }}</div>\r\n }\r\n </div>\r\n\r\n @if (closeable()) {\r\n <button type=\"button\" class=\"fui-alert__close\" (click)=\"onClose()\" aria-label=\"Close alert\">\r\n <fui-icon name=\"x\" size=\"sm\" />\r\n </button>\r\n }\r\n</div>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}