angular-tailwind-components 1.1.3 → 1.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.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, Directive, signal, inject, NgZone, ElementRef, viewChild, computed, Component, ViewContainerRef, HostListener, Input, output, InjectionToken, model, forwardRef, effect, contentChildren, ApplicationRef, EnvironmentInjector, Injector, createComponent, Injectable, booleanAttribute } from '@angular/core';
|
|
2
|
+
import { input, Directive, signal, inject, NgZone, ElementRef, viewChild, computed, Component, ViewContainerRef, HostListener, Input, output, InjectionToken, model, forwardRef, viewChildren, effect, contentChildren, ApplicationRef, EnvironmentInjector, Injector, createComponent, Injectable, booleanAttribute } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/common';
|
|
4
4
|
import { DOCUMENT, NgClass, NgTemplateOutlet, formatDate, CommonModule } from '@angular/common';
|
|
5
5
|
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
@@ -1672,6 +1672,555 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
1672
1672
|
], template: "<div class=\"tailwind-input-wrapper flex flex-col gap-1.5\">\n @if (label()) {\n <label\n [attr.for]=\"id() ? id() + '-inner' : null\"\n class=\"text-sm font-medium text-surface-700\"\n [class.text-danger-600]=\"hasError()\">\n {{ label() }}\n </label>\n }\n\n <input\n [attr.id]=\"id() ? id() + '-inner' : null\"\n [type]=\"type()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"readonly()\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"(helperText() || errorText()) && id() ? id() + '-helper' : null\"\n [value]=\"value()\"\n [class]=\"inputClasses()\"\n (input)=\"onInputChange($event)\"\n (blur)=\"onBlur()\" />\n\n @if (helperText() && !hasError()) {\n <p [attr.id]=\"id() ? id() + '-helper' : null\" class=\"text-xs text-surface-500\">\n {{ helperText() }}\n </p>\n }\n @if (errorText() && hasError()) {\n <p [attr.id]=\"id() ? id() + '-helper' : null\" class=\"text-xs text-danger-600\">\n {{ errorText() }}\n </p>\n }\n</div>\n", styles: [":host{display:block}\n"] }]
|
|
1673
1673
|
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], helperText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helperText", required: false }] }], errorText: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorText", required: false }] }], hasError: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasError", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
|
|
1674
1674
|
|
|
1675
|
+
class TailwindTextarea extends TailwindComponent {
|
|
1676
|
+
/** Label text */
|
|
1677
|
+
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
1678
|
+
/** Placeholder text */
|
|
1679
|
+
placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
1680
|
+
/** Visible row count */
|
|
1681
|
+
rows = input(4, ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
|
|
1682
|
+
/** Optional maximum width in columns */
|
|
1683
|
+
cols = input(undefined, ...(ngDevMode ? [{ debugName: "cols" }] : /* istanbul ignore next */ []));
|
|
1684
|
+
/** Maximum character length (HTML maxlength) */
|
|
1685
|
+
maxlength = input(undefined, ...(ngDevMode ? [{ debugName: "maxlength" }] : /* istanbul ignore next */ []));
|
|
1686
|
+
/** Resize behavior */
|
|
1687
|
+
resize = input('vertical', ...(ngDevMode ? [{ debugName: "resize" }] : /* istanbul ignore next */ []));
|
|
1688
|
+
/** Size variant */
|
|
1689
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
1690
|
+
/** Whether the textarea is readonly */
|
|
1691
|
+
readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
|
|
1692
|
+
/** Helper text shown below field */
|
|
1693
|
+
helperText = input('', ...(ngDevMode ? [{ debugName: "helperText" }] : /* istanbul ignore next */ []));
|
|
1694
|
+
/** Error text shown when hasError is true */
|
|
1695
|
+
errorText = input('', ...(ngDevMode ? [{ debugName: "errorText" }] : /* istanbul ignore next */ []));
|
|
1696
|
+
/** Whether the textarea is in error state */
|
|
1697
|
+
hasError = input(false, ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
|
|
1698
|
+
/** Two-way bound value */
|
|
1699
|
+
value = model('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
1700
|
+
/** Internal disabled state */
|
|
1701
|
+
isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
1702
|
+
/** Computed textarea classes */
|
|
1703
|
+
textareaClasses = computed(() => {
|
|
1704
|
+
const base = [
|
|
1705
|
+
'block w-full bg-white',
|
|
1706
|
+
'border transition-colors duration-150',
|
|
1707
|
+
'placeholder:text-surface-400',
|
|
1708
|
+
'outline-none focus:outline focus:outline-2 focus:outline-offset-2',
|
|
1709
|
+
'disabled:bg-surface-50 disabled:text-surface-400 disabled:cursor-not-allowed'
|
|
1710
|
+
];
|
|
1711
|
+
const sizeMap = {
|
|
1712
|
+
xs: 'text-xs px-2 py-1 rounded-sm min-h-[4.5rem]',
|
|
1713
|
+
sm: 'text-sm px-2.5 py-1.5 rounded-md min-h-[5rem]',
|
|
1714
|
+
md: 'text-sm px-3 py-2 rounded-md min-h-[5.5rem]',
|
|
1715
|
+
lg: 'text-base px-3.5 py-2.5 rounded-lg min-h-[6.5rem]',
|
|
1716
|
+
xl: 'text-base px-4 py-3 rounded-lg min-h-[7.5rem]'
|
|
1717
|
+
};
|
|
1718
|
+
const resizeMap = {
|
|
1719
|
+
vertical: 'resize-y',
|
|
1720
|
+
none: 'resize-none',
|
|
1721
|
+
both: 'resize',
|
|
1722
|
+
horizontal: 'resize-x'
|
|
1723
|
+
};
|
|
1724
|
+
const stateClass = this.hasError()
|
|
1725
|
+
? 'border-danger-400 focus:outline-danger-500 text-danger-900'
|
|
1726
|
+
: 'border-surface-300 focus:outline-primary-500 text-surface-900';
|
|
1727
|
+
return [...base, sizeMap[this.size()], resizeMap[this.resize()], stateClass].join(' ');
|
|
1728
|
+
}, ...(ngDevMode ? [{ debugName: "textareaClasses" }] : /* istanbul ignore next */ []));
|
|
1729
|
+
onChange = () => { };
|
|
1730
|
+
onTouched = () => { };
|
|
1731
|
+
writeValue(value) {
|
|
1732
|
+
this.value.set(value ?? '');
|
|
1733
|
+
}
|
|
1734
|
+
registerOnChange(fn) {
|
|
1735
|
+
this.onChange = fn;
|
|
1736
|
+
}
|
|
1737
|
+
registerOnTouched(fn) {
|
|
1738
|
+
this.onTouched = fn;
|
|
1739
|
+
}
|
|
1740
|
+
setDisabledState(disabled) {
|
|
1741
|
+
this.isDisabled.set(disabled);
|
|
1742
|
+
}
|
|
1743
|
+
onInputChange(event) {
|
|
1744
|
+
const val = event.target.value;
|
|
1745
|
+
this.value.set(val);
|
|
1746
|
+
this.onChange(val);
|
|
1747
|
+
}
|
|
1748
|
+
onBlur() {
|
|
1749
|
+
this.onTouched();
|
|
1750
|
+
}
|
|
1751
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindTextarea, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1752
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindTextarea, isStandalone: true, selector: "tailwind-textarea", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, cols: { classPropertyName: "cols", publicName: "cols", isSignal: true, isRequired: false, transformFunction: null }, maxlength: { classPropertyName: "maxlength", publicName: "maxlength", isSignal: true, isRequired: false, transformFunction: null }, resize: { classPropertyName: "resize", publicName: "resize", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, helperText: { classPropertyName: "helperText", publicName: "helperText", isSignal: true, isRequired: false, transformFunction: null }, errorText: { classPropertyName: "errorText", publicName: "errorText", isSignal: true, isRequired: false, transformFunction: null }, hasError: { classPropertyName: "hasError", publicName: "hasError", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, providers: [
|
|
1753
|
+
{
|
|
1754
|
+
provide: NG_VALUE_ACCESSOR,
|
|
1755
|
+
useExisting: forwardRef(() => TailwindTextarea),
|
|
1756
|
+
multi: true
|
|
1757
|
+
}
|
|
1758
|
+
], usesInheritance: true, ngImport: i0, template: "<div class=\"tailwind-textarea-wrapper flex flex-col gap-1.5\">\r\n @if (label()) {\r\n <label\r\n [attr.for]=\"id() ? id() + '-inner' : null\"\r\n class=\"text-sm font-medium text-surface-700\"\r\n [class.text-danger-600]=\"hasError()\">\r\n {{ label() }}\r\n </label>\r\n }\r\n\r\n <textarea\r\n [attr.id]=\"id() ? id() + '-inner' : null\"\r\n [placeholder]=\"placeholder()\"\r\n [rows]=\"rows()\"\r\n [attr.cols]=\"cols() ?? null\"\r\n [attr.maxlength]=\"maxlength() ?? null\"\r\n [disabled]=\"isDisabled()\"\r\n [readonly]=\"readonly()\"\r\n [attr.aria-invalid]=\"hasError() || null\"\r\n [attr.aria-describedby]=\"(helperText() || errorText()) && id() ? id() + '-helper' : null\"\r\n [value]=\"value()\"\r\n [class]=\"textareaClasses()\"\r\n (input)=\"onInputChange($event)\"\r\n (blur)=\"onBlur()\"></textarea>\r\n\r\n @if (helperText() && !hasError()) {\r\n <p [attr.id]=\"id() ? id() + '-helper' : null\" class=\"text-xs text-surface-500\">\r\n {{ helperText() }}\r\n </p>\r\n }\r\n @if (errorText() && hasError()) {\r\n <p [attr.id]=\"id() ? id() + '-helper' : null\" class=\"text-xs text-danger-600\">\r\n {{ errorText() }}\r\n </p>\r\n }\r\n</div>\r\n", styles: [":host{display:block}\n"] });
|
|
1759
|
+
}
|
|
1760
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindTextarea, decorators: [{
|
|
1761
|
+
type: Component,
|
|
1762
|
+
args: [{ selector: 'tailwind-textarea', providers: [
|
|
1763
|
+
{
|
|
1764
|
+
provide: NG_VALUE_ACCESSOR,
|
|
1765
|
+
useExisting: forwardRef(() => TailwindTextarea),
|
|
1766
|
+
multi: true
|
|
1767
|
+
}
|
|
1768
|
+
], template: "<div class=\"tailwind-textarea-wrapper flex flex-col gap-1.5\">\r\n @if (label()) {\r\n <label\r\n [attr.for]=\"id() ? id() + '-inner' : null\"\r\n class=\"text-sm font-medium text-surface-700\"\r\n [class.text-danger-600]=\"hasError()\">\r\n {{ label() }}\r\n </label>\r\n }\r\n\r\n <textarea\r\n [attr.id]=\"id() ? id() + '-inner' : null\"\r\n [placeholder]=\"placeholder()\"\r\n [rows]=\"rows()\"\r\n [attr.cols]=\"cols() ?? null\"\r\n [attr.maxlength]=\"maxlength() ?? null\"\r\n [disabled]=\"isDisabled()\"\r\n [readonly]=\"readonly()\"\r\n [attr.aria-invalid]=\"hasError() || null\"\r\n [attr.aria-describedby]=\"(helperText() || errorText()) && id() ? id() + '-helper' : null\"\r\n [value]=\"value()\"\r\n [class]=\"textareaClasses()\"\r\n (input)=\"onInputChange($event)\"\r\n (blur)=\"onBlur()\"></textarea>\r\n\r\n @if (helperText() && !hasError()) {\r\n <p [attr.id]=\"id() ? id() + '-helper' : null\" class=\"text-xs text-surface-500\">\r\n {{ helperText() }}\r\n </p>\r\n }\r\n @if (errorText() && hasError()) {\r\n <p [attr.id]=\"id() ? id() + '-helper' : null\" class=\"text-xs text-danger-600\">\r\n {{ errorText() }}\r\n </p>\r\n }\r\n</div>\r\n", styles: [":host{display:block}\n"] }]
|
|
1769
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], cols: [{ type: i0.Input, args: [{ isSignal: true, alias: "cols", required: false }] }], maxlength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxlength", required: false }] }], resize: [{ type: i0.Input, args: [{ isSignal: true, alias: "resize", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], helperText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helperText", required: false }] }], errorText: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorText", required: false }] }], hasError: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasError", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
|
|
1770
|
+
|
|
1771
|
+
class TailwindUpload extends TailwindComponent {
|
|
1772
|
+
static nextId = 0;
|
|
1773
|
+
fallbackFileId = `tw-upload-${TailwindUpload.nextId++}`;
|
|
1774
|
+
fileInput = viewChild.required('fileInput');
|
|
1775
|
+
/** Visual layout: compact button or drop zone */
|
|
1776
|
+
variant = input('area', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
1777
|
+
/** Field label */
|
|
1778
|
+
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
1779
|
+
/** Button label when `variant` is `button` */
|
|
1780
|
+
buttonLabel = input('Choose file', ...(ngDevMode ? [{ debugName: "buttonLabel" }] : /* istanbul ignore next */ []));
|
|
1781
|
+
/** Drop zone title when `variant` is `area` */
|
|
1782
|
+
areaTitle = input('Drag and drop a file', ...(ngDevMode ? [{ debugName: "areaTitle" }] : /* istanbul ignore next */ []));
|
|
1783
|
+
/** Drop zone hint when `variant` is `area` */
|
|
1784
|
+
areaHint = input('or click to browse', ...(ngDevMode ? [{ debugName: "areaHint" }] : /* istanbul ignore next */ []));
|
|
1785
|
+
/** Accepted MIME types / extensions (native `accept`) */
|
|
1786
|
+
accept = input(undefined, ...(ngDevMode ? [{ debugName: "accept" }] : /* istanbul ignore next */ []));
|
|
1787
|
+
/** Allow multiple files */
|
|
1788
|
+
multiple = input(false, ...(ngDevMode ? [{ debugName: "multiple" }] : /* istanbul ignore next */ []));
|
|
1789
|
+
/** Max size per file (bytes); if any file exceeds it, selection is rejected */
|
|
1790
|
+
maxFileSizeBytes = input(undefined, ...(ngDevMode ? [{ debugName: "maxFileSizeBytes" }] : /* istanbul ignore next */ []));
|
|
1791
|
+
/** Button / control size */
|
|
1792
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
1793
|
+
/** Show a clear control when there is a value */
|
|
1794
|
+
showClear = input(true, ...(ngDevMode ? [{ debugName: "showClear" }] : /* istanbul ignore next */ []));
|
|
1795
|
+
/** Label for the clear action (i18n) */
|
|
1796
|
+
clearText = input('clear', ...(ngDevMode ? [{ debugName: "clearText" }] : /* istanbul ignore next */ []));
|
|
1797
|
+
helperText = input('', ...(ngDevMode ? [{ debugName: "helperText" }] : /* istanbul ignore next */ []));
|
|
1798
|
+
errorText = input('', ...(ngDevMode ? [{ debugName: "errorText" }] : /* istanbul ignore next */ []));
|
|
1799
|
+
hasError = input(false, ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
|
|
1800
|
+
/** Data URL (`data:<mime>;base64,...`) — forms / `[(value)]`; with `multiple`, only the first file is stored here */
|
|
1801
|
+
value = model('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
1802
|
+
/** Raw files after a successful selection */
|
|
1803
|
+
filesSelected = output();
|
|
1804
|
+
/** Human-readable validation message when selection is rejected */
|
|
1805
|
+
validationError = output();
|
|
1806
|
+
isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
1807
|
+
isDragOver = signal(false, ...(ngDevMode ? [{ debugName: "isDragOver" }] : /* istanbul ignore next */ []));
|
|
1808
|
+
selectedNames = signal([], ...(ngDevMode ? [{ debugName: "selectedNames" }] : /* istanbul ignore next */ []));
|
|
1809
|
+
dragDepth = 0;
|
|
1810
|
+
onChange = () => { };
|
|
1811
|
+
onTouched = () => { };
|
|
1812
|
+
fileInputId = computed(() => this.id() ?? this.fallbackFileId, ...(ngDevMode ? [{ debugName: "fileInputId" }] : /* istanbul ignore next */ []));
|
|
1813
|
+
areaClasses = computed(() => {
|
|
1814
|
+
const base = [
|
|
1815
|
+
'flex flex-col items-center justify-center gap-2 rounded-lg border-2 border-dashed px-6 py-10 text-center',
|
|
1816
|
+
'transition-colors duration-150 outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2'
|
|
1817
|
+
];
|
|
1818
|
+
if (this.isDisabled()) {
|
|
1819
|
+
return [...base, 'cursor-not-allowed opacity-50 bg-surface-50 border-surface-200 text-surface-500'].join(' ');
|
|
1820
|
+
}
|
|
1821
|
+
if (this.isDragOver()) {
|
|
1822
|
+
return [...base, 'cursor-pointer border-primary-500 bg-primary-50/60 text-surface-800 focus-visible:outline-primary-500'].join(' ');
|
|
1823
|
+
}
|
|
1824
|
+
if (this.hasError()) {
|
|
1825
|
+
return [
|
|
1826
|
+
...base,
|
|
1827
|
+
'cursor-pointer border-danger-400 bg-danger-50/40 text-danger-900 focus-visible:outline-danger-500 hover:border-danger-500'
|
|
1828
|
+
].join(' ');
|
|
1829
|
+
}
|
|
1830
|
+
return [
|
|
1831
|
+
...base,
|
|
1832
|
+
'cursor-pointer border-surface-300 bg-surface-50/50 text-surface-800 focus-visible:outline-primary-500',
|
|
1833
|
+
'hover:border-primary-400 hover:bg-primary-50/30'
|
|
1834
|
+
].join(' ');
|
|
1835
|
+
}, ...(ngDevMode ? [{ debugName: "areaClasses" }] : /* istanbul ignore next */ []));
|
|
1836
|
+
writeValue(obj) {
|
|
1837
|
+
this.value.set(obj ?? '');
|
|
1838
|
+
if (!obj) {
|
|
1839
|
+
this.selectedNames.set([]);
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
registerOnChange(fn) {
|
|
1843
|
+
this.onChange = fn;
|
|
1844
|
+
}
|
|
1845
|
+
registerOnTouched(fn) {
|
|
1846
|
+
this.onTouched = fn;
|
|
1847
|
+
}
|
|
1848
|
+
setDisabledState(disabled) {
|
|
1849
|
+
this.isDisabled.set(disabled);
|
|
1850
|
+
}
|
|
1851
|
+
triggerPicker(event) {
|
|
1852
|
+
event?.preventDefault();
|
|
1853
|
+
event?.stopPropagation();
|
|
1854
|
+
if (this.isDisabled())
|
|
1855
|
+
return;
|
|
1856
|
+
this.fileInput().nativeElement.click();
|
|
1857
|
+
}
|
|
1858
|
+
onKeydownArea(event) {
|
|
1859
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
1860
|
+
event.preventDefault();
|
|
1861
|
+
this.triggerPicker();
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
onDragEnter(event) {
|
|
1865
|
+
event.preventDefault();
|
|
1866
|
+
event.stopPropagation();
|
|
1867
|
+
if (this.isDisabled())
|
|
1868
|
+
return;
|
|
1869
|
+
this.dragDepth++;
|
|
1870
|
+
this.isDragOver.set(true);
|
|
1871
|
+
}
|
|
1872
|
+
onDragLeave(event) {
|
|
1873
|
+
event.preventDefault();
|
|
1874
|
+
event.stopPropagation();
|
|
1875
|
+
this.dragDepth = Math.max(0, this.dragDepth - 1);
|
|
1876
|
+
if (this.dragDepth === 0) {
|
|
1877
|
+
this.isDragOver.set(false);
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
onDragOver(event) {
|
|
1881
|
+
event.preventDefault();
|
|
1882
|
+
event.stopPropagation();
|
|
1883
|
+
}
|
|
1884
|
+
onDrop(event) {
|
|
1885
|
+
event.preventDefault();
|
|
1886
|
+
event.stopPropagation();
|
|
1887
|
+
this.dragDepth = 0;
|
|
1888
|
+
this.isDragOver.set(false);
|
|
1889
|
+
if (this.isDisabled())
|
|
1890
|
+
return;
|
|
1891
|
+
const files = event.dataTransfer?.files;
|
|
1892
|
+
if (files?.length) {
|
|
1893
|
+
void this.handleFiles(files);
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
onNativeChange(event) {
|
|
1897
|
+
const input = event.target;
|
|
1898
|
+
const files = input.files;
|
|
1899
|
+
if (files?.length) {
|
|
1900
|
+
void this.handleFiles(files);
|
|
1901
|
+
}
|
|
1902
|
+
input.value = '';
|
|
1903
|
+
}
|
|
1904
|
+
clear(event) {
|
|
1905
|
+
event?.preventDefault();
|
|
1906
|
+
event?.stopPropagation();
|
|
1907
|
+
if (this.isDisabled())
|
|
1908
|
+
return;
|
|
1909
|
+
this.selectedNames.set([]);
|
|
1910
|
+
this.value.set('');
|
|
1911
|
+
this.onChange('');
|
|
1912
|
+
this.fileInput().nativeElement.value = '';
|
|
1913
|
+
}
|
|
1914
|
+
blurHost() {
|
|
1915
|
+
this.onTouched();
|
|
1916
|
+
}
|
|
1917
|
+
validate(files) {
|
|
1918
|
+
const max = this.maxFileSizeBytes();
|
|
1919
|
+
if (max == null)
|
|
1920
|
+
return null;
|
|
1921
|
+
const tooLarge = files.filter((f) => f.size > max);
|
|
1922
|
+
if (tooLarge.length === 0)
|
|
1923
|
+
return null;
|
|
1924
|
+
const maxLabel = max >= 1024 * 1024
|
|
1925
|
+
? `${(max / (1024 * 1024)).toFixed(1)} MB`
|
|
1926
|
+
: max >= 1024
|
|
1927
|
+
? `${Math.round(max / 1024)} KB`
|
|
1928
|
+
: `${max} bytes`;
|
|
1929
|
+
return tooLarge.length === 1
|
|
1930
|
+
? `File exceeds maximum size (${maxLabel}).`
|
|
1931
|
+
: `${tooLarge.length} files exceed maximum size (${maxLabel}).`;
|
|
1932
|
+
}
|
|
1933
|
+
async handleFiles(fileList) {
|
|
1934
|
+
let files = Array.from(fileList);
|
|
1935
|
+
if (!this.multiple() && files.length > 1) {
|
|
1936
|
+
files = [files[0]];
|
|
1937
|
+
}
|
|
1938
|
+
const err = this.validate(files);
|
|
1939
|
+
if (err) {
|
|
1940
|
+
this.validationError.emit(err);
|
|
1941
|
+
return;
|
|
1942
|
+
}
|
|
1943
|
+
this.selectedNames.set(files.map((f) => f.name));
|
|
1944
|
+
try {
|
|
1945
|
+
const dataUrls = await Promise.all(files.map((f) => this.readAsDataUrl(f)));
|
|
1946
|
+
this.filesSelected.emit(files);
|
|
1947
|
+
const primary = dataUrls[0] ?? '';
|
|
1948
|
+
this.value.set(primary);
|
|
1949
|
+
this.onChange(primary);
|
|
1950
|
+
}
|
|
1951
|
+
catch {
|
|
1952
|
+
this.validationError.emit('Could not read file.');
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
readAsDataUrl(file) {
|
|
1956
|
+
return new Promise((resolve, reject) => {
|
|
1957
|
+
const reader = new FileReader();
|
|
1958
|
+
reader.onload = () => {
|
|
1959
|
+
const result = reader.result;
|
|
1960
|
+
if (typeof result === 'string') {
|
|
1961
|
+
resolve(result);
|
|
1962
|
+
}
|
|
1963
|
+
else {
|
|
1964
|
+
reject(new Error('Unexpected read result'));
|
|
1965
|
+
}
|
|
1966
|
+
};
|
|
1967
|
+
reader.onerror = () => reject(reader.error ?? new Error('read error'));
|
|
1968
|
+
reader.readAsDataURL(file);
|
|
1969
|
+
});
|
|
1970
|
+
}
|
|
1971
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindUpload, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1972
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindUpload, isStandalone: true, selector: "tailwind-upload", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, buttonLabel: { classPropertyName: "buttonLabel", publicName: "buttonLabel", isSignal: true, isRequired: false, transformFunction: null }, areaTitle: { classPropertyName: "areaTitle", publicName: "areaTitle", isSignal: true, isRequired: false, transformFunction: null }, areaHint: { classPropertyName: "areaHint", publicName: "areaHint", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, maxFileSizeBytes: { classPropertyName: "maxFileSizeBytes", publicName: "maxFileSizeBytes", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, showClear: { classPropertyName: "showClear", publicName: "showClear", isSignal: true, isRequired: false, transformFunction: null }, clearText: { classPropertyName: "clearText", publicName: "clearText", isSignal: true, isRequired: false, transformFunction: null }, helperText: { classPropertyName: "helperText", publicName: "helperText", isSignal: true, isRequired: false, transformFunction: null }, errorText: { classPropertyName: "errorText", publicName: "errorText", isSignal: true, isRequired: false, transformFunction: null }, hasError: { classPropertyName: "hasError", publicName: "hasError", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", filesSelected: "filesSelected", validationError: "validationError" }, providers: [
|
|
1973
|
+
{
|
|
1974
|
+
provide: NG_VALUE_ACCESSOR,
|
|
1975
|
+
useExisting: forwardRef(() => TailwindUpload),
|
|
1976
|
+
multi: true
|
|
1977
|
+
}
|
|
1978
|
+
], viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"tailwind-upload-wrapper flex flex-col gap-1.5\">\r\n @if (label()) {\r\n <label\r\n [attr.for]=\"fileInputId()\"\r\n class=\"text-sm font-medium text-surface-700\"\r\n [class.text-danger-600]=\"hasError()\">\r\n {{ label() }}\r\n </label>\r\n }\r\n\r\n <input\r\n #fileInput\r\n type=\"file\"\r\n class=\"sr-only\"\r\n [attr.id]=\"fileInputId()\"\r\n [accept]=\"accept() ?? null\"\r\n [attr.multiple]=\"multiple() ? '' : null\"\r\n [disabled]=\"isDisabled()\"\r\n [attr.aria-invalid]=\"hasError() || null\"\r\n [attr.aria-describedby]=\"helperText() || errorText() ? fileInputId() + '-helper' : null\"\r\n (change)=\"onNativeChange($event)\"\r\n (blur)=\"blurHost()\" />\r\n\r\n @if (variant() === 'button') {\r\n <div class=\"flex flex-wrap items-center gap-2\">\r\n <tailwind-button\r\n type=\"button\"\r\n color=\"primary\"\r\n kind=\"solid\"\r\n [size]=\"size()\"\r\n [disabled]=\"isDisabled()\"\r\n (onClick)=\"triggerPicker($event)\">\r\n {{ buttonLabel() }}\r\n </tailwind-button>\r\n @if (showClear() && value()) {\r\n <button\r\n type=\"button\"\r\n class=\"text-sm font-medium text-primary-600 underline-offset-2 hover:underline disabled:cursor-not-allowed disabled:opacity-50\"\r\n [disabled]=\"isDisabled()\"\r\n (click)=\"clear($event)\">\r\n {{ clearText() }}\r\n </button>\r\n }\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-2\">\r\n <div\r\n role=\"button\"\r\n tabindex=\"0\"\r\n [class]=\"areaClasses()\"\r\n [attr.aria-disabled]=\"isDisabled() || null\"\r\n (click)=\"triggerPicker($event)\"\r\n (keydown)=\"onKeydownArea($event)\"\r\n (dragenter)=\"onDragEnter($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (dragover)=\"onDragOver($event)\"\r\n (drop)=\"onDrop($event)\">\r\n <tailwind-icon icon=\"cloud-upload\" [size]=\"40\" />\r\n <span class=\"text-sm font-medium\">{{ areaTitle() }}</span>\r\n <span class=\"text-xs text-surface-500\">{{ areaHint() }}</span>\r\n </div>\r\n @if (showClear() && value()) {\r\n <button\r\n type=\"button\"\r\n class=\"self-start text-sm font-medium text-primary-600 underline-offset-2 hover:underline disabled:cursor-not-allowed disabled:opacity-50\"\r\n [disabled]=\"isDisabled()\"\r\n (click)=\"clear($event)\">\r\n {{ clearText() }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n @if (selectedNames().length) {\r\n <p class=\"truncate text-xs text-surface-600\" [attr.title]=\"selectedNames().join(', ')\">\r\n {{ selectedNames().join(', ') }}\r\n </p>\r\n }\r\n\r\n @if (helperText() && !hasError()) {\r\n <p [attr.id]=\"fileInputId() + '-helper'\" class=\"text-xs text-surface-500\">\r\n {{ helperText() }}\r\n </p>\r\n }\r\n @if (errorText() && hasError()) {\r\n <p [attr.id]=\"fileInputId() + '-helper'\" class=\"text-xs text-danger-600\">\r\n {{ errorText() }}\r\n </p>\r\n }\r\n</div>\r\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "component", type: TailwindIcon, selector: "tailwind-icon", inputs: ["icon", "size"] }, { kind: "component", type: TailwindButton, selector: "tailwind-button", inputs: ["color", "kind", "size", "disabled", "type"], outputs: ["onClick"] }] });
|
|
1979
|
+
}
|
|
1980
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindUpload, decorators: [{
|
|
1981
|
+
type: Component,
|
|
1982
|
+
args: [{ selector: 'tailwind-upload', imports: [TailwindIcon, TailwindButton], providers: [
|
|
1983
|
+
{
|
|
1984
|
+
provide: NG_VALUE_ACCESSOR,
|
|
1985
|
+
useExisting: forwardRef(() => TailwindUpload),
|
|
1986
|
+
multi: true
|
|
1987
|
+
}
|
|
1988
|
+
], template: "<div class=\"tailwind-upload-wrapper flex flex-col gap-1.5\">\r\n @if (label()) {\r\n <label\r\n [attr.for]=\"fileInputId()\"\r\n class=\"text-sm font-medium text-surface-700\"\r\n [class.text-danger-600]=\"hasError()\">\r\n {{ label() }}\r\n </label>\r\n }\r\n\r\n <input\r\n #fileInput\r\n type=\"file\"\r\n class=\"sr-only\"\r\n [attr.id]=\"fileInputId()\"\r\n [accept]=\"accept() ?? null\"\r\n [attr.multiple]=\"multiple() ? '' : null\"\r\n [disabled]=\"isDisabled()\"\r\n [attr.aria-invalid]=\"hasError() || null\"\r\n [attr.aria-describedby]=\"helperText() || errorText() ? fileInputId() + '-helper' : null\"\r\n (change)=\"onNativeChange($event)\"\r\n (blur)=\"blurHost()\" />\r\n\r\n @if (variant() === 'button') {\r\n <div class=\"flex flex-wrap items-center gap-2\">\r\n <tailwind-button\r\n type=\"button\"\r\n color=\"primary\"\r\n kind=\"solid\"\r\n [size]=\"size()\"\r\n [disabled]=\"isDisabled()\"\r\n (onClick)=\"triggerPicker($event)\">\r\n {{ buttonLabel() }}\r\n </tailwind-button>\r\n @if (showClear() && value()) {\r\n <button\r\n type=\"button\"\r\n class=\"text-sm font-medium text-primary-600 underline-offset-2 hover:underline disabled:cursor-not-allowed disabled:opacity-50\"\r\n [disabled]=\"isDisabled()\"\r\n (click)=\"clear($event)\">\r\n {{ clearText() }}\r\n </button>\r\n }\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-2\">\r\n <div\r\n role=\"button\"\r\n tabindex=\"0\"\r\n [class]=\"areaClasses()\"\r\n [attr.aria-disabled]=\"isDisabled() || null\"\r\n (click)=\"triggerPicker($event)\"\r\n (keydown)=\"onKeydownArea($event)\"\r\n (dragenter)=\"onDragEnter($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (dragover)=\"onDragOver($event)\"\r\n (drop)=\"onDrop($event)\">\r\n <tailwind-icon icon=\"cloud-upload\" [size]=\"40\" />\r\n <span class=\"text-sm font-medium\">{{ areaTitle() }}</span>\r\n <span class=\"text-xs text-surface-500\">{{ areaHint() }}</span>\r\n </div>\r\n @if (showClear() && value()) {\r\n <button\r\n type=\"button\"\r\n class=\"self-start text-sm font-medium text-primary-600 underline-offset-2 hover:underline disabled:cursor-not-allowed disabled:opacity-50\"\r\n [disabled]=\"isDisabled()\"\r\n (click)=\"clear($event)\">\r\n {{ clearText() }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n @if (selectedNames().length) {\r\n <p class=\"truncate text-xs text-surface-600\" [attr.title]=\"selectedNames().join(', ')\">\r\n {{ selectedNames().join(', ') }}\r\n </p>\r\n }\r\n\r\n @if (helperText() && !hasError()) {\r\n <p [attr.id]=\"fileInputId() + '-helper'\" class=\"text-xs text-surface-500\">\r\n {{ helperText() }}\r\n </p>\r\n }\r\n @if (errorText() && hasError()) {\r\n <p [attr.id]=\"fileInputId() + '-helper'\" class=\"text-xs text-danger-600\">\r\n {{ errorText() }}\r\n </p>\r\n }\r\n</div>\r\n", styles: [":host{display:block}\n"] }]
|
|
1989
|
+
}], propDecorators: { fileInput: [{ type: i0.ViewChild, args: ['fileInput', { isSignal: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], buttonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonLabel", required: false }] }], areaTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "areaTitle", required: false }] }], areaHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "areaHint", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], maxFileSizeBytes: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFileSizeBytes", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], clearText: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearText", required: false }] }], helperText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helperText", required: false }] }], errorText: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorText", required: false }] }], hasError: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasError", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], filesSelected: [{ type: i0.Output, args: ["filesSelected"] }], validationError: [{ type: i0.Output, args: ["validationError"] }] } });
|
|
1990
|
+
|
|
1991
|
+
class TailwindInputOtp extends TailwindComponent {
|
|
1992
|
+
/** Label text */
|
|
1993
|
+
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
1994
|
+
/** Number of character slots */
|
|
1995
|
+
length = input(6, ...(ngDevMode ? [{ debugName: "length" }] : /* istanbul ignore next */ []));
|
|
1996
|
+
/** Allow only digits */
|
|
1997
|
+
integerOnly = input(true, ...(ngDevMode ? [{ debugName: "integerOnly" }] : /* istanbul ignore next */ []));
|
|
1998
|
+
/** Mask digits (password bullets) */
|
|
1999
|
+
mask = input(false, ...(ngDevMode ? [{ debugName: "mask" }] : /* istanbul ignore next */ []));
|
|
2000
|
+
/** Size variant */
|
|
2001
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
2002
|
+
/** Slots are read-only (navigation still allowed) */
|
|
2003
|
+
readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
|
|
2004
|
+
/** Helper text shown below */
|
|
2005
|
+
helperText = input('', ...(ngDevMode ? [{ debugName: "helperText" }] : /* istanbul ignore next */ []));
|
|
2006
|
+
/** Error text when hasError is true */
|
|
2007
|
+
errorText = input('', ...(ngDevMode ? [{ debugName: "errorText" }] : /* istanbul ignore next */ []));
|
|
2008
|
+
/** Error state styling */
|
|
2009
|
+
hasError = input(false, ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
|
|
2010
|
+
/** Accessible label for the group (used when label is empty) */
|
|
2011
|
+
ariaLabel = input('Verification code', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
2012
|
+
/** Separator string; empty hides */
|
|
2013
|
+
separator = input('', ...(ngDevMode ? [{ debugName: "separator" }] : /* istanbul ignore next */ []));
|
|
2014
|
+
/** 0-based slot index after which the separator is rendered */
|
|
2015
|
+
separatorAfterIndex = input(null, ...(ngDevMode ? [{ debugName: "separatorAfterIndex" }] : /* istanbul ignore next */ []));
|
|
2016
|
+
/** Hint for browsers / SMS autofill (first slot only) */
|
|
2017
|
+
autocomplete = input('one-time-code', ...(ngDevMode ? [{ debugName: "autocomplete" }] : /* istanbul ignore next */ []));
|
|
2018
|
+
/** Two-way bound full code string */
|
|
2019
|
+
value = model('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
2020
|
+
/** Emitted when all slots are filled */
|
|
2021
|
+
completed = output();
|
|
2022
|
+
isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
2023
|
+
slotIndexes = computed(() => {
|
|
2024
|
+
const n = Math.max(1, Math.min(32, Math.floor(this.length())));
|
|
2025
|
+
return Array.from({ length: n }, (_, i) => i);
|
|
2026
|
+
}, ...(ngDevMode ? [{ debugName: "slotIndexes" }] : /* istanbul ignore next */ []));
|
|
2027
|
+
otpInputs = viewChildren('otpDigit', ...(ngDevMode ? [{ debugName: "otpInputs" }] : /* istanbul ignore next */ []));
|
|
2028
|
+
cellClasses = computed(() => {
|
|
2029
|
+
const base = [
|
|
2030
|
+
'block w-10 text-center font-mono tabular-nums bg-white',
|
|
2031
|
+
'border transition-colors duration-150',
|
|
2032
|
+
'outline-none focus:outline focus:outline-2 focus:outline-offset-2',
|
|
2033
|
+
'disabled:bg-surface-50 disabled:text-surface-400 disabled:cursor-not-allowed'
|
|
2034
|
+
];
|
|
2035
|
+
const sizeMap = {
|
|
2036
|
+
xs: 'text-xs px-1 py-1 rounded-sm min-w-7',
|
|
2037
|
+
sm: 'text-sm px-1.5 py-1.5 rounded-md min-w-8',
|
|
2038
|
+
md: 'text-sm px-2 py-2 rounded-md min-w-10',
|
|
2039
|
+
lg: 'text-base px-2.5 py-2.5 rounded-lg min-w-11',
|
|
2040
|
+
xl: 'text-base px-3 py-3 rounded-lg min-w-12'
|
|
2041
|
+
};
|
|
2042
|
+
const stateClass = this.hasError()
|
|
2043
|
+
? 'border-danger-400 focus:outline-danger-500 text-danger-900'
|
|
2044
|
+
: 'border-surface-300 focus:outline-primary-500 text-surface-900';
|
|
2045
|
+
return [...base, sizeMap[this.size()], stateClass].join(' ');
|
|
2046
|
+
}, ...(ngDevMode ? [{ debugName: "cellClasses" }] : /* istanbul ignore next */ []));
|
|
2047
|
+
groupAriaLabel = computed(() => this.label() || this.ariaLabel(), ...(ngDevMode ? [{ debugName: "groupAriaLabel" }] : /* istanbul ignore next */ []));
|
|
2048
|
+
onChange = () => { };
|
|
2049
|
+
onTouched = () => { };
|
|
2050
|
+
writeValue(value) {
|
|
2051
|
+
this.value.set(this.normalizeIncoming(value ?? ''));
|
|
2052
|
+
}
|
|
2053
|
+
registerOnChange(fn) {
|
|
2054
|
+
this.onChange = fn;
|
|
2055
|
+
}
|
|
2056
|
+
registerOnTouched(fn) {
|
|
2057
|
+
this.onTouched = fn;
|
|
2058
|
+
}
|
|
2059
|
+
setDisabledState(disabled) {
|
|
2060
|
+
this.isDisabled.set(disabled);
|
|
2061
|
+
}
|
|
2062
|
+
maxSlots() {
|
|
2063
|
+
return this.slotIndexes().length;
|
|
2064
|
+
}
|
|
2065
|
+
digitAt(index) {
|
|
2066
|
+
return this.value()[index] ?? '';
|
|
2067
|
+
}
|
|
2068
|
+
showSeparatorAfter(index) {
|
|
2069
|
+
const sep = this.separator();
|
|
2070
|
+
const pos = this.separatorAfterIndex();
|
|
2071
|
+
return !!sep && pos !== null && pos === index;
|
|
2072
|
+
}
|
|
2073
|
+
inputType() {
|
|
2074
|
+
return this.mask() ? 'password' : 'text';
|
|
2075
|
+
}
|
|
2076
|
+
inputMode() {
|
|
2077
|
+
return this.integerOnly() ? 'numeric' : 'text';
|
|
2078
|
+
}
|
|
2079
|
+
autocompleteForSlot(index) {
|
|
2080
|
+
return index === 0 ? this.autocomplete() : null;
|
|
2081
|
+
}
|
|
2082
|
+
cellId(index) {
|
|
2083
|
+
const base = this.id() ?? 'tailwind-input-otp';
|
|
2084
|
+
return `${base}-digit-${index}`;
|
|
2085
|
+
}
|
|
2086
|
+
onSlotFocus(index) {
|
|
2087
|
+
this.onTouched();
|
|
2088
|
+
const len = this.value().length;
|
|
2089
|
+
if (index > len) {
|
|
2090
|
+
queueMicrotask(() => this.focusSlot(Math.min(len, this.maxSlots() - 1)));
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
onInput(event, index) {
|
|
2094
|
+
if (this.readonly()) {
|
|
2095
|
+
return;
|
|
2096
|
+
}
|
|
2097
|
+
const inputEl = event.target;
|
|
2098
|
+
let raw = inputEl.value;
|
|
2099
|
+
if (this.integerOnly()) {
|
|
2100
|
+
raw = raw.replace(/\D/g, '');
|
|
2101
|
+
}
|
|
2102
|
+
const char = raw.slice(-1);
|
|
2103
|
+
let v = this.value();
|
|
2104
|
+
const max = this.maxSlots();
|
|
2105
|
+
if (char && index > v.length) {
|
|
2106
|
+
queueMicrotask(() => this.focusSlot(v.length));
|
|
2107
|
+
inputEl.value = this.digitAt(index);
|
|
2108
|
+
return;
|
|
2109
|
+
}
|
|
2110
|
+
if (!char) {
|
|
2111
|
+
if (index < v.length) {
|
|
2112
|
+
v = v.slice(0, index) + v.slice(index + 1);
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
else {
|
|
2116
|
+
if (index < v.length) {
|
|
2117
|
+
v = v.slice(0, index) + char + v.slice(index + 1);
|
|
2118
|
+
}
|
|
2119
|
+
else if (index === v.length) {
|
|
2120
|
+
v = v + char;
|
|
2121
|
+
}
|
|
2122
|
+
v = v.slice(0, max);
|
|
2123
|
+
}
|
|
2124
|
+
v = this.normalizeIncoming(v);
|
|
2125
|
+
this.commit(v);
|
|
2126
|
+
queueMicrotask(() => {
|
|
2127
|
+
inputEl.value = this.digitAt(index);
|
|
2128
|
+
if (char && index < max - 1) {
|
|
2129
|
+
this.focusSlot(index + 1);
|
|
2130
|
+
}
|
|
2131
|
+
});
|
|
2132
|
+
}
|
|
2133
|
+
onPaste(event, index) {
|
|
2134
|
+
if (this.readonly() || this.isDisabled()) {
|
|
2135
|
+
return;
|
|
2136
|
+
}
|
|
2137
|
+
event.preventDefault();
|
|
2138
|
+
const text = event.clipboardData?.getData('text') ?? '';
|
|
2139
|
+
let cleaned = this.integerOnly() ? text.replace(/\D/g, '') : text.replace(/\s/g, '');
|
|
2140
|
+
const max = this.maxSlots();
|
|
2141
|
+
cleaned = cleaned.slice(0, max - index);
|
|
2142
|
+
const merged = this.normalizeIncoming(this.value().slice(0, index) + cleaned);
|
|
2143
|
+
this.commit(merged);
|
|
2144
|
+
queueMicrotask(() => this.focusSlot(cleaned.length ? Math.min(index + cleaned.length - 1, max - 1) : index));
|
|
2145
|
+
}
|
|
2146
|
+
onKeydown(event, index) {
|
|
2147
|
+
const max = this.maxSlots();
|
|
2148
|
+
const v = this.value();
|
|
2149
|
+
if (event.key === 'Backspace') {
|
|
2150
|
+
const cur = this.digitAt(index);
|
|
2151
|
+
if (!cur && index > 0) {
|
|
2152
|
+
event.preventDefault();
|
|
2153
|
+
const nextVal = this.normalizeIncoming(v.slice(0, index - 1) + v.slice(index));
|
|
2154
|
+
this.commit(nextVal);
|
|
2155
|
+
queueMicrotask(() => this.focusSlot(index - 1));
|
|
2156
|
+
}
|
|
2157
|
+
else if (cur) {
|
|
2158
|
+
event.preventDefault();
|
|
2159
|
+
const nextVal = this.normalizeIncoming(v.slice(0, index) + v.slice(index + 1));
|
|
2160
|
+
this.commit(nextVal);
|
|
2161
|
+
queueMicrotask(() => {
|
|
2162
|
+
const el = this.otpInputs()[index]?.nativeElement;
|
|
2163
|
+
if (el) {
|
|
2164
|
+
el.value = this.digitAt(index);
|
|
2165
|
+
}
|
|
2166
|
+
});
|
|
2167
|
+
}
|
|
2168
|
+
return;
|
|
2169
|
+
}
|
|
2170
|
+
if (event.key === 'ArrowLeft' && index > 0) {
|
|
2171
|
+
event.preventDefault();
|
|
2172
|
+
this.focusSlot(index - 1);
|
|
2173
|
+
}
|
|
2174
|
+
else if (event.key === 'ArrowRight' && index < max - 1) {
|
|
2175
|
+
event.preventDefault();
|
|
2176
|
+
this.focusSlot(index + 1);
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
commit(joined) {
|
|
2180
|
+
const prev = this.value();
|
|
2181
|
+
this.value.set(joined);
|
|
2182
|
+
this.onChange(joined);
|
|
2183
|
+
const max = this.maxSlots();
|
|
2184
|
+
if (joined.length === max && prev.length !== max) {
|
|
2185
|
+
this.completed.emit(joined);
|
|
2186
|
+
}
|
|
2187
|
+
}
|
|
2188
|
+
normalizeIncoming(v) {
|
|
2189
|
+
const max = Math.max(1, Math.min(32, Math.floor(this.length())));
|
|
2190
|
+
let s = v ?? '';
|
|
2191
|
+
if (this.integerOnly()) {
|
|
2192
|
+
s = s.replace(/\D/g, '');
|
|
2193
|
+
}
|
|
2194
|
+
return s.slice(0, max);
|
|
2195
|
+
}
|
|
2196
|
+
focusSlot(index) {
|
|
2197
|
+
queueMicrotask(() => {
|
|
2198
|
+
const list = this.otpInputs();
|
|
2199
|
+
const el = list[index]?.nativeElement;
|
|
2200
|
+
el?.focus();
|
|
2201
|
+
el?.select();
|
|
2202
|
+
});
|
|
2203
|
+
}
|
|
2204
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindInputOtp, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
2205
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindInputOtp, isStandalone: true, selector: "tailwind-input-otp", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, length: { classPropertyName: "length", publicName: "length", isSignal: true, isRequired: false, transformFunction: null }, integerOnly: { classPropertyName: "integerOnly", publicName: "integerOnly", isSignal: true, isRequired: false, transformFunction: null }, mask: { classPropertyName: "mask", publicName: "mask", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, helperText: { classPropertyName: "helperText", publicName: "helperText", isSignal: true, isRequired: false, transformFunction: null }, errorText: { classPropertyName: "errorText", publicName: "errorText", isSignal: true, isRequired: false, transformFunction: null }, hasError: { classPropertyName: "hasError", publicName: "hasError", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, separator: { classPropertyName: "separator", publicName: "separator", isSignal: true, isRequired: false, transformFunction: null }, separatorAfterIndex: { classPropertyName: "separatorAfterIndex", publicName: "separatorAfterIndex", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", completed: "completed" }, providers: [
|
|
2206
|
+
{
|
|
2207
|
+
provide: NG_VALUE_ACCESSOR,
|
|
2208
|
+
useExisting: forwardRef(() => TailwindInputOtp),
|
|
2209
|
+
multi: true
|
|
2210
|
+
}
|
|
2211
|
+
], viewQueries: [{ propertyName: "otpInputs", predicate: ["otpDigit"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"tailwind-input-otp-wrapper flex flex-col gap-1.5\">\r\n @if (label()) {\r\n <label\r\n [attr.for]=\"cellId(0)\"\r\n class=\"text-sm font-medium text-surface-700\"\r\n [class.text-danger-600]=\"hasError()\">\r\n {{ label() }}\r\n </label>\r\n }\r\n\r\n <div role=\"group\" [attr.aria-label]=\"groupAriaLabel()\" class=\"flex flex-wrap items-center gap-2\">\r\n @for (idx of slotIndexes(); track idx) {\r\n <input\r\n #otpDigit\r\n [attr.id]=\"cellId(idx)\"\r\n [type]=\"inputType()\"\r\n [attr.inputmode]=\"inputMode()\"\r\n [attr.autocomplete]=\"autocompleteForSlot(idx)\"\r\n [attr.aria-label]=\"'Digit ' + (idx + 1) + ' of ' + slotIndexes().length\"\r\n [disabled]=\"isDisabled()\"\r\n [readonly]=\"readonly()\"\r\n [attr.aria-invalid]=\"hasError() || null\"\r\n [attr.aria-describedby]=\"(helperText() || errorText()) && id() ? id() + '-helper' : null\"\r\n maxlength=\"1\"\r\n spellcheck=\"false\"\r\n [class]=\"cellClasses()\"\r\n [value]=\"digitAt(idx)\"\r\n (input)=\"onInput($event, idx)\"\r\n (keydown)=\"onKeydown($event, idx)\"\r\n (paste)=\"onPaste($event, idx)\"\r\n (focus)=\"onSlotFocus(idx)\" />\r\n @if (showSeparatorAfter(idx)) {\r\n <span class=\"select-none text-surface-500\" aria-hidden=\"true\">{{ separator() }}</span>\r\n }\r\n }\r\n </div>\r\n\r\n @if (helperText() && !hasError()) {\r\n <p [attr.id]=\"id() ? id() + '-helper' : null\" class=\"text-xs text-surface-500\">\r\n {{ helperText() }}\r\n </p>\r\n }\r\n @if (errorText() && hasError()) {\r\n <p [attr.id]=\"id() ? id() + '-helper' : null\" class=\"text-xs text-danger-600\">\r\n {{ errorText() }}\r\n </p>\r\n }\r\n</div>\r\n", styles: [":host{display:block}\n"] });
|
|
2212
|
+
}
|
|
2213
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindInputOtp, decorators: [{
|
|
2214
|
+
type: Component,
|
|
2215
|
+
args: [{ selector: 'tailwind-input-otp', providers: [
|
|
2216
|
+
{
|
|
2217
|
+
provide: NG_VALUE_ACCESSOR,
|
|
2218
|
+
useExisting: forwardRef(() => TailwindInputOtp),
|
|
2219
|
+
multi: true
|
|
2220
|
+
}
|
|
2221
|
+
], template: "<div class=\"tailwind-input-otp-wrapper flex flex-col gap-1.5\">\r\n @if (label()) {\r\n <label\r\n [attr.for]=\"cellId(0)\"\r\n class=\"text-sm font-medium text-surface-700\"\r\n [class.text-danger-600]=\"hasError()\">\r\n {{ label() }}\r\n </label>\r\n }\r\n\r\n <div role=\"group\" [attr.aria-label]=\"groupAriaLabel()\" class=\"flex flex-wrap items-center gap-2\">\r\n @for (idx of slotIndexes(); track idx) {\r\n <input\r\n #otpDigit\r\n [attr.id]=\"cellId(idx)\"\r\n [type]=\"inputType()\"\r\n [attr.inputmode]=\"inputMode()\"\r\n [attr.autocomplete]=\"autocompleteForSlot(idx)\"\r\n [attr.aria-label]=\"'Digit ' + (idx + 1) + ' of ' + slotIndexes().length\"\r\n [disabled]=\"isDisabled()\"\r\n [readonly]=\"readonly()\"\r\n [attr.aria-invalid]=\"hasError() || null\"\r\n [attr.aria-describedby]=\"(helperText() || errorText()) && id() ? id() + '-helper' : null\"\r\n maxlength=\"1\"\r\n spellcheck=\"false\"\r\n [class]=\"cellClasses()\"\r\n [value]=\"digitAt(idx)\"\r\n (input)=\"onInput($event, idx)\"\r\n (keydown)=\"onKeydown($event, idx)\"\r\n (paste)=\"onPaste($event, idx)\"\r\n (focus)=\"onSlotFocus(idx)\" />\r\n @if (showSeparatorAfter(idx)) {\r\n <span class=\"select-none text-surface-500\" aria-hidden=\"true\">{{ separator() }}</span>\r\n }\r\n }\r\n </div>\r\n\r\n @if (helperText() && !hasError()) {\r\n <p [attr.id]=\"id() ? id() + '-helper' : null\" class=\"text-xs text-surface-500\">\r\n {{ helperText() }}\r\n </p>\r\n }\r\n @if (errorText() && hasError()) {\r\n <p [attr.id]=\"id() ? id() + '-helper' : null\" class=\"text-xs text-danger-600\">\r\n {{ errorText() }}\r\n </p>\r\n }\r\n</div>\r\n", styles: [":host{display:block}\n"] }]
|
|
2222
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], length: [{ type: i0.Input, args: [{ isSignal: true, alias: "length", required: false }] }], integerOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "integerOnly", required: false }] }], mask: [{ type: i0.Input, args: [{ isSignal: true, alias: "mask", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], helperText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helperText", required: false }] }], errorText: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorText", required: false }] }], hasError: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasError", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], separator: [{ type: i0.Input, args: [{ isSignal: true, alias: "separator", required: false }] }], separatorAfterIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "separatorAfterIndex", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], completed: [{ type: i0.Output, args: ["completed"] }], otpInputs: [{ type: i0.ViewChildren, args: ['otpDigit', { isSignal: true }] }] } });
|
|
2223
|
+
|
|
1675
2224
|
class TailwindCheckbox extends TailwindComponent {
|
|
1676
2225
|
/** Label text */
|
|
1677
2226
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
@@ -2814,11 +3363,11 @@ class TailwindBreadcrumb extends TailwindComponent {
|
|
|
2814
3363
|
items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
2815
3364
|
ariaLabel = input('Breadcrumb', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
2816
3365
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindBreadcrumb, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
2817
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindBreadcrumb, isStandalone: true, selector: "tailwind-breadcrumb", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<nav [attr.aria-label]=\"ariaLabel()\" class=\"flex\">\n <ol class=\"inline-flex items-center gap-1.5 text-sm\">\n @for (item of items(); track item.label; let last = $last; let first = $first) {\n <li class=\"inline-flex items-center\">\n @if (!first) {\n <span class=\"mx-1.5 text-surface-400\" aria-hidden=\"true\">\n <svg class=\"w-3.5 h-3.5\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\"\n clip-rule=\"evenodd\" />\n </svg>\n </span>\n }\n @if (item.href && !last) {\n <a
|
|
3366
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindBreadcrumb, isStandalone: true, selector: "tailwind-breadcrumb", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<nav [attr.aria-label]=\"ariaLabel()\" class=\"flex\">\n <ol class=\"inline-flex items-center gap-1.5 text-sm\">\n @for (item of items(); track item.label; let last = $last; let first = $first) {\n <li class=\"inline-flex items-center\">\n @if (!first) {\n <span class=\"mx-1.5 text-surface-400\" aria-hidden=\"true\">\n <svg class=\"w-3.5 h-3.5\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\"\n clip-rule=\"evenodd\" />\n </svg>\n </span>\n }\n @if ((item.link ?? item.href) && !last) {\n <a\n [href]=\"item.link ?? item.href\"\n class=\"inline-flex items-center gap-1 text-surface-500 hover:text-primary-600 transition-colors font-medium\">\n @if (item.icon) {\n <tailwind-icon [icon]=\"item.icon\" [size]=\"16\" />\n }\n {{ item.label }}\n </a>\n } @else {\n <span\n class=\"inline-flex items-center gap-1 font-medium\"\n [class.text-surface-900]=\"last\"\n [class.text-surface-500]=\"!last\"\n [attr.aria-current]=\"last ? 'page' : null\">\n @if (item.icon) {\n <tailwind-icon [icon]=\"item.icon\" [size]=\"16\" />\n }\n {{ item.label }}\n </span>\n }\n </li>\n }\n </ol>\n</nav>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "component", type: TailwindIcon, selector: "tailwind-icon", inputs: ["icon", "size"] }] });
|
|
2818
3367
|
}
|
|
2819
3368
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindBreadcrumb, decorators: [{
|
|
2820
3369
|
type: Component,
|
|
2821
|
-
args: [{ selector: 'tailwind-breadcrumb', template: "<nav [attr.aria-label]=\"ariaLabel()\" class=\"flex\">\n <ol class=\"inline-flex items-center gap-1.5 text-sm\">\n @for (item of items(); track item.label; let last = $last; let first = $first) {\n <li class=\"inline-flex items-center\">\n @if (!first) {\n <span class=\"mx-1.5 text-surface-400\" aria-hidden=\"true\">\n <svg class=\"w-3.5 h-3.5\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\"\n clip-rule=\"evenodd\" />\n </svg>\n </span>\n }\n @if (item.href && !last) {\n <a
|
|
3370
|
+
args: [{ imports: [TailwindIcon], selector: 'tailwind-breadcrumb', template: "<nav [attr.aria-label]=\"ariaLabel()\" class=\"flex\">\n <ol class=\"inline-flex items-center gap-1.5 text-sm\">\n @for (item of items(); track item.label; let last = $last; let first = $first) {\n <li class=\"inline-flex items-center\">\n @if (!first) {\n <span class=\"mx-1.5 text-surface-400\" aria-hidden=\"true\">\n <svg class=\"w-3.5 h-3.5\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\"\n clip-rule=\"evenodd\" />\n </svg>\n </span>\n }\n @if ((item.link ?? item.href) && !last) {\n <a\n [href]=\"item.link ?? item.href\"\n class=\"inline-flex items-center gap-1 text-surface-500 hover:text-primary-600 transition-colors font-medium\">\n @if (item.icon) {\n <tailwind-icon [icon]=\"item.icon\" [size]=\"16\" />\n }\n {{ item.label }}\n </a>\n } @else {\n <span\n class=\"inline-flex items-center gap-1 font-medium\"\n [class.text-surface-900]=\"last\"\n [class.text-surface-500]=\"!last\"\n [attr.aria-current]=\"last ? 'page' : null\">\n @if (item.icon) {\n <tailwind-icon [icon]=\"item.icon\" [size]=\"16\" />\n }\n {{ item.label }}\n </span>\n }\n </li>\n }\n </ol>\n</nav>\n", styles: [":host{display:block}\n"] }]
|
|
2822
3371
|
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
|
|
2823
3372
|
|
|
2824
3373
|
class TailwindPagination extends TailwindComponent {
|
|
@@ -4144,5 +4693,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
4144
4693
|
* Generated bundle index. Do not edit.
|
|
4145
4694
|
*/
|
|
4146
4695
|
|
|
4147
|
-
export { TAILWIND_COMPONENTS_SIZE, TAILWIND_DATETIME_LANGUAGE, TAILWIND_ICON_SIZE, TAILWIND_MODAL_DATA, TAILWIND_SOLAR_ICON_NAMES, TailwindAccordion, TailwindAccordionItem, TailwindAlert, TailwindBadge, TailwindBreadcrumb, TailwindButton, TailwindCard, TailwindCheckbox, TailwindDatePicker, TailwindDateTimePicker, TailwindDivider, TailwindDrawer, TailwindIcon, TailwindInput, TailwindMenu, TailwindMessage, TailwindMeter, TailwindModal, TailwindModalRef, TailwindModalService, TailwindNotification, TailwindPagination, TailwindProgressBar, TailwindRadioGroup, TailwindSelect, TailwindSkeleton, TailwindSlider, TailwindSpinner, TailwindStep, TailwindStepper, TailwindTab, TailwindTabGroup, TailwindTable, TailwindTag, TailwindTimePicker, TailwindTitle, TailwindToast, TailwindToastService, TailwindToggle, TailwindToolbar, TailwindTooltip, TailwindTooltipDirective };
|
|
4696
|
+
export { TAILWIND_COMPONENTS_SIZE, TAILWIND_DATETIME_LANGUAGE, TAILWIND_ICON_SIZE, TAILWIND_MODAL_DATA, TAILWIND_SOLAR_ICON_NAMES, TailwindAccordion, TailwindAccordionItem, TailwindAlert, TailwindBadge, TailwindBreadcrumb, TailwindButton, TailwindCard, TailwindCheckbox, TailwindDatePicker, TailwindDateTimePicker, TailwindDivider, TailwindDrawer, TailwindIcon, TailwindInput, TailwindInputOtp, TailwindMenu, TailwindMessage, TailwindMeter, TailwindModal, TailwindModalRef, TailwindModalService, TailwindNotification, TailwindPagination, TailwindProgressBar, TailwindRadioGroup, TailwindSelect, TailwindSkeleton, TailwindSlider, TailwindSpinner, TailwindStep, TailwindStepper, TailwindTab, TailwindTabGroup, TailwindTable, TailwindTag, TailwindTextarea, TailwindTimePicker, TailwindTitle, TailwindToast, TailwindToastService, TailwindToggle, TailwindToolbar, TailwindTooltip, TailwindTooltipDirective, TailwindUpload };
|
|
4148
4697
|
//# sourceMappingURL=angular-tailwind-components.mjs.map
|