sn-toggle 0.0.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.
- package/ng-package.json +7 -0
- package/package.json +28 -0
- package/src/lib/sn-toggle.component.spec.ts +42 -0
- package/src/lib/sn-toggle.component.ts +26 -0
- package/src/lib/sn-toggle.html +18 -0
- package/src/lib/sn-toggle.scss +47 -0
- package/src/public-api.ts +1 -0
- package/tsconfig.lib.json +11 -0
- package/tsconfig.lib.prod.json +9 -0
- package/tsconfig.spec.json +8 -0
package/ng-package.json
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sn-toggle",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "SnToggle is an Angular 21 standalone toggle switch component",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Swapnil Nakate",
|
|
7
|
+
"email": "nakate.swapnil7@gmail.com",
|
|
8
|
+
"url": "https://swapnilnakate.in"
|
|
9
|
+
},
|
|
10
|
+
"peerDependencies": {
|
|
11
|
+
"@angular/common": "^21.0.0",
|
|
12
|
+
"@angular/core": "^21.0.0"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"tslib": "^2.3.0"
|
|
16
|
+
},
|
|
17
|
+
"sideEffects": false,
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/swapnilnakate7/sn-ui/issues",
|
|
20
|
+
"email": "nakate.swapnil7@gmail.com"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"url": "https://github.com/swapnilnakate7/sn-ui",
|
|
24
|
+
"type": "git",
|
|
25
|
+
"directory": "projects/sn-toggle"
|
|
26
|
+
},
|
|
27
|
+
"license": "MIT"
|
|
28
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
+
import { SnToggleComponent } from './sn-toggle.component';
|
|
3
|
+
|
|
4
|
+
describe('SnToggleComponent', () => {
|
|
5
|
+
let component: SnToggleComponent;
|
|
6
|
+
let fixture: ComponentFixture<SnToggleComponent>;
|
|
7
|
+
|
|
8
|
+
beforeEach(async () => {
|
|
9
|
+
await TestBed.configureTestingModule({
|
|
10
|
+
imports: [SnToggleComponent],
|
|
11
|
+
}).compileComponents();
|
|
12
|
+
|
|
13
|
+
fixture = TestBed.createComponent(SnToggleComponent);
|
|
14
|
+
component = fixture.componentInstance;
|
|
15
|
+
fixture.detectChanges();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should create', () => {
|
|
19
|
+
expect(component).toBeTruthy();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('should default checked to false', () => {
|
|
23
|
+
expect(component.checked).toBeFalse();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should default disabled to false', () => {
|
|
27
|
+
expect(component.disabled).toBeFalse();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should default scheme to "primary"', () => {
|
|
31
|
+
expect(component.scheme).toBe('primary');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should emit toggled with new value when onChange is called', () => {
|
|
35
|
+
let emittedValue: boolean | undefined;
|
|
36
|
+
component.toggled.subscribe((v: boolean) => (emittedValue = v));
|
|
37
|
+
const mockEvent = { target: { checked: true } } as unknown as Event;
|
|
38
|
+
component.onChange(mockEvent);
|
|
39
|
+
expect(component.checked).toBeTrue();
|
|
40
|
+
expect(emittedValue).toBeTrue();
|
|
41
|
+
});
|
|
42
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Component, EventEmitter, Input, Output, booleanAttribute } from '@angular/core';
|
|
2
|
+
import { CommonModule, NgClass } from '@angular/common';
|
|
3
|
+
|
|
4
|
+
@Component({
|
|
5
|
+
selector: 'sn-toggle',
|
|
6
|
+
standalone: true,
|
|
7
|
+
imports: [CommonModule, NgClass],
|
|
8
|
+
templateUrl: './sn-toggle.html',
|
|
9
|
+
styleUrl: 'sn-toggle.scss',
|
|
10
|
+
})
|
|
11
|
+
export class SnToggleComponent {
|
|
12
|
+
@Input({ transform: booleanAttribute }) checked: boolean = false;
|
|
13
|
+
@Input({ transform: booleanAttribute }) disabled: boolean = false;
|
|
14
|
+
@Input() label: string = '';
|
|
15
|
+
@Input() scheme: string = 'primary';
|
|
16
|
+
@Output() toggled = new EventEmitter<boolean>();
|
|
17
|
+
|
|
18
|
+
private static _idCounter = 0;
|
|
19
|
+
readonly inputId = `sn-toggle-${++SnToggleComponent._idCounter}`;
|
|
20
|
+
|
|
21
|
+
onChange(event: Event): void {
|
|
22
|
+
const input = event.target as HTMLInputElement;
|
|
23
|
+
this.checked = input.checked;
|
|
24
|
+
this.toggled.emit(this.checked);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<div class="sn-toggle-wrapper">
|
|
2
|
+
<input
|
|
3
|
+
type="checkbox"
|
|
4
|
+
class="sn-toggle-input"
|
|
5
|
+
[id]="inputId"
|
|
6
|
+
[checked]="checked"
|
|
7
|
+
[disabled]="disabled"
|
|
8
|
+
(change)="onChange($event)"
|
|
9
|
+
/>
|
|
10
|
+
<label [htmlFor]="inputId" class="sn-toggle-label" [ngClass]="'scheme-' + scheme">
|
|
11
|
+
<span class="sn-toggle-track">
|
|
12
|
+
<span class="sn-toggle-thumb"></span>
|
|
13
|
+
</span>
|
|
14
|
+
@if (label) {
|
|
15
|
+
<span class="sn-toggle-text">{{ label }}</span>
|
|
16
|
+
}
|
|
17
|
+
</label>
|
|
18
|
+
</div>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
@tailwind base;
|
|
2
|
+
@tailwind components;
|
|
3
|
+
@tailwind utilities;
|
|
4
|
+
|
|
5
|
+
.sn-toggle-wrapper {
|
|
6
|
+
@apply inline-flex items-center gap-2;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.sn-toggle-input {
|
|
10
|
+
@apply sr-only;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.sn-toggle-label {
|
|
14
|
+
@apply inline-flex items-center gap-2 cursor-pointer select-none;
|
|
15
|
+
|
|
16
|
+
&[class*="scheme-"] .sn-toggle-track { background-color: #d1d5db; }
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.sn-toggle-track {
|
|
20
|
+
@apply relative inline-flex items-center w-10 h-6 rounded-full transition-colors duration-200;
|
|
21
|
+
background-color: #d1d5db;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.sn-toggle-thumb {
|
|
25
|
+
@apply absolute left-1 w-4 h-4 bg-white rounded-full shadow transition-transform duration-200;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.sn-toggle-text {
|
|
29
|
+
@apply text-sm text-gray-700;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Move thumb when checked */
|
|
33
|
+
.sn-toggle-input:checked + .sn-toggle-label .sn-toggle-thumb {
|
|
34
|
+
transform: translateX(1rem);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* Scheme colours when checked */
|
|
38
|
+
.sn-toggle-input:checked + .sn-toggle-label.scheme-primary .sn-toggle-track { @apply bg-blue-500; }
|
|
39
|
+
.sn-toggle-input:checked + .sn-toggle-label.scheme-warn .sn-toggle-track { @apply bg-yellow-500; }
|
|
40
|
+
.sn-toggle-input:checked + .sn-toggle-label.scheme-danger .sn-toggle-track { @apply bg-red-500; }
|
|
41
|
+
.sn-toggle-input:checked + .sn-toggle-label.scheme-success .sn-toggle-track { @apply bg-green-500; }
|
|
42
|
+
.sn-toggle-input:checked + .sn-toggle-label.scheme-default .sn-toggle-track { @apply bg-gray-500; }
|
|
43
|
+
|
|
44
|
+
/* Disabled state */
|
|
45
|
+
.sn-toggle-input:disabled + .sn-toggle-label {
|
|
46
|
+
@apply opacity-50 cursor-not-allowed;
|
|
47
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './lib/sn-toggle.component';
|