@besaitech/ng-design-system 0.0.33 → 0.0.34
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 { inject, input, computed, ChangeDetectionStrategy, Component, booleanAttribute, isDevMode, effect, output, signal, forwardRef,
|
|
2
|
+
import { inject, input, computed, ChangeDetectionStrategy, Component, booleanAttribute, isDevMode, effect, output, signal, forwardRef, numberAttribute, viewChildren, afterRenderEffect, viewChild, ElementRef, model, Injector, afterNextRender, Injectable, TemplateRef, Directive, contentChildren, contentChild } from '@angular/core';
|
|
3
3
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
4
4
|
import * as i1 from '@angular/forms';
|
|
5
5
|
import { NG_VALUE_ACCESSOR, NG_VALIDATORS, FormsModule } from '@angular/forms';
|
|
@@ -152,7 +152,7 @@ const VARIANTS$2 = {
|
|
|
152
152
|
ghost: 'bg-transparent text-ink-soft hover:bg-black/5 active:bg-black/10',
|
|
153
153
|
danger: 'bg-danger text-white shadow-sm hover:brightness-95 active:brightness-90',
|
|
154
154
|
};
|
|
155
|
-
const SIZES$
|
|
155
|
+
const SIZES$a = {
|
|
156
156
|
sm: 'h-8 px-3 text-sm',
|
|
157
157
|
md: 'h-10 px-4 text-sm',
|
|
158
158
|
lg: 'h-12 px-5 text-base',
|
|
@@ -212,7 +212,7 @@ class SdsButton {
|
|
|
212
212
|
BASE,
|
|
213
213
|
this.shape() === 'pill' ? 'rounded-full' : 'rounded-control',
|
|
214
214
|
VARIANTS$2[this.variant()],
|
|
215
|
-
SIZES$
|
|
215
|
+
SIZES$a[size],
|
|
216
216
|
this.iconOnly() ? ICON_ONLY[size] : '',
|
|
217
217
|
this.block() ? 'w-full' : '',
|
|
218
218
|
]
|
|
@@ -264,8 +264,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
264
264
|
`, styles: [".sds-spinner{width:1em;height:1em;border:2px solid currentColor;border-right-color:transparent;border-radius:9999px;animation:sds-spin .6s linear infinite}@keyframes sds-spin{to{transform:rotate(360deg)}}\n"] }]
|
|
265
265
|
}], ctorParameters: () => [], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: false }] }], iconOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnly", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
|
|
266
266
|
|
|
267
|
-
let nextId$
|
|
268
|
-
const SIZES$
|
|
267
|
+
let nextId$b = 0;
|
|
268
|
+
const SIZES$9 = {
|
|
269
269
|
sm: 'h-9 text-sm',
|
|
270
270
|
md: 'h-10 text-sm',
|
|
271
271
|
lg: 'h-12 text-base',
|
|
@@ -277,7 +277,7 @@ const SIZES$8 = {
|
|
|
277
277
|
* sidebar search field).
|
|
278
278
|
*/
|
|
279
279
|
class SdsInput {
|
|
280
|
-
inputId = `sds-input-${nextId$
|
|
280
|
+
inputId = `sds-input-${nextId$b++}`;
|
|
281
281
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
282
282
|
/** Accessible name used when no visible [label] is provided. */
|
|
283
283
|
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
@@ -354,7 +354,7 @@ class SdsInput {
|
|
|
354
354
|
return `${left} ${right}`;
|
|
355
355
|
}, ...(ngDevMode ? [{ debugName: "fieldPadding" }] : []));
|
|
356
356
|
wrapperClasses = computed(() => {
|
|
357
|
-
const parts = [SIZES$
|
|
357
|
+
const parts = [SIZES$9[this.size()], this.pill() ? 'rounded-full' : 'rounded-control'];
|
|
358
358
|
if (this.isDisabled())
|
|
359
359
|
parts.push('opacity-60 cursor-not-allowed');
|
|
360
360
|
if (this.filled()) {
|
|
@@ -598,6 +598,323 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
598
598
|
`, styles: ["input:-webkit-autofill,input:-webkit-autofill:hover,input:-webkit-autofill:focus,input:-webkit-autofill:active{transition:background-color 100000s ease-in-out 0s;-webkit-text-fill-color:currentColor;caret-color:currentColor}\n"] }]
|
|
599
599
|
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], leadingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "leadingIcon", required: false }] }], trailingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "trailingIcon", required: false }] }], trailingAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "trailingAction", required: false }] }], trailingActionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "trailingActionLabel", required: false }] }], trailingActionPressed: [{ type: i0.Input, args: [{ isSignal: true, alias: "trailingActionPressed", required: false }] }], trailingActionClick: [{ type: i0.Output, args: ["trailingActionClick"] }] } });
|
|
600
600
|
|
|
601
|
+
let nextId$a = 0;
|
|
602
|
+
const SIZES$8 = {
|
|
603
|
+
md: 'h-12 w-11 text-lg',
|
|
604
|
+
lg: 'h-14 w-12 text-xl',
|
|
605
|
+
};
|
|
606
|
+
/**
|
|
607
|
+
* A segmented one-time-code field: one box per character, for the short numeric codes emailed or
|
|
608
|
+
* texted for sign-in and verification. Implements ControlValueAccessor — bind
|
|
609
|
+
* `formControlName`/`[(ngModel)]`; the value is the concatenated string (e.g. `"483920"`), and
|
|
610
|
+
* {@link completed} fires the moment every box is filled.
|
|
611
|
+
*
|
|
612
|
+
* <p>Only digits are accepted (`inputMode` is `numeric` by default). Typing auto-advances,
|
|
613
|
+
* Backspace steps back and clears, the arrow keys move between boxes, and pasting a whole code
|
|
614
|
+
* distributes it across the boxes from the focused one — so a user can paste `483920` into the
|
|
615
|
+
* first box and have it land correctly.
|
|
616
|
+
*/
|
|
617
|
+
class SdsOtpInput {
|
|
618
|
+
groupId = `sds-otp-${nextId$a++}`;
|
|
619
|
+
/** How many boxes / characters the code has. */
|
|
620
|
+
length = input(6, ...(ngDevMode ? [{ debugName: "length", transform: numberAttribute }] : [{ transform: numberAttribute }]));
|
|
621
|
+
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
622
|
+
/** Accessible name for the whole group when no visible [label] is provided. */
|
|
623
|
+
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
624
|
+
hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : []));
|
|
625
|
+
error = input('', ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
626
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
627
|
+
/** `numeric` for digit codes (the default); `text` for alphanumeric codes. */
|
|
628
|
+
inputMode = input('numeric', ...(ngDevMode ? [{ debugName: "inputMode" }] : []));
|
|
629
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
630
|
+
/** Focus the first box on first render. */
|
|
631
|
+
autoFocus = input(false, ...(ngDevMode ? [{ debugName: "autoFocus", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
632
|
+
/**
|
|
633
|
+
* Accessible name for an individual box, suffixed with its 1-based position ("Digit 1", "Digit
|
|
634
|
+
* 2", …). French default so existing consumers are unchanged; translate it in an app serving more
|
|
635
|
+
* than one language, since each box is an icon-less control whose only name this is.
|
|
636
|
+
*/
|
|
637
|
+
cellLabel = input('Chiffre', ...(ngDevMode ? [{ debugName: "cellLabel" }] : []));
|
|
638
|
+
/** Emitted with the full value the moment the last box is filled. */
|
|
639
|
+
completed = output();
|
|
640
|
+
cells = viewChildren('cell', ...(ngDevMode ? [{ debugName: "cells" }] : []));
|
|
641
|
+
/** One entry per box; the source of truth, kept exactly {@link length} long. */
|
|
642
|
+
chars = signal([], ...(ngDevMode ? [{ debugName: "chars" }] : []));
|
|
643
|
+
cvaDisabled = signal(false, ...(ngDevMode ? [{ debugName: "cvaDisabled" }] : []));
|
|
644
|
+
indexes = computed(() => Array.from({ length: this.length() }, (_, i) => i), ...(ngDevMode ? [{ debugName: "indexes" }] : []));
|
|
645
|
+
isDisabled = computed(() => this.disabled() || this.cvaDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
|
|
646
|
+
describedBy = computed(() => {
|
|
647
|
+
if (this.error())
|
|
648
|
+
return `${this.groupId}-err`;
|
|
649
|
+
if (this.hint())
|
|
650
|
+
return `${this.groupId}-hint`;
|
|
651
|
+
return null;
|
|
652
|
+
}, ...(ngDevMode ? [{ debugName: "describedBy" }] : []));
|
|
653
|
+
cellClasses = computed(() => {
|
|
654
|
+
const parts = ['rounded-control border', SIZES$8[this.size()]];
|
|
655
|
+
parts.push(this.error()
|
|
656
|
+
? 'border-danger focus:border-danger focus:ring-2 focus:ring-danger/25'
|
|
657
|
+
: 'border-border text-ink focus:border-brand-500 focus:ring-2 focus:ring-brand-500/25');
|
|
658
|
+
if (this.isDisabled())
|
|
659
|
+
parts.push('opacity-60');
|
|
660
|
+
return parts.join(' ');
|
|
661
|
+
}, ...(ngDevMode ? [{ debugName: "cellClasses" }] : []));
|
|
662
|
+
constructor() {
|
|
663
|
+
// Autofocus once the boxes are in the DOM. afterRenderEffect re-runs on signal reads, but the
|
|
664
|
+
// guard keeps it to the first paint — refocusing on every value change would fight the user.
|
|
665
|
+
let focused = false;
|
|
666
|
+
afterRenderEffect(() => {
|
|
667
|
+
if (this.autoFocus() && !focused && !this.isDisabled()) {
|
|
668
|
+
this.cells()[0]?.nativeElement.focus();
|
|
669
|
+
focused = true;
|
|
670
|
+
}
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
// --- ControlValueAccessor -------------------------------------------------
|
|
674
|
+
onChange = () => { };
|
|
675
|
+
onTouched = () => { };
|
|
676
|
+
writeValue(value) {
|
|
677
|
+
// Programmatic set never emits — CVA writeValue must not call onChange.
|
|
678
|
+
this.chars.set(this.spread(value ?? ''));
|
|
679
|
+
}
|
|
680
|
+
registerOnChange(fn) {
|
|
681
|
+
this.onChange = fn;
|
|
682
|
+
}
|
|
683
|
+
registerOnTouched(fn) {
|
|
684
|
+
this.onTouched = fn;
|
|
685
|
+
}
|
|
686
|
+
setDisabledState(isDisabled) {
|
|
687
|
+
this.cvaDisabled.set(isDisabled);
|
|
688
|
+
}
|
|
689
|
+
// --- events ---------------------------------------------------------------
|
|
690
|
+
charAt(index) {
|
|
691
|
+
return this.chars()[index] ?? '';
|
|
692
|
+
}
|
|
693
|
+
onInput(event, index) {
|
|
694
|
+
const el = event.target;
|
|
695
|
+
const raw = el.value;
|
|
696
|
+
const digits = this.sanitize(raw);
|
|
697
|
+
if (digits.length === 0) {
|
|
698
|
+
if (raw.length === 0) {
|
|
699
|
+
// Genuinely emptied (cut, or a deletion the keydown handler did not catch) — clear the box.
|
|
700
|
+
this.setChar(index, '');
|
|
701
|
+
}
|
|
702
|
+
else {
|
|
703
|
+
// A rejected character (letter, symbol) — reassert the box's real content, since the
|
|
704
|
+
// [value] binding will not repaint an unchanged signal.
|
|
705
|
+
el.value = this.charAt(index);
|
|
706
|
+
}
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
if (digits.length > 1) {
|
|
710
|
+
// Fast typing or an autofill dropped several characters into one box — spread them.
|
|
711
|
+
this.fill(digits, index);
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
714
|
+
this.setChar(index, digits);
|
|
715
|
+
this.focusIndex(index + 1);
|
|
716
|
+
}
|
|
717
|
+
onKeydown(event, index) {
|
|
718
|
+
switch (event.key) {
|
|
719
|
+
case 'Backspace':
|
|
720
|
+
event.preventDefault();
|
|
721
|
+
if (this.charAt(index)) {
|
|
722
|
+
this.setChar(index, '');
|
|
723
|
+
}
|
|
724
|
+
else if (index > 0) {
|
|
725
|
+
this.setChar(index - 1, '');
|
|
726
|
+
this.focusIndex(index - 1);
|
|
727
|
+
}
|
|
728
|
+
break;
|
|
729
|
+
case 'ArrowLeft':
|
|
730
|
+
event.preventDefault();
|
|
731
|
+
this.focusIndex(index - 1);
|
|
732
|
+
break;
|
|
733
|
+
case 'ArrowRight':
|
|
734
|
+
event.preventDefault();
|
|
735
|
+
this.focusIndex(index + 1);
|
|
736
|
+
break;
|
|
737
|
+
case 'Delete':
|
|
738
|
+
event.preventDefault();
|
|
739
|
+
this.setChar(index, '');
|
|
740
|
+
break;
|
|
741
|
+
default:
|
|
742
|
+
break;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
onPaste(event, index) {
|
|
746
|
+
const digits = this.sanitize(event.clipboardData?.getData('text') ?? '');
|
|
747
|
+
if (!digits)
|
|
748
|
+
return;
|
|
749
|
+
event.preventDefault();
|
|
750
|
+
this.fill(digits, index);
|
|
751
|
+
}
|
|
752
|
+
onFocus(event) {
|
|
753
|
+
// Select the box's content so a keystroke overwrites rather than being rejected by maxlength.
|
|
754
|
+
event.target.select();
|
|
755
|
+
}
|
|
756
|
+
// --- internals ------------------------------------------------------------
|
|
757
|
+
sanitize(raw) {
|
|
758
|
+
return this.inputMode() === 'numeric'
|
|
759
|
+
? raw.replace(/\D/g, '')
|
|
760
|
+
: raw.replace(/[^A-Za-z0-9]/g, '');
|
|
761
|
+
}
|
|
762
|
+
/** Normalize any input string into an array exactly {@link length} long. */
|
|
763
|
+
spread(raw) {
|
|
764
|
+
const cleaned = this.sanitize(raw).slice(0, this.length());
|
|
765
|
+
return Array.from({ length: this.length() }, (_, i) => cleaned[i] ?? '');
|
|
766
|
+
}
|
|
767
|
+
setChar(index, value) {
|
|
768
|
+
const next = this.normalized();
|
|
769
|
+
next[index] = value;
|
|
770
|
+
this.commit(next);
|
|
771
|
+
}
|
|
772
|
+
/** Write `digits` across the boxes starting at `start`, then focus the next empty box. */
|
|
773
|
+
fill(digits, start) {
|
|
774
|
+
const next = this.normalized();
|
|
775
|
+
let cursor = start;
|
|
776
|
+
for (const ch of digits) {
|
|
777
|
+
if (cursor >= this.length())
|
|
778
|
+
break;
|
|
779
|
+
next[cursor] = ch;
|
|
780
|
+
cursor += 1;
|
|
781
|
+
}
|
|
782
|
+
this.commit(next);
|
|
783
|
+
this.focusIndex(Math.min(cursor, this.length() - 1));
|
|
784
|
+
}
|
|
785
|
+
commit(next) {
|
|
786
|
+
this.chars.set(next);
|
|
787
|
+
const value = next.join('');
|
|
788
|
+
this.onChange(value);
|
|
789
|
+
if (next.every((c) => c !== '')) {
|
|
790
|
+
this.completed.emit(value);
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
/** The current boxes as a fresh, correctly-sized array to mutate. */
|
|
794
|
+
normalized() {
|
|
795
|
+
const current = this.chars();
|
|
796
|
+
return Array.from({ length: this.length() }, (_, i) => current[i] ?? '');
|
|
797
|
+
}
|
|
798
|
+
focusIndex(index) {
|
|
799
|
+
const clamped = Math.max(0, Math.min(index, this.length() - 1));
|
|
800
|
+
const cell = this.cells()[clamped]?.nativeElement;
|
|
801
|
+
if (cell) {
|
|
802
|
+
cell.focus();
|
|
803
|
+
cell.select();
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsOtpInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
807
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsOtpInput, isStandalone: true, selector: "sds-otp-input", inputs: { length: { classPropertyName: "length", publicName: "length", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, inputMode: { classPropertyName: "inputMode", publicName: "inputMode", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, autoFocus: { classPropertyName: "autoFocus", publicName: "autoFocus", isSignal: true, isRequired: false, transformFunction: null }, cellLabel: { classPropertyName: "cellLabel", publicName: "cellLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { completed: "completed" }, host: { classAttribute: "block" }, providers: [
|
|
808
|
+
{
|
|
809
|
+
provide: NG_VALUE_ACCESSOR,
|
|
810
|
+
useExisting: forwardRef(() => SdsOtpInput),
|
|
811
|
+
multi: true,
|
|
812
|
+
},
|
|
813
|
+
], viewQueries: [{ propertyName: "cells", predicate: ["cell"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
814
|
+
@if (label()) {
|
|
815
|
+
<label [id]="groupId + '-label'" class="mb-1.5 block text-sm font-medium text-ink">
|
|
816
|
+
{{ label() }}
|
|
817
|
+
</label>
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
<div
|
|
821
|
+
class="flex items-center gap-2"
|
|
822
|
+
role="group"
|
|
823
|
+
[attr.aria-labelledby]="label() ? groupId + '-label' : null"
|
|
824
|
+
[attr.aria-label]="!label() && ariaLabel() ? ariaLabel() : null"
|
|
825
|
+
[attr.aria-describedby]="describedBy()"
|
|
826
|
+
>
|
|
827
|
+
@for (i of indexes(); track i) {
|
|
828
|
+
<input
|
|
829
|
+
#cell
|
|
830
|
+
type="text"
|
|
831
|
+
[attr.data-index]="i"
|
|
832
|
+
[inputMode]="inputMode()"
|
|
833
|
+
autocomplete="one-time-code"
|
|
834
|
+
maxlength="1"
|
|
835
|
+
[value]="charAt(i)"
|
|
836
|
+
[disabled]="isDisabled()"
|
|
837
|
+
[attr.aria-label]="cellLabel() + ' ' + (i + 1)"
|
|
838
|
+
[attr.aria-invalid]="error() ? 'true' : null"
|
|
839
|
+
class="bg-white text-center font-semibold tabular-nums outline-none transition-colors
|
|
840
|
+
disabled:cursor-not-allowed"
|
|
841
|
+
[class]="cellClasses()"
|
|
842
|
+
(input)="onInput($event, i)"
|
|
843
|
+
(keydown)="onKeydown($event, i)"
|
|
844
|
+
(paste)="onPaste($event, i)"
|
|
845
|
+
(focus)="onFocus($event)"
|
|
846
|
+
(blur)="onTouched()"
|
|
847
|
+
/>
|
|
848
|
+
}
|
|
849
|
+
</div>
|
|
850
|
+
|
|
851
|
+
@if (error()) {
|
|
852
|
+
<p [id]="groupId + '-err'" class="mt-1.5 text-xs font-medium text-danger">{{ error() }}</p>
|
|
853
|
+
} @else if (hint()) {
|
|
854
|
+
<p [id]="groupId + '-hint'" class="mt-1.5 text-xs text-ink-faint">{{ hint() }}</p>
|
|
855
|
+
}
|
|
856
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
857
|
+
}
|
|
858
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsOtpInput, decorators: [{
|
|
859
|
+
type: Component,
|
|
860
|
+
args: [{
|
|
861
|
+
selector: 'sds-otp-input',
|
|
862
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
863
|
+
providers: [
|
|
864
|
+
{
|
|
865
|
+
provide: NG_VALUE_ACCESSOR,
|
|
866
|
+
useExisting: forwardRef(() => SdsOtpInput),
|
|
867
|
+
multi: true,
|
|
868
|
+
},
|
|
869
|
+
],
|
|
870
|
+
host: { class: 'block' },
|
|
871
|
+
template: `
|
|
872
|
+
@if (label()) {
|
|
873
|
+
<label [id]="groupId + '-label'" class="mb-1.5 block text-sm font-medium text-ink">
|
|
874
|
+
{{ label() }}
|
|
875
|
+
</label>
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
<div
|
|
879
|
+
class="flex items-center gap-2"
|
|
880
|
+
role="group"
|
|
881
|
+
[attr.aria-labelledby]="label() ? groupId + '-label' : null"
|
|
882
|
+
[attr.aria-label]="!label() && ariaLabel() ? ariaLabel() : null"
|
|
883
|
+
[attr.aria-describedby]="describedBy()"
|
|
884
|
+
>
|
|
885
|
+
@for (i of indexes(); track i) {
|
|
886
|
+
<input
|
|
887
|
+
#cell
|
|
888
|
+
type="text"
|
|
889
|
+
[attr.data-index]="i"
|
|
890
|
+
[inputMode]="inputMode()"
|
|
891
|
+
autocomplete="one-time-code"
|
|
892
|
+
maxlength="1"
|
|
893
|
+
[value]="charAt(i)"
|
|
894
|
+
[disabled]="isDisabled()"
|
|
895
|
+
[attr.aria-label]="cellLabel() + ' ' + (i + 1)"
|
|
896
|
+
[attr.aria-invalid]="error() ? 'true' : null"
|
|
897
|
+
class="bg-white text-center font-semibold tabular-nums outline-none transition-colors
|
|
898
|
+
disabled:cursor-not-allowed"
|
|
899
|
+
[class]="cellClasses()"
|
|
900
|
+
(input)="onInput($event, i)"
|
|
901
|
+
(keydown)="onKeydown($event, i)"
|
|
902
|
+
(paste)="onPaste($event, i)"
|
|
903
|
+
(focus)="onFocus($event)"
|
|
904
|
+
(blur)="onTouched()"
|
|
905
|
+
/>
|
|
906
|
+
}
|
|
907
|
+
</div>
|
|
908
|
+
|
|
909
|
+
@if (error()) {
|
|
910
|
+
<p [id]="groupId + '-err'" class="mt-1.5 text-xs font-medium text-danger">{{ error() }}</p>
|
|
911
|
+
} @else if (hint()) {
|
|
912
|
+
<p [id]="groupId + '-hint'" class="mt-1.5 text-xs text-ink-faint">{{ hint() }}</p>
|
|
913
|
+
}
|
|
914
|
+
`,
|
|
915
|
+
}]
|
|
916
|
+
}], ctorParameters: () => [], propDecorators: { length: [{ type: i0.Input, args: [{ isSignal: true, alias: "length", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], inputMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputMode", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], autoFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoFocus", required: false }] }], cellLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellLabel", required: false }] }], completed: [{ type: i0.Output, args: ["completed"] }], cells: [{ type: i0.ViewChildren, args: ['cell', { isSignal: true }] }] } });
|
|
917
|
+
|
|
601
918
|
let nextId$9 = 0;
|
|
602
919
|
const SIZES$7 = {
|
|
603
920
|
sm: 'text-sm px-3 py-2',
|
|
@@ -7467,5 +7784,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
7467
7784
|
* Generated bundle index. Do not edit.
|
|
7468
7785
|
*/
|
|
7469
7786
|
|
|
7470
|
-
export { SDS_ICONS, SDS_PHONE_COUNTRIES, SdsAccordion, SdsAccordionContent, SdsAccordionHeader, SdsAccordionPanel, SdsAccordionStore, SdsAvatar, SdsBadge, SdsButton, SdsCalendar, SdsCard, SdsCheckbox, SdsDatePicker, SdsIcon, SdsInput, SdsMultiSelect, SdsNavGroup, SdsNavItem, SdsPaginator, SdsPhoneInput, SdsSelect, SdsShell, SdsSidebar, SdsTab, SdsTabList, SdsTabPanel, SdsTabPanels, SdsTable, SdsTableCell, SdsTableRowExpansion, SdsTabs, SdsTabsStore, SdsTextarea, SdsToggleSwitch, SdsTopbar, SidebarStore, addDays, addMonths, addMonthsKeepDay, formatDdMmYyyy, isOutOfRange, isSameDay, isoDay, sdsFormatNational, sdsMatchDialCode, sdsNormalizeSignificant, startOfDay, startOfMonth };
|
|
7787
|
+
export { SDS_ICONS, SDS_PHONE_COUNTRIES, SdsAccordion, SdsAccordionContent, SdsAccordionHeader, SdsAccordionPanel, SdsAccordionStore, SdsAvatar, SdsBadge, SdsButton, SdsCalendar, SdsCard, SdsCheckbox, SdsDatePicker, SdsIcon, SdsInput, SdsMultiSelect, SdsNavGroup, SdsNavItem, SdsOtpInput, SdsPaginator, SdsPhoneInput, SdsSelect, SdsShell, SdsSidebar, SdsTab, SdsTabList, SdsTabPanel, SdsTabPanels, SdsTable, SdsTableCell, SdsTableRowExpansion, SdsTabs, SdsTabsStore, SdsTextarea, SdsToggleSwitch, SdsTopbar, SidebarStore, addDays, addMonths, addMonthsKeepDay, formatDdMmYyyy, isOutOfRange, isSameDay, isoDay, sdsFormatNational, sdsMatchDialCode, sdsNormalizeSignificant, startOfDay, startOfMonth };
|
|
7471
7788
|
//# sourceMappingURL=besaitech-ng-design-system.mjs.map
|