Skip to content

Commit 54b8377

Browse files
committed
fix: remove consoles, docs, fix examples
1 parent d94db08 commit 54b8377

File tree

12 files changed

+169
-30
lines changed

12 files changed

+169
-30
lines changed

README.md

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ import { InputOTPComponent } from '@ngxpert/input-otp';
2020
@Component({
2121
selector: 'app-my-component',
2222
template: `
23-
<input-otp [maxLength]="6" [(ngModel)]="otpValue">
23+
<input-otp [maxLength]="6" [(ngModel)]="otpValue" #otpInput>
2424
<div style="display: flex;">
25-
@for (slot of otp.slots(); track $index) {
25+
@for (slot of otpInput.slots(); track $index) {
2626
<div>{{ slot.char }}</div>
2727
}
2828
</div>
@@ -43,11 +43,11 @@ export class MyComponent {
4343

4444
## Default example
4545

46-
The example below uses `tailwindcss` `tailwind-merge` `clsx`:
46+
The example below uses `tailwindcss` `tailwind-merge` `clsx`. You can see it online [here](https://ngxpert.github.io/input-otp/examples), code available [here](https://github.com/ngxpert/input-otp/tree/main/src/app/pages/examples/main).
4747

4848
### main.component
4949

50-
```tsx
50+
```ts
5151
import { Component } from '@angular/core';
5252
import { FormsModule } from '@angular/forms';
5353
import { InputOTPComponent } from '@ngxpert/input-otp';
@@ -64,23 +64,37 @@ import { FakeDashComponent } from './fake-components';
6464
#otp="inputOtp"
6565
>
6666
<div class="flex">
67-
@for (slot of otp.slots().slice(0, 3); track $index) {
67+
@for (
68+
slot of otp.slots().slice(0, 3);
69+
track $index;
70+
let first = $first;
71+
let last = $last
72+
) {
6873
<app-slot
6974
[isActive]="slot.isActive"
7075
[char]="slot.char"
7176
[placeholderChar]="slot.placeholderChar"
7277
[hasFakeCaret]="slot.hasFakeCaret"
78+
[first]="first"
79+
[last]="last"
7380
/>
7481
}
7582
</div>
7683
<app-fake-dash />
7784
<div class="flex">
78-
@for (slot of otp.slots().slice(3, 6); track $index + 3) {
85+
@for (
86+
slot of otp.slots().slice(3, 6);
87+
track $index + 3;
88+
let last = $last;
89+
let first = $first
90+
) {
7991
<app-slot
8092
[isActive]="slot.isActive"
8193
[char]="slot.char"
8294
[placeholderChar]="slot.placeholderChar"
8395
[hasFakeCaret]="slot.hasFakeCaret"
96+
[first]="first"
97+
[last]="last"
8498
/>
8599
}
86100
</div>
@@ -110,10 +124,12 @@ import { cn } from './utils';
110124
'relative w-10 h-14 text-[2rem]',
111125
'flex items-center justify-center',
112126
'transition-all duration-300',
113-
'border-border border-y border-r first:border-l first:rounded-l-md last:rounded-r-md',
127+
'border-y border-r',
114128
'group-hover:border-accent-foreground/20 group-focus-within:border-accent-foreground/20',
115129
'outline outline-0 outline-accent-foreground/20',
116-
{ 'outline-4 outline-accent-foreground': isActive }
130+
{ 'outline-4 outline-accent-foreground': isActive },
131+
{ 'border-l rounded-l-md': first },
132+
{ 'rounded-r-md': last }
117133
)
118134
"
119135
>
@@ -134,6 +150,8 @@ export class SlotComponent {
134150
@Input() char: string | null = null;
135151
@Input() placeholderChar: string | null = null;
136152
@Input() hasFakeCaret = false;
153+
@Input() first = false;
154+
@Input() last = false;
137155
cn = cn;
138156
}
139157

@@ -148,7 +166,7 @@ import { Component } from '@angular/core';
148166
selector: 'app-fake-dash',
149167
template: `
150168
<div class="flex w-10 justify-center items-center">
151-
<div class="w-3 h-1 rounded-full bg-border"></div>
169+
<div class="w-3 h-1 rounded-full bg-black/75"></div>
152170
</div>
153171
`,
154172
})
@@ -160,7 +178,7 @@ export class FakeDashComponent {}
160178
<div
161179
class="absolute pointer-events-none inset-0 flex items-center justify-center animate-caret-blink"
162180
>
163-
<div class="w-px h-8 bg-white"></div>
181+
<div class="w-[2px] h-8 bg-black/75"></div>
164182
</div>
165183
`,
166184
})
@@ -171,7 +189,6 @@ export class FakeCaretComponent {}
171189
### utils
172190

173191
```ts
174-
// Small utility to merge class names.
175192
import { clsx } from 'clsx';
176193
import { twMerge } from 'tailwind-merge';
177194

@@ -183,6 +200,27 @@ export function cn(...inputs: ClassValue[]) {
183200

184201
```
185202

203+
### styles
204+
205+
```css
206+
@import "tailwindcss";
207+
208+
@theme {
209+
--animate-caret-blink: caret-blink 1.2s ease-out infinite;
210+
@keyframes caret-blink {
211+
0%,
212+
70%,
213+
100% {
214+
opacity: 1;
215+
}
216+
20%,
217+
50% {
218+
opacity: 0;
219+
}
220+
}
221+
}
222+
```
223+
186224
## How it works
187225

188226
There's currently no native OTP/2FA/MFA input in HTML, which means people are either going with

projects/ngxpert/input-otp/src/lib/components/input-otp/input-otp.component.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,6 @@ export class InputOTPComponent
217217

218218
private valueOrFocusedChanged() {
219219
// Forcefully remove :autofill state
220-
console.log('valueOrFocusedChanged');
221220
this.inputRef()?.nativeElement?.dispatchEvent(new Event('input'));
222221

223222
// Update the selection state
@@ -443,7 +442,6 @@ export class InputOTPComponent
443442
}
444443

445444
private changeFocus(value: boolean) {
446-
console.log('changeFocus', value);
447445
this.isFocused.set(value);
448446
this.valueOrFocusedChanged();
449447
}

src/app/components/code/code.component.html

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,16 @@
99
@for (file of files; track file.fileName) {
1010
<mat-tab [label]="file.fileName">
1111
<ng-template mat-tab-label>{{ file.fileName }}</ng-template>
12-
<div
13-
[innerHTML]="
14-
file.content | codeHighlight: file.language | async | safeHtml
15-
"
16-
></div>
12+
<div class="relative">
13+
<span class="absolute top-2 right-2">
14+
<app-copy-button [textToCopy]="file.content" />
15+
</span>
16+
<div
17+
[innerHTML]="
18+
file.content | codeHighlight: file.language | async | safeHtml
19+
"
20+
></div>
21+
</div>
1722
</mat-tab>
1823
}
1924
</mat-tab-group>

src/app/components/code/code.component.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,17 @@ import { MatTabsModule } from '@angular/material/tabs';
1111
import { AsyncPipe } from '@angular/common';
1212
import { CodeHighlightPipe } from '../../shared/pipes/code-highlight.pipe';
1313
import { SafeHtmlPipe } from '../../shared/pipes/safe-html.pipe';
14-
14+
import { CopyButtonComponent } from '../copy-button/copy-button.component';
1515
@Component({
1616
selector: 'app-code',
1717
templateUrl: './code.component.html',
18-
imports: [MatTabsModule, AsyncPipe, CodeHighlightPipe, SafeHtmlPipe],
18+
imports: [
19+
MatTabsModule,
20+
AsyncPipe,
21+
CodeHighlightPipe,
22+
SafeHtmlPipe,
23+
CopyButtonComponent,
24+
],
1925
})
2026
export class CodeComponent {
2127
readonly files: { fileName: string; content: string; language: string }[] = [
@@ -43,5 +49,26 @@ ${fakeComponentsContent}`,
4349
${utilsContent}`,
4450
language: 'ts',
4551
},
52+
{
53+
fileName: 'styles.css',
54+
content: `
55+
@import "tailwindcss";
56+
57+
@theme {
58+
--animate-caret-blink: caret-blink 1.2s ease-out infinite;
59+
@keyframes caret-blink {
60+
0%,
61+
70%,
62+
100% {
63+
opacity: 1;
64+
}
65+
20%,
66+
50% {
67+
opacity: 0;
68+
}
69+
}
70+
}`,
71+
language: 'css',
72+
},
4673
];
4774
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<button
2+
appUiButton
3+
size="icon"
4+
variant="ghost"
5+
[cdkCopyToClipboard]="textToCopy"
6+
(cdkCopyToClipboardCopied)="copied()"
7+
>
8+
@if (isCopied) {
9+
<span class="text-muted-foreground material-symbols-outlined"> check </span>
10+
} @else {
11+
<span class="text-muted-foreground material-symbols-outlined">
12+
content_copy
13+
</span>
14+
}
15+
<span class="sr-only">Copy</span>
16+
</button>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Component, Input } from '@angular/core';
2+
import { ButtonDirective } from '../ui/button/button.component';
3+
import { CdkCopyToClipboard } from '@angular/cdk/clipboard';
4+
@Component({
5+
selector: 'app-copy-button',
6+
templateUrl: './copy-button.component.html',
7+
imports: [ButtonDirective, CdkCopyToClipboard],
8+
})
9+
export class CopyButtonComponent {
10+
@Input() textToCopy = '';
11+
isCopied = false;
12+
13+
copied() {
14+
this.isCopied = true;
15+
setTimeout(() => {
16+
this.isCopied = false;
17+
}, 2000);
18+
}
19+
}

src/app/components/showcase/showcase.component.html

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,39 @@
1313
name="otp"
1414
[disabled]="disabled()"
1515
>
16-
<div class="flex gap-2">
17-
@for (slot of otp.slots().slice(0, 3); track $index) {
16+
<div class="flex">
17+
@for (
18+
slot of otp.slots().slice(0, 3);
19+
track $index;
20+
let first = $first;
21+
let last = $last
22+
) {
1823
<app-slot
1924
[isActive]="slot.isActive"
2025
[char]="slot.char"
2126
[placeholderChar]="slot.placeholderChar"
2227
[hasFakeCaret]="slot.hasFakeCaret"
2328
[animateIdx]="$index"
29+
[first]="first"
30+
[last]="last"
2431
/>
2532
}
2633

2734
<app-fake-dash />
2835

29-
@for (slot of otp.slots().slice(3, 6); track $index + 3) {
36+
@for (
37+
slot of otp.slots().slice(3, 6);
38+
track $index + 3;
39+
let last = $last;
40+
let first = $first
41+
) {
3042
<app-slot
3143
[isActive]="slot.isActive"
3244
[char]="slot.char"
3345
[placeholderChar]="slot.placeholderChar"
3446
[hasFakeCaret]="slot.hasFakeCaret"
47+
[last]="last"
48+
[first]="first"
3549
/>
3650
}
3751
</div>

src/app/components/slot/slot.component.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
<div
22
[ngClass]="[
3-
'relative w-10 md:w-20 h-14 md:h-28 text-[2rem] md:text-[4rem] flex items-center justify-center border-border border-y border-r first:border-l first:rounded-l-md last:rounded-r-md transition-all [transition-duration:300ms] outline outline-0 outline-accent-foreground/20',
3+
'relative w-10 md:w-20 h-14 md:h-28 text-[2rem] md:text-[4rem] flex items-center justify-center border-border border-y border-r transition-all [transition-duration:300ms] outline outline-0 outline-accent-foreground/20',
44
'group-hover:border-accent-foreground/20 group-focus-within:!border-accent-foreground/50',
55
isActive ? 'outline-4 outline-accent-foreground' : '',
6+
first ? 'border-l rounded-l-md' : '',
7+
last ? 'rounded-r-md' : '',
68
]"
79
>
810
<div

src/app/components/slot/slot.component.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ export class SlotComponent implements SlotProps {
1313
@Input() char: string | null = null;
1414
@Input() placeholderChar: string | null = null;
1515
@Input() hasFakeCaret = false;
16+
@Input() first = false;
17+
@Input() last = false;
1618
private _animateIdx: number | undefined;
1719
willAnimateChar = false;
1820
willAnimateCaret = false;

src/app/pages/examples/main/fake-components.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Component } from '@angular/core';
44
selector: 'app-fake-dash',
55
template: `
66
<div class="flex w-10 justify-center items-center">
7-
<div class="w-3 h-1 rounded-full bg-border"></div>
7+
<div class="w-3 h-1 rounded-full bg-black/75"></div>
88
</div>
99
`,
1010
})
@@ -16,7 +16,7 @@ export class FakeDashComponent {}
1616
<div
1717
class="absolute pointer-events-none inset-0 flex items-center justify-center animate-caret-blink"
1818
>
19-
<div class="w-px h-8 bg-white"></div>
19+
<div class="w-[2px] h-8 bg-black/75"></div>
2020
</div>
2121
`,
2222
})

0 commit comments

Comments
 (0)