@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.
- package/README.md +741 -276
- package/fesm2022/keepui-ui.mjs +464 -2
- package/fesm2022/keepui-ui.mjs.map +1 -1
- package/lib/components/stepper/stepper.component.d.ts +67 -0
- package/lib/components/stepper/stepper.component.d.ts.map +1 -0
- package/lib/components/stepper/stepper.types.d.ts +16 -0
- package/lib/components/stepper/stepper.types.d.ts.map +1 -0
- package/lib/components/tab-group/tab-group.component.d.ts +52 -0
- package/lib/components/tab-group/tab-group.component.d.ts.map +1 -0
- package/lib/components/tab-group/tab-group.types.d.ts +14 -0
- package/lib/components/tab-group/tab-group.types.d.ts.map +1 -0
- package/package.json +1 -1
- package/public-api.d.ts +4 -0
- package/public-api.d.ts.map +1 -1
- package/styles/prebuilt.css +1 -1
package/fesm2022/keepui-ui.mjs
CHANGED
|
@@ -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
|