@keepui/ui 0.4.0 → 0.5.0

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.
@@ -1,6 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, Injectable, input, output, computed, ChangeDetectionStrategy, Component, inject, signal, DestroyRef, viewChild, model, effect, makeEnvironmentProviders } from '@angular/core';
2
+ import { InjectionToken, Injectable, input, output, computed, ChangeDetectionStrategy, Component, inject, signal, DestroyRef, viewChild, model, effect, viewChildren, makeEnvironmentProviders } from '@angular/core';
3
3
  import { TranslocoPipe, TRANSLOCO_SCOPE, TranslocoService, provideTransloco } from '@jsverse/transloco';
4
+ import { NgTemplateOutlet } from '@angular/common';
4
5
  import { of } from 'rxjs';
5
6
 
6
7
  /**
@@ -1723,6 +1724,467 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
1723
1724
  }]
1724
1725
  }] });
1725
1726
 
1727
+ /**
1728
+ * Accessible pill-style tab group with icon support and two visual variants.
1729
+ *
1730
+ * Implements the WAI-ARIA `tablist` pattern: keyboard navigation with arrow keys,
1731
+ * `Home`, and `End`. Each tab carries `role="tab"` and `aria-selected`.
1732
+ *
1733
+ * Works identically on **web** and **Angular + Capacitor**.
1734
+ *
1735
+ * ```html
1736
+ * <!-- Basic usage -->
1737
+ * <keepui-tab-group
1738
+ * [tabs]="tabs"
1739
+ * [selectedTabId]="activeTab"
1740
+ * (tabChange)="activeTab = $event"
1741
+ * />
1742
+ *
1743
+ * <!-- Filled variant -->
1744
+ * <keepui-tab-group
1745
+ * variant="filled"
1746
+ * [tabs]="tabs"
1747
+ * [selectedTabId]="activeTab"
1748
+ * (tabChange)="activeTab = $event"
1749
+ * />
1750
+ * ```
1751
+ */
1752
+ class TabGroupComponent {
1753
+ constructor() {
1754
+ /** List of tabs to render. */
1755
+ this.tabs = input.required();
1756
+ /** ID of the currently selected tab. */
1757
+ this.selectedTabId = input.required();
1758
+ /** Visual style variant. @default 'default' */
1759
+ this.variant = input('default');
1760
+ /**
1761
+ * Accessible label for the tablist container.
1762
+ * Provide a meaningful description when multiple tab groups exist on the page.
1763
+ */
1764
+ this.ariaLabel = input('');
1765
+ /** Emits the `id` of the tab the user has selected. */
1766
+ this.tabChange = output();
1767
+ this.tabButtons = viewChildren('tabButton');
1768
+ this.containerClass = computed(() => this.variant() === 'filled'
1769
+ ? 'bg-ku-action-primary/10 border-ku-action-primary/20'
1770
+ : 'bg-ku-secondary border-ku-secondary-border');
1771
+ }
1772
+ buttonClass(tabId) {
1773
+ const isActive = this.selectedTabId() === tabId;
1774
+ if (this.variant() === 'filled') {
1775
+ return isActive
1776
+ ? 'bg-ku-action-primary text-white'
1777
+ : 'text-ku-gray-text hover:text-ku-primary-text hover:bg-ku-action-primary/10';
1778
+ }
1779
+ return isActive
1780
+ ? 'bg-ku-primary text-ku-primary-text shadow-sm border border-ku-primary-border'
1781
+ : 'text-ku-gray-text hover:text-ku-primary-text hover:bg-ku-secondary-hover';
1782
+ }
1783
+ iconClass(tabId) {
1784
+ const isActive = this.selectedTabId() === tabId;
1785
+ if (this.variant() === 'filled') {
1786
+ return isActive ? 'text-white' : 'text-ku-gray-text';
1787
+ }
1788
+ return isActive ? 'text-ku-action-primary' : 'text-ku-gray-text';
1789
+ }
1790
+ onTabClick(tab) {
1791
+ if (!tab.disabled && tab.id !== this.selectedTabId()) {
1792
+ this.tabChange.emit(tab.id);
1793
+ }
1794
+ }
1795
+ onKeydown(event) {
1796
+ const tabs = this.tabs().filter(t => !t.disabled);
1797
+ const activeIndex = tabs.findIndex(t => t.id === this.selectedTabId());
1798
+ let nextIndex = activeIndex;
1799
+ if (event.key === 'ArrowRight' || event.key === 'ArrowDown') {
1800
+ nextIndex = (activeIndex + 1) % tabs.length;
1801
+ }
1802
+ else if (event.key === 'ArrowLeft' || event.key === 'ArrowUp') {
1803
+ nextIndex = (activeIndex - 1 + tabs.length) % tabs.length;
1804
+ }
1805
+ else if (event.key === 'Home') {
1806
+ nextIndex = 0;
1807
+ }
1808
+ else if (event.key === 'End') {
1809
+ nextIndex = tabs.length - 1;
1810
+ }
1811
+ else {
1812
+ return;
1813
+ }
1814
+ event.preventDefault();
1815
+ const nextTab = tabs[nextIndex];
1816
+ this.tabChange.emit(nextTab.id);
1817
+ this.focusTab(nextTab.id);
1818
+ }
1819
+ focusTab(tabId) {
1820
+ const allTabs = this.tabs();
1821
+ const index = allTabs.findIndex(t => t.id === tabId);
1822
+ const buttons = this.tabButtons();
1823
+ buttons[index]?.nativeElement.focus();
1824
+ }
1825
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: TabGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1826
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.20", type: TabGroupComponent, isStandalone: true, selector: "keepui-tab-group", inputs: { tabs: { classPropertyName: "tabs", publicName: "tabs", isSignal: true, isRequired: true, transformFunction: null }, selectedTabId: { classPropertyName: "selectedTabId", publicName: "selectedTabId", isSignal: true, isRequired: true, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { tabChange: "tabChange" }, viewQueries: [{ propertyName: "tabButtons", predicate: ["tabButton"], descendants: true, isSignal: true }], ngImport: i0, template: `
1827
+ <div
1828
+ role="tablist"
1829
+ [attr.aria-label]="ariaLabel() || null"
1830
+ class="flex items-center p-1 rounded-full border transition-colors duration-200"
1831
+ [class]="containerClass()"
1832
+ (keydown)="onKeydown($event)"
1833
+ >
1834
+ @for (tab of tabs(); track tab.id; let i = $index) {
1835
+ <button
1836
+ #tabButton
1837
+ type="button"
1838
+ role="tab"
1839
+ [id]="'keepui-tab-' + tab.id"
1840
+ [attr.aria-selected]="selectedTabId() === tab.id"
1841
+ [attr.aria-disabled]="tab.disabled ? true : null"
1842
+ [disabled]="tab.disabled || false"
1843
+ [tabindex]="selectedTabId() === tab.id ? 0 : -1"
1844
+ class="flex-1 inline-flex items-center justify-center gap-1.5 px-3 py-1.5 rounded-full
1845
+ transition-colors duration-200 text-sm font-medium cursor-pointer
1846
+ min-h-[2.75rem]
1847
+ focus-visible:outline-none focus-visible:ring-2
1848
+ focus-visible:ring-ku-action-primary focus-visible:ring-offset-2
1849
+ disabled:cursor-not-allowed disabled:opacity-40"
1850
+ [class]="buttonClass(tab.id)"
1851
+ (click)="onTabClick(tab)"
1852
+ >
1853
+ @if (tab.icon) {
1854
+ <keepui-icon
1855
+ [name]="tab.icon"
1856
+ [size]="16"
1857
+ [class]="iconClass(tab.id)"
1858
+ aria-hidden="true"
1859
+ />
1860
+ }
1861
+ <span>{{ tab.label }}</span>
1862
+ </button>
1863
+ }
1864
+ </div>
1865
+ `, isInline: true, dependencies: [{ kind: "component", type: IconComponent, selector: "keepui-icon", inputs: ["name", "size", "viewBox", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1866
+ }
1867
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: TabGroupComponent, decorators: [{
1868
+ type: Component,
1869
+ args: [{
1870
+ selector: 'keepui-tab-group',
1871
+ standalone: true,
1872
+ changeDetection: ChangeDetectionStrategy.OnPush,
1873
+ imports: [IconComponent],
1874
+ template: `
1875
+ <div
1876
+ role="tablist"
1877
+ [attr.aria-label]="ariaLabel() || null"
1878
+ class="flex items-center p-1 rounded-full border transition-colors duration-200"
1879
+ [class]="containerClass()"
1880
+ (keydown)="onKeydown($event)"
1881
+ >
1882
+ @for (tab of tabs(); track tab.id; let i = $index) {
1883
+ <button
1884
+ #tabButton
1885
+ type="button"
1886
+ role="tab"
1887
+ [id]="'keepui-tab-' + tab.id"
1888
+ [attr.aria-selected]="selectedTabId() === tab.id"
1889
+ [attr.aria-disabled]="tab.disabled ? true : null"
1890
+ [disabled]="tab.disabled || false"
1891
+ [tabindex]="selectedTabId() === tab.id ? 0 : -1"
1892
+ class="flex-1 inline-flex items-center justify-center gap-1.5 px-3 py-1.5 rounded-full
1893
+ transition-colors duration-200 text-sm font-medium cursor-pointer
1894
+ min-h-[2.75rem]
1895
+ focus-visible:outline-none focus-visible:ring-2
1896
+ focus-visible:ring-ku-action-primary focus-visible:ring-offset-2
1897
+ disabled:cursor-not-allowed disabled:opacity-40"
1898
+ [class]="buttonClass(tab.id)"
1899
+ (click)="onTabClick(tab)"
1900
+ >
1901
+ @if (tab.icon) {
1902
+ <keepui-icon
1903
+ [name]="tab.icon"
1904
+ [size]="16"
1905
+ [class]="iconClass(tab.id)"
1906
+ aria-hidden="true"
1907
+ />
1908
+ }
1909
+ <span>{{ tab.label }}</span>
1910
+ </button>
1911
+ }
1912
+ </div>
1913
+ `,
1914
+ }]
1915
+ }] });
1916
+
1917
+ /**
1918
+ * Visual step-progress indicator with optional navigation.
1919
+ *
1920
+ * Renders a sequence of numbered step circles connected by a progress bar.
1921
+ * Completed steps show a check-mark; the active step is highlighted; future
1922
+ * steps are muted. Steps with an `icon` replace the number with the given SVG symbol.
1923
+ *
1924
+ * Accessibility: uses `role="list"` / `role="listitem"` with `aria-current="step"` on
1925
+ * the active item. When steps are interactive (i.e. `stepChange` is listened to),
1926
+ * completed and current steps render as `<button>` elements; future steps remain
1927
+ * inert `<span>` elements.
1928
+ *
1929
+ * Works identically on **web** and **Angular + Capacitor**.
1930
+ *
1931
+ * ```html
1932
+ * <!-- Read-only progress indicator -->
1933
+ * <keepui-stepper [steps]="steps" [activeIndex]="1" />
1934
+ *
1935
+ * <!-- Interactive stepper (go back to a previous step) -->
1936
+ * <keepui-stepper
1937
+ * [steps]="steps"
1938
+ * [activeIndex]="currentStep"
1939
+ * (stepChange)="currentStep = $event"
1940
+ * />
1941
+ *
1942
+ * <!-- Small variant -->
1943
+ * <keepui-stepper [steps]="steps" [activeIndex]="0" size="sm" />
1944
+ * ```
1945
+ */
1946
+ class StepperComponent {
1947
+ constructor() {
1948
+ /** Steps to render. */
1949
+ this.steps = input.required();
1950
+ /** Zero-based index of the currently active step. @default 0 */
1951
+ this.activeIndex = input(0);
1952
+ /** Visual size of the step circles and connector bars. @default 'md' */
1953
+ this.size = input('md');
1954
+ /** Layout direction. @default 'horizontal' */
1955
+ this.orientation = input('horizontal');
1956
+ /**
1957
+ * Accessible label for the `<nav>` element.
1958
+ * @default ''
1959
+ */
1960
+ this.ariaLabel = input('');
1961
+ /**
1962
+ * Emits the zero-based index of the step the user clicked.
1963
+ * Only completed steps and the active step are clickable.
1964
+ * When no subscriber is attached, the stepper is purely visual.
1965
+ */
1966
+ this.stepChange = output();
1967
+ this.iconSize = computed(() => (this.size() === 'sm' ? 12 : 16));
1968
+ this.wrapperClass = computed(() => 'w-full');
1969
+ this.listClass = computed(() => {
1970
+ const base = 'list-none m-0 p-0 flex';
1971
+ return this.orientation() === 'vertical'
1972
+ ? `${base} flex-col gap-0`
1973
+ : `${base} flex-row items-start`;
1974
+ });
1975
+ this.itemClass = computed(() => {
1976
+ const base = 'flex';
1977
+ return this.orientation() === 'vertical'
1978
+ ? `${base} flex-row items-center flex-1`
1979
+ : `${base} flex-col items-center flex-1`;
1980
+ });
1981
+ this.stepColumnClass = computed(() => {
1982
+ return this.orientation() === 'vertical'
1983
+ ? 'flex flex-row items-center gap-3'
1984
+ : 'flex flex-col items-center gap-1.5';
1985
+ });
1986
+ }
1987
+ isCompleted(index) {
1988
+ return index < this.activeIndex();
1989
+ }
1990
+ isActive(index) {
1991
+ return index === this.activeIndex();
1992
+ }
1993
+ isClickable(index, step) {
1994
+ return !step.disabled && (this.isCompleted(index) || this.isActive(index));
1995
+ }
1996
+ onStepClick(index, step) {
1997
+ if (!step.disabled) {
1998
+ this.stepChange.emit(index);
1999
+ }
2000
+ }
2001
+ bubbleClass(index) {
2002
+ const sizeClass = this.size() === 'sm'
2003
+ ? 'w-6 h-6 text-xs'
2004
+ : 'w-9 h-9 text-sm';
2005
+ const base = [
2006
+ 'inline-flex items-center justify-center rounded-full shrink-0',
2007
+ 'transition-colors duration-200',
2008
+ 'focus-visible:outline-none focus-visible:ring-2',
2009
+ 'focus-visible:ring-ku-action-primary focus-visible:ring-offset-2',
2010
+ sizeClass,
2011
+ ].join(' ');
2012
+ if (this.isCompleted(index)) {
2013
+ return `${base} bg-ku-action-primary text-white cursor-pointer`;
2014
+ }
2015
+ if (this.isActive(index)) {
2016
+ return `${base} bg-ku-action-primary text-white ring-2 ring-ku-action-primary ring-offset-2`;
2017
+ }
2018
+ return `${base} bg-ku-secondary border-2 border-ku-secondary-border text-ku-gray-text cursor-default`;
2019
+ }
2020
+ labelClass(index) {
2021
+ const base = 'text-xs font-medium text-center transition-colors duration-200';
2022
+ if (this.isActive(index)) {
2023
+ return `${base} text-ku-primary-text`;
2024
+ }
2025
+ if (this.isCompleted(index)) {
2026
+ return `${base} text-ku-action-primary`;
2027
+ }
2028
+ return `${base} text-ku-gray-text`;
2029
+ }
2030
+ connectorClass(index) {
2031
+ const filled = this.isCompleted(index) || this.isActive(index);
2032
+ if (this.orientation() === 'vertical') {
2033
+ const height = this.size() === 'sm' ? 'h-8' : 'h-10';
2034
+ return [
2035
+ `${height} w-0.5 mx-auto my-1 rounded-full transition-colors duration-300`,
2036
+ filled ? 'bg-ku-action-primary' : 'bg-ku-secondary-border',
2037
+ ].join(' ');
2038
+ }
2039
+ return [
2040
+ 'w-full h-0.5 mt-4 mb-1 rounded-full transition-colors duration-300',
2041
+ filled ? 'bg-ku-action-primary' : 'bg-ku-secondary-border',
2042
+ ].join(' ');
2043
+ }
2044
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: StepperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2045
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.20", type: StepperComponent, isStandalone: true, selector: "keepui-stepper", inputs: { steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: true, transformFunction: null }, activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { stepChange: "stepChange" }, ngImport: i0, template: `
2046
+ <nav
2047
+ [attr.aria-label]="ariaLabel() || null"
2048
+ [class]="wrapperClass()"
2049
+ >
2050
+ <ol
2051
+ role="list"
2052
+ [class]="listClass()"
2053
+ >
2054
+ @for (step of steps(); track step.id; let i = $index; let last = $last) {
2055
+ <li
2056
+ role="listitem"
2057
+ [class]="itemClass()"
2058
+ [attr.aria-current]="isActive(i) ? 'step' : null"
2059
+ >
2060
+ <div [class]="stepColumnClass()">
2061
+ @if (isClickable(i, step)) {
2062
+ <button
2063
+ type="button"
2064
+ [class]="bubbleClass(i)"
2065
+ [attr.aria-label]="step.label"
2066
+ [attr.aria-disabled]="step.disabled ? true : null"
2067
+ [disabled]="step.disabled || false"
2068
+ (click)="onStepClick(i, step)"
2069
+ >
2070
+ <ng-container *ngTemplateOutlet="bubbleContent; context: { i, step }" />
2071
+ </button>
2072
+ } @else {
2073
+ <span [class]="bubbleClass(i)" aria-hidden="true">
2074
+ <ng-container *ngTemplateOutlet="bubbleContent; context: { i, step }" />
2075
+ </span>
2076
+ }
2077
+
2078
+ <span [class]="labelClass(i)">{{ step.label }}</span>
2079
+ </div>
2080
+
2081
+ @if (!last) {
2082
+ <div [class]="connectorClass(i)"></div>
2083
+ }
2084
+ </li>
2085
+ }
2086
+ </ol>
2087
+ </nav>
2088
+
2089
+ <ng-template #bubbleContent let-i="i" let-step="step">
2090
+ @if (isCompleted(i)) {
2091
+ <svg
2092
+ width="14"
2093
+ height="14"
2094
+ viewBox="0 0 24 24"
2095
+ fill="none"
2096
+ stroke="currentColor"
2097
+ stroke-width="3"
2098
+ stroke-linecap="round"
2099
+ stroke-linejoin="round"
2100
+ aria-hidden="true"
2101
+ >
2102
+ <polyline points="20 6 9 17 4 12" />
2103
+ </svg>
2104
+ } @else if (step.icon) {
2105
+ <keepui-icon [name]="step.icon" [size]="iconSize()" aria-hidden="true" />
2106
+ } @else {
2107
+ <span class="font-semibold leading-none">{{ i + 1 }}</span>
2108
+ }
2109
+ </ng-template>
2110
+ `, isInline: true, dependencies: [{ kind: "component", type: IconComponent, selector: "keepui-icon", inputs: ["name", "size", "viewBox", "ariaLabel"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2111
+ }
2112
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: StepperComponent, decorators: [{
2113
+ type: Component,
2114
+ args: [{
2115
+ selector: 'keepui-stepper',
2116
+ standalone: true,
2117
+ changeDetection: ChangeDetectionStrategy.OnPush,
2118
+ imports: [IconComponent, NgTemplateOutlet],
2119
+ template: `
2120
+ <nav
2121
+ [attr.aria-label]="ariaLabel() || null"
2122
+ [class]="wrapperClass()"
2123
+ >
2124
+ <ol
2125
+ role="list"
2126
+ [class]="listClass()"
2127
+ >
2128
+ @for (step of steps(); track step.id; let i = $index; let last = $last) {
2129
+ <li
2130
+ role="listitem"
2131
+ [class]="itemClass()"
2132
+ [attr.aria-current]="isActive(i) ? 'step' : null"
2133
+ >
2134
+ <div [class]="stepColumnClass()">
2135
+ @if (isClickable(i, step)) {
2136
+ <button
2137
+ type="button"
2138
+ [class]="bubbleClass(i)"
2139
+ [attr.aria-label]="step.label"
2140
+ [attr.aria-disabled]="step.disabled ? true : null"
2141
+ [disabled]="step.disabled || false"
2142
+ (click)="onStepClick(i, step)"
2143
+ >
2144
+ <ng-container *ngTemplateOutlet="bubbleContent; context: { i, step }" />
2145
+ </button>
2146
+ } @else {
2147
+ <span [class]="bubbleClass(i)" aria-hidden="true">
2148
+ <ng-container *ngTemplateOutlet="bubbleContent; context: { i, step }" />
2149
+ </span>
2150
+ }
2151
+
2152
+ <span [class]="labelClass(i)">{{ step.label }}</span>
2153
+ </div>
2154
+
2155
+ @if (!last) {
2156
+ <div [class]="connectorClass(i)"></div>
2157
+ }
2158
+ </li>
2159
+ }
2160
+ </ol>
2161
+ </nav>
2162
+
2163
+ <ng-template #bubbleContent let-i="i" let-step="step">
2164
+ @if (isCompleted(i)) {
2165
+ <svg
2166
+ width="14"
2167
+ height="14"
2168
+ viewBox="0 0 24 24"
2169
+ fill="none"
2170
+ stroke="currentColor"
2171
+ stroke-width="3"
2172
+ stroke-linecap="round"
2173
+ stroke-linejoin="round"
2174
+ aria-hidden="true"
2175
+ >
2176
+ <polyline points="20 6 9 17 4 12" />
2177
+ </svg>
2178
+ } @else if (step.icon) {
2179
+ <keepui-icon [name]="step.icon" [size]="iconSize()" aria-hidden="true" />
2180
+ } @else {
2181
+ <span class="font-semibold leading-none">{{ i + 1 }}</span>
2182
+ }
2183
+ </ng-template>
2184
+ `,
2185
+ }]
2186
+ }] });
2187
+
1726
2188
  /**
1727
2189
  * Registers KeepUI core providers for a **web** Angular application.
1728
2190
  *
@@ -1950,5 +2412,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
1950
2412
  * Generated bundle index. Do not edit.
1951
2413
  */
1952
2414
 
1953
- export { ButtonComponent, CardComponent, FILE_PORT, IconActionButtonComponent, IconComponent, ImagePreviewComponent, KEEPUI_AVAILABLE_LANGUAGES, KEEPUI_TRANSLATIONS, KEEPUI_TRANSLATION_KEYS, KeepUiLanguageService, MockFileService, SignalDropdownComponent, SignalTextInputComponent, SignalTextareaComponent, WebFileService, provideKeepUi, provideKeepUiI18n };
2415
+ export { ButtonComponent, CardComponent, FILE_PORT, IconActionButtonComponent, IconComponent, ImagePreviewComponent, KEEPUI_AVAILABLE_LANGUAGES, KEEPUI_TRANSLATIONS, KEEPUI_TRANSLATION_KEYS, KeepUiLanguageService, MockFileService, SignalDropdownComponent, SignalTextInputComponent, SignalTextareaComponent, StepperComponent, TabGroupComponent, WebFileService, provideKeepUi, provideKeepUiI18n };
1954
2416
  //# sourceMappingURL=keepui-ui.mjs.map