sn-checkbox-x 0.0.1 → 0.0.2
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/fesm2022/sn-checkbox-x.mjs +85 -0
- package/fesm2022/sn-checkbox-x.mjs.map +1 -0
- package/package.json +14 -3
- package/types/sn-checkbox-x.d.ts +27 -0
- package/ng-package.json +0 -7
- package/src/lib/sn-checkbox-x.html +0 -20
- package/src/lib/sn-checkbox-x.scss +0 -96
- package/src/lib/sn-checkbox-x.spec.ts +0 -96
- package/src/lib/sn-checkbox-x.ts +0 -59
- package/src/public-api.ts +0 -5
- package/tsconfig.lib.json +0 -18
- package/tsconfig.lib.prod.json +0 -11
- package/tsconfig.spec.json +0 -14
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { EventEmitter, forwardRef, booleanAttribute, Output, Input, Component } from '@angular/core';
|
|
3
|
+
import * as i1 from '@angular/common';
|
|
4
|
+
import { CommonModule } from '@angular/common';
|
|
5
|
+
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
6
|
+
|
|
7
|
+
class SnCheckboxXComponent {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.id = '';
|
|
10
|
+
this.label = '';
|
|
11
|
+
this.name = '';
|
|
12
|
+
this.disabled = false;
|
|
13
|
+
this.indeterminate = false;
|
|
14
|
+
this.changed = new EventEmitter();
|
|
15
|
+
this.checked = false;
|
|
16
|
+
this.onChange = () => { };
|
|
17
|
+
this.onTouched = () => { };
|
|
18
|
+
}
|
|
19
|
+
onCheckboxChange(event) {
|
|
20
|
+
const target = event.target;
|
|
21
|
+
this.checked = target.checked;
|
|
22
|
+
this.indeterminate = false;
|
|
23
|
+
this.onChange(this.checked);
|
|
24
|
+
this.changed.emit(this.checked);
|
|
25
|
+
}
|
|
26
|
+
onBlur() {
|
|
27
|
+
this.onTouched();
|
|
28
|
+
}
|
|
29
|
+
// ControlValueAccessor implementation
|
|
30
|
+
writeValue(value) {
|
|
31
|
+
this.checked = value ?? false;
|
|
32
|
+
}
|
|
33
|
+
registerOnChange(fn) {
|
|
34
|
+
this.onChange = fn;
|
|
35
|
+
}
|
|
36
|
+
registerOnTouched(fn) {
|
|
37
|
+
this.onTouched = fn;
|
|
38
|
+
}
|
|
39
|
+
setDisabledState(isDisabled) {
|
|
40
|
+
this.disabled = isDisabled;
|
|
41
|
+
}
|
|
42
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SnCheckboxXComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
43
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "21.2.0", type: SnCheckboxXComponent, isStandalone: true, selector: "sn-checkbox-x", inputs: { id: "id", label: "label", name: "name", disabled: ["disabled", "disabled", booleanAttribute], indeterminate: ["indeterminate", "indeterminate", booleanAttribute] }, outputs: { changed: "changed" }, providers: [
|
|
44
|
+
{
|
|
45
|
+
provide: NG_VALUE_ACCESSOR,
|
|
46
|
+
useExisting: forwardRef(() => SnCheckboxXComponent),
|
|
47
|
+
multi: true,
|
|
48
|
+
},
|
|
49
|
+
], ngImport: i0, template: "<div class=\"sn-checkbox-wrapper\">\n <input\n type=\"checkbox\"\n class=\"sn-checkbox-input\"\n [id]=\"id\"\n [name]=\"name\"\n [checked]=\"checked\"\n [disabled]=\"disabled\"\n [indeterminate]=\"indeterminate\"\n (change)=\"onCheckboxChange($event)\"\n (blur)=\"onBlur()\"\n aria-role=\"checkbox\"\n [attr.aria-checked]=\"indeterminate ? 'mixed' : checked\"\n [attr.aria-label]=\"label\"\n />\n <label class=\"sn-checkbox-label\" [attr.for]=\"id\" *ngIf=\"label\">\n {{ label }}\n </label>\n</div>\n\n", styles: ["@charset \"UTF-8\";.sn-checkbox-wrapper{display:flex;align-items:center;gap:.5rem;-webkit-user-select:none;user-select:none}.sn-checkbox-input{width:1.25rem;height:1.25rem;cursor:pointer;appearance:none;border:2px solid #d1d5db;border-radius:.375rem;background-color:#fff;transition:all .2s ease-in-out}.sn-checkbox-input:hover:not(:disabled):not(:checked){border-color:#3b82f6;background-color:#f0f9ff}.sn-checkbox-input:checked{background-color:#3b82f6;border-color:#3b82f6;position:relative}.sn-checkbox-input:checked:hover:not(:disabled){background-color:#2563eb}.sn-checkbox-input:checked:after{content:\"\\2713\";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);color:#fff;font-size:.875rem;font-weight:700}.sn-checkbox-input:indeterminate{background-color:#3b82f6;border-color:#3b82f6;position:relative}.sn-checkbox-input:indeterminate:after{content:\"\\2212\";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);color:#fff;font-size:1rem;font-weight:700}.sn-checkbox-input:focus{outline:none;border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61a}.sn-checkbox-input:disabled{cursor:not-allowed;opacity:.5;background-color:#f3f4f6;border-color:#e5e7eb}.sn-checkbox-input:disabled:checked{background-color:#9ca3af;border-color:#9ca3af}.sn-checkbox-label{cursor:pointer;font-size:.875rem;line-height:1.25rem;color:#374151;transition:color .2s ease-in-out}.sn-checkbox-input:disabled~.sn-checkbox-label{opacity:.5;cursor:not-allowed}.sn-checkbox-label:hover{color:#1f2937}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
|
|
50
|
+
}
|
|
51
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SnCheckboxXComponent, decorators: [{
|
|
52
|
+
type: Component,
|
|
53
|
+
args: [{ selector: 'sn-checkbox-x', standalone: true, imports: [CommonModule], providers: [
|
|
54
|
+
{
|
|
55
|
+
provide: NG_VALUE_ACCESSOR,
|
|
56
|
+
useExisting: forwardRef(() => SnCheckboxXComponent),
|
|
57
|
+
multi: true,
|
|
58
|
+
},
|
|
59
|
+
], template: "<div class=\"sn-checkbox-wrapper\">\n <input\n type=\"checkbox\"\n class=\"sn-checkbox-input\"\n [id]=\"id\"\n [name]=\"name\"\n [checked]=\"checked\"\n [disabled]=\"disabled\"\n [indeterminate]=\"indeterminate\"\n (change)=\"onCheckboxChange($event)\"\n (blur)=\"onBlur()\"\n aria-role=\"checkbox\"\n [attr.aria-checked]=\"indeterminate ? 'mixed' : checked\"\n [attr.aria-label]=\"label\"\n />\n <label class=\"sn-checkbox-label\" [attr.for]=\"id\" *ngIf=\"label\">\n {{ label }}\n </label>\n</div>\n\n", styles: ["@charset \"UTF-8\";.sn-checkbox-wrapper{display:flex;align-items:center;gap:.5rem;-webkit-user-select:none;user-select:none}.sn-checkbox-input{width:1.25rem;height:1.25rem;cursor:pointer;appearance:none;border:2px solid #d1d5db;border-radius:.375rem;background-color:#fff;transition:all .2s ease-in-out}.sn-checkbox-input:hover:not(:disabled):not(:checked){border-color:#3b82f6;background-color:#f0f9ff}.sn-checkbox-input:checked{background-color:#3b82f6;border-color:#3b82f6;position:relative}.sn-checkbox-input:checked:hover:not(:disabled){background-color:#2563eb}.sn-checkbox-input:checked:after{content:\"\\2713\";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);color:#fff;font-size:.875rem;font-weight:700}.sn-checkbox-input:indeterminate{background-color:#3b82f6;border-color:#3b82f6;position:relative}.sn-checkbox-input:indeterminate:after{content:\"\\2212\";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);color:#fff;font-size:1rem;font-weight:700}.sn-checkbox-input:focus{outline:none;border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61a}.sn-checkbox-input:disabled{cursor:not-allowed;opacity:.5;background-color:#f3f4f6;border-color:#e5e7eb}.sn-checkbox-input:disabled:checked{background-color:#9ca3af;border-color:#9ca3af}.sn-checkbox-label{cursor:pointer;font-size:.875rem;line-height:1.25rem;color:#374151;transition:color .2s ease-in-out}.sn-checkbox-input:disabled~.sn-checkbox-label{opacity:.5;cursor:not-allowed}.sn-checkbox-label:hover{color:#1f2937}\n"] }]
|
|
60
|
+
}], propDecorators: { id: [{
|
|
61
|
+
type: Input
|
|
62
|
+
}], label: [{
|
|
63
|
+
type: Input
|
|
64
|
+
}], name: [{
|
|
65
|
+
type: Input
|
|
66
|
+
}], disabled: [{
|
|
67
|
+
type: Input,
|
|
68
|
+
args: [{ transform: booleanAttribute }]
|
|
69
|
+
}], indeterminate: [{
|
|
70
|
+
type: Input,
|
|
71
|
+
args: [{ transform: booleanAttribute }]
|
|
72
|
+
}], changed: [{
|
|
73
|
+
type: Output
|
|
74
|
+
}] } });
|
|
75
|
+
|
|
76
|
+
/*
|
|
77
|
+
* Public API Surface of sn-checkbox-x
|
|
78
|
+
*/
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Generated bundle index. Do not edit.
|
|
82
|
+
*/
|
|
83
|
+
|
|
84
|
+
export { SnCheckboxXComponent };
|
|
85
|
+
//# sourceMappingURL=sn-checkbox-x.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sn-checkbox-x.mjs","sources":["../../../projects/sn-checkbox-x/src/lib/sn-checkbox-x.ts","../../../projects/sn-checkbox-x/src/lib/sn-checkbox-x.html","../../../projects/sn-checkbox-x/src/public-api.ts","../../../projects/sn-checkbox-x/src/sn-checkbox-x.ts"],"sourcesContent":["import { Component, Input, Output, EventEmitter, forwardRef, booleanAttribute } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\n\n@Component({\n selector: 'sn-checkbox-x',\n standalone: true,\n imports: [CommonModule],\n templateUrl: './sn-checkbox-x.html',\n styleUrl: './sn-checkbox-x.scss',\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => SnCheckboxXComponent),\n multi: true,\n },\n ],\n})\nexport class SnCheckboxXComponent implements ControlValueAccessor {\n @Input() id: string = '';\n @Input() label: string = '';\n @Input() name: string = '';\n @Input({ transform: booleanAttribute }) disabled: boolean = false;\n @Input({ transform: booleanAttribute }) indeterminate: boolean = false;\n @Output() changed = new EventEmitter<boolean>();\n\n checked: boolean = false;\n private onChange: (value: boolean) => void = () => {};\n private onTouched: () => void = () => {};\n\n onCheckboxChange(event: Event): void {\n const target = event.target as HTMLInputElement;\n this.checked = target.checked;\n this.indeterminate = false;\n this.onChange(this.checked);\n this.changed.emit(this.checked);\n }\n\n onBlur(): void {\n this.onTouched();\n }\n\n // ControlValueAccessor implementation\n writeValue(value: boolean): void {\n this.checked = value ?? false;\n }\n\n registerOnChange(fn: (value: boolean) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.disabled = isDisabled;\n }\n}\n","<div class=\"sn-checkbox-wrapper\">\n <input\n type=\"checkbox\"\n class=\"sn-checkbox-input\"\n [id]=\"id\"\n [name]=\"name\"\n [checked]=\"checked\"\n [disabled]=\"disabled\"\n [indeterminate]=\"indeterminate\"\n (change)=\"onCheckboxChange($event)\"\n (blur)=\"onBlur()\"\n aria-role=\"checkbox\"\n [attr.aria-checked]=\"indeterminate ? 'mixed' : checked\"\n [attr.aria-label]=\"label\"\n />\n <label class=\"sn-checkbox-label\" [attr.for]=\"id\" *ngIf=\"label\">\n {{ label }}\n </label>\n</div>\n\n","/*\n * Public API Surface of sn-checkbox-x\n */\n\nexport * from './lib/sn-checkbox-x';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sn-checkbox-x",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "Angular checkbox component with indeterminate state support - SnUI Library",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Swapnil Nakate",
|
|
@@ -34,5 +34,16 @@
|
|
|
34
34
|
"type": "git",
|
|
35
35
|
"directory": "projects/sn-checkbox"
|
|
36
36
|
},
|
|
37
|
-
"license": "MIT"
|
|
38
|
-
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"module": "fesm2022/sn-checkbox-x.mjs",
|
|
39
|
+
"typings": "types/sn-checkbox-x.d.ts",
|
|
40
|
+
"exports": {
|
|
41
|
+
"./package.json": {
|
|
42
|
+
"default": "./package.json"
|
|
43
|
+
},
|
|
44
|
+
".": {
|
|
45
|
+
"types": "./types/sn-checkbox-x.d.ts",
|
|
46
|
+
"default": "./fesm2022/sn-checkbox-x.mjs"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { EventEmitter } from '@angular/core';
|
|
3
|
+
import { ControlValueAccessor } from '@angular/forms';
|
|
4
|
+
|
|
5
|
+
declare class SnCheckboxXComponent implements ControlValueAccessor {
|
|
6
|
+
id: string;
|
|
7
|
+
label: string;
|
|
8
|
+
name: string;
|
|
9
|
+
disabled: boolean;
|
|
10
|
+
indeterminate: boolean;
|
|
11
|
+
changed: EventEmitter<boolean>;
|
|
12
|
+
checked: boolean;
|
|
13
|
+
private onChange;
|
|
14
|
+
private onTouched;
|
|
15
|
+
onCheckboxChange(event: Event): void;
|
|
16
|
+
onBlur(): void;
|
|
17
|
+
writeValue(value: boolean): void;
|
|
18
|
+
registerOnChange(fn: (value: boolean) => void): void;
|
|
19
|
+
registerOnTouched(fn: () => void): void;
|
|
20
|
+
setDisabledState(isDisabled: boolean): void;
|
|
21
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SnCheckboxXComponent, never>;
|
|
22
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SnCheckboxXComponent, "sn-checkbox-x", never, { "id": { "alias": "id"; "required": false; }; "label": { "alias": "label"; "required": false; }; "name": { "alias": "name"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "indeterminate": { "alias": "indeterminate"; "required": false; }; }, { "changed": "changed"; }, never, never, true, never>;
|
|
23
|
+
static ngAcceptInputType_disabled: unknown;
|
|
24
|
+
static ngAcceptInputType_indeterminate: unknown;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export { SnCheckboxXComponent };
|
package/ng-package.json
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
<div class="sn-checkbox-wrapper">
|
|
2
|
-
<input
|
|
3
|
-
type="checkbox"
|
|
4
|
-
class="sn-checkbox-input"
|
|
5
|
-
[id]="id"
|
|
6
|
-
[name]="name"
|
|
7
|
-
[checked]="checked"
|
|
8
|
-
[disabled]="disabled"
|
|
9
|
-
[indeterminate]="indeterminate"
|
|
10
|
-
(change)="onCheckboxChange($event)"
|
|
11
|
-
(blur)="onBlur()"
|
|
12
|
-
aria-role="checkbox"
|
|
13
|
-
[attr.aria-checked]="indeterminate ? 'mixed' : checked"
|
|
14
|
-
[attr.aria-label]="label"
|
|
15
|
-
/>
|
|
16
|
-
<label class="sn-checkbox-label" [attr.for]="id" *ngIf="label">
|
|
17
|
-
{{ label }}
|
|
18
|
-
</label>
|
|
19
|
-
</div>
|
|
20
|
-
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
.sn-checkbox-wrapper {
|
|
2
|
-
display: flex;
|
|
3
|
-
align-items: center;
|
|
4
|
-
gap: 0.5rem;
|
|
5
|
-
user-select: none;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
.sn-checkbox-input {
|
|
9
|
-
width: 1.25rem;
|
|
10
|
-
height: 1.25rem;
|
|
11
|
-
cursor: pointer;
|
|
12
|
-
appearance: none;
|
|
13
|
-
border: 2px solid #d1d5db;
|
|
14
|
-
border-radius: 0.375rem;
|
|
15
|
-
background-color: #ffffff;
|
|
16
|
-
transition: all 0.2s ease-in-out;
|
|
17
|
-
|
|
18
|
-
&:hover:not(:disabled):not(:checked) {
|
|
19
|
-
border-color: #3b82f6;
|
|
20
|
-
background-color: #f0f9ff;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
&:checked {
|
|
24
|
-
background-color: #3b82f6;
|
|
25
|
-
border-color: #3b82f6;
|
|
26
|
-
position: relative;
|
|
27
|
-
|
|
28
|
-
&:hover:not(:disabled) {
|
|
29
|
-
background-color: #2563eb;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
&::after {
|
|
33
|
-
content: '✓';
|
|
34
|
-
position: absolute;
|
|
35
|
-
top: 50%;
|
|
36
|
-
left: 50%;
|
|
37
|
-
transform: translate(-50%, -50%);
|
|
38
|
-
color: white;
|
|
39
|
-
font-size: 0.875rem;
|
|
40
|
-
font-weight: bold;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
&:indeterminate {
|
|
45
|
-
background-color: #3b82f6;
|
|
46
|
-
border-color: #3b82f6;
|
|
47
|
-
position: relative;
|
|
48
|
-
|
|
49
|
-
&::after {
|
|
50
|
-
content: '−';
|
|
51
|
-
position: absolute;
|
|
52
|
-
top: 50%;
|
|
53
|
-
left: 50%;
|
|
54
|
-
transform: translate(-50%, -50%);
|
|
55
|
-
color: white;
|
|
56
|
-
font-size: 1rem;
|
|
57
|
-
font-weight: bold;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
&:focus {
|
|
62
|
-
outline: none;
|
|
63
|
-
border-color: #3b82f6;
|
|
64
|
-
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
&:disabled {
|
|
68
|
-
cursor: not-allowed;
|
|
69
|
-
opacity: 0.5;
|
|
70
|
-
background-color: #f3f4f6;
|
|
71
|
-
border-color: #e5e7eb;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
&:disabled:checked {
|
|
75
|
-
background-color: #9ca3af;
|
|
76
|
-
border-color: #9ca3af;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
.sn-checkbox-label {
|
|
81
|
-
cursor: pointer;
|
|
82
|
-
font-size: 0.875rem;
|
|
83
|
-
line-height: 1.25rem;
|
|
84
|
-
color: #374151;
|
|
85
|
-
transition: color 0.2s ease-in-out;
|
|
86
|
-
|
|
87
|
-
.sn-checkbox-input:disabled ~ & {
|
|
88
|
-
opacity: 0.5;
|
|
89
|
-
cursor: not-allowed;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
&:hover {
|
|
93
|
-
color: #1f2937;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
-
import { SnCheckboxXComponent } from './sn-checkbox-x';
|
|
3
|
-
import { DebugElement } from '@angular/core';
|
|
4
|
-
import { By } from '@angular/platform-browser';
|
|
5
|
-
|
|
6
|
-
describe('SnCheckboxXComponent', () => {
|
|
7
|
-
let component: SnCheckboxXComponent;
|
|
8
|
-
let fixture: ComponentFixture<SnCheckboxXComponent>;
|
|
9
|
-
let inputElement: DebugElement;
|
|
10
|
-
|
|
11
|
-
beforeEach(async () => {
|
|
12
|
-
await TestBed.configureTestingModule({
|
|
13
|
-
imports: [SnCheckboxXComponent],
|
|
14
|
-
}).compileComponents();
|
|
15
|
-
|
|
16
|
-
fixture = TestBed.createComponent(SnCheckboxXComponent);
|
|
17
|
-
component = fixture.componentInstance;
|
|
18
|
-
fixture.detectChanges();
|
|
19
|
-
inputElement = fixture.debugElement.query(By.css('input[type="checkbox"]'));
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('should create', () => {
|
|
23
|
-
expect(component).toBeTruthy();
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('should toggle checkbox value on change', () => {
|
|
27
|
-
const spy = jasmine.createSpy('onChange');
|
|
28
|
-
component.registerOnChange(spy);
|
|
29
|
-
|
|
30
|
-
inputElement.nativeElement.click();
|
|
31
|
-
fixture.detectChanges();
|
|
32
|
-
|
|
33
|
-
expect(component.checked).toBe(true);
|
|
34
|
-
expect(spy).toHaveBeenCalledWith(true);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('should emit changed event on checkbox change', () => {
|
|
38
|
-
const spy = spyOn(component.changed, 'emit');
|
|
39
|
-
|
|
40
|
-
inputElement.nativeElement.click();
|
|
41
|
-
fixture.detectChanges();
|
|
42
|
-
|
|
43
|
-
expect(spy).toHaveBeenCalledWith(true);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it('should update checked value from writeValue', () => {
|
|
47
|
-
component.writeValue(true);
|
|
48
|
-
fixture.detectChanges();
|
|
49
|
-
|
|
50
|
-
expect(component.checked).toBe(true);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('should handle disabled state', () => {
|
|
54
|
-
component.setDisabledState(true);
|
|
55
|
-
fixture.detectChanges();
|
|
56
|
-
|
|
57
|
-
expect(component.disabled).toBe(true);
|
|
58
|
-
expect(inputElement.nativeElement.disabled).toBe(true);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('should set indeterminate state', () => {
|
|
62
|
-
component.indeterminate = true;
|
|
63
|
-
fixture.detectChanges();
|
|
64
|
-
|
|
65
|
-
expect(inputElement.nativeElement.indeterminate).toBe(true);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('should clear indeterminate state on checkbox change', () => {
|
|
69
|
-
component.indeterminate = true;
|
|
70
|
-
inputElement.nativeElement.click();
|
|
71
|
-
fixture.detectChanges();
|
|
72
|
-
|
|
73
|
-
expect(component.indeterminate).toBe(false);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('should display label when provided', () => {
|
|
77
|
-
component.label = 'Accept Terms';
|
|
78
|
-
component.id = 'accept-terms';
|
|
79
|
-
fixture.detectChanges();
|
|
80
|
-
|
|
81
|
-
const labelElement = fixture.debugElement.query(By.css('label'));
|
|
82
|
-
expect(labelElement).toBeTruthy();
|
|
83
|
-
expect(labelElement.nativeElement.textContent).toContain('Accept Terms');
|
|
84
|
-
expect(labelElement.nativeElement.getAttribute('for')).toBe('accept-terms');
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('should call onTouched on blur', () => {
|
|
88
|
-
const spy = jasmine.createSpy('onTouched');
|
|
89
|
-
component.registerOnTouched(spy);
|
|
90
|
-
|
|
91
|
-
inputElement.nativeElement.dispatchEvent(new Event('blur'));
|
|
92
|
-
fixture.detectChanges();
|
|
93
|
-
|
|
94
|
-
expect(spy).toHaveBeenCalled();
|
|
95
|
-
});
|
|
96
|
-
});
|
package/src/lib/sn-checkbox-x.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { Component, Input, Output, EventEmitter, forwardRef, booleanAttribute } from '@angular/core';
|
|
2
|
-
import { CommonModule } from '@angular/common';
|
|
3
|
-
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
4
|
-
|
|
5
|
-
@Component({
|
|
6
|
-
selector: 'sn-checkbox-x',
|
|
7
|
-
standalone: true,
|
|
8
|
-
imports: [CommonModule],
|
|
9
|
-
templateUrl: './sn-checkbox-x.html',
|
|
10
|
-
styleUrl: './sn-checkbox-x.scss',
|
|
11
|
-
providers: [
|
|
12
|
-
{
|
|
13
|
-
provide: NG_VALUE_ACCESSOR,
|
|
14
|
-
useExisting: forwardRef(() => SnCheckboxXComponent),
|
|
15
|
-
multi: true,
|
|
16
|
-
},
|
|
17
|
-
],
|
|
18
|
-
})
|
|
19
|
-
export class SnCheckboxXComponent implements ControlValueAccessor {
|
|
20
|
-
@Input() id: string = '';
|
|
21
|
-
@Input() label: string = '';
|
|
22
|
-
@Input() name: string = '';
|
|
23
|
-
@Input({ transform: booleanAttribute }) disabled: boolean = false;
|
|
24
|
-
@Input({ transform: booleanAttribute }) indeterminate: boolean = false;
|
|
25
|
-
@Output() changed = new EventEmitter<boolean>();
|
|
26
|
-
|
|
27
|
-
checked: boolean = false;
|
|
28
|
-
private onChange: (value: boolean) => void = () => {};
|
|
29
|
-
private onTouched: () => void = () => {};
|
|
30
|
-
|
|
31
|
-
onCheckboxChange(event: Event): void {
|
|
32
|
-
const target = event.target as HTMLInputElement;
|
|
33
|
-
this.checked = target.checked;
|
|
34
|
-
this.indeterminate = false;
|
|
35
|
-
this.onChange(this.checked);
|
|
36
|
-
this.changed.emit(this.checked);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
onBlur(): void {
|
|
40
|
-
this.onTouched();
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// ControlValueAccessor implementation
|
|
44
|
-
writeValue(value: boolean): void {
|
|
45
|
-
this.checked = value ?? false;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
registerOnChange(fn: (value: boolean) => void): void {
|
|
49
|
-
this.onChange = fn;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
registerOnTouched(fn: () => void): void {
|
|
53
|
-
this.onTouched = fn;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
setDisabledState(isDisabled: boolean): void {
|
|
57
|
-
this.disabled = isDisabled;
|
|
58
|
-
}
|
|
59
|
-
}
|
package/src/public-api.ts
DELETED
package/tsconfig.lib.json
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
|
2
|
-
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
|
3
|
-
{
|
|
4
|
-
"extends": "../../tsconfig.json",
|
|
5
|
-
"compilerOptions": {
|
|
6
|
-
"outDir": "../../out-tsc/lib",
|
|
7
|
-
"declaration": true,
|
|
8
|
-
"declarationMap": true,
|
|
9
|
-
"inlineSources": true,
|
|
10
|
-
"types": []
|
|
11
|
-
},
|
|
12
|
-
"include": [
|
|
13
|
-
"src/**/*.ts"
|
|
14
|
-
],
|
|
15
|
-
"exclude": [
|
|
16
|
-
"**/*.spec.ts"
|
|
17
|
-
]
|
|
18
|
-
}
|
package/tsconfig.lib.prod.json
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
|
2
|
-
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
|
3
|
-
{
|
|
4
|
-
"extends": "./tsconfig.lib.json",
|
|
5
|
-
"compilerOptions": {
|
|
6
|
-
"declarationMap": false
|
|
7
|
-
},
|
|
8
|
-
"angularCompilerOptions": {
|
|
9
|
-
"compilationMode": "partial"
|
|
10
|
-
}
|
|
11
|
-
}
|
package/tsconfig.spec.json
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
|
2
|
-
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
|
3
|
-
{
|
|
4
|
-
"extends": "../../tsconfig.json",
|
|
5
|
-
"compilerOptions": {
|
|
6
|
-
"outDir": "../../out-tsc/spec",
|
|
7
|
-
"types": [
|
|
8
|
-
"jasmine"
|
|
9
|
-
]
|
|
10
|
-
},
|
|
11
|
-
"include": [
|
|
12
|
-
"src/**/*.ts"
|
|
13
|
-
]
|
|
14
|
-
}
|