everipackage-reusable-components 1.0.0

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/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # ReusableComponents
2
+
3
+ This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 21.1.0.
4
+
5
+ ## Code scaffolding
6
+
7
+ Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
8
+
9
+ ```bash
10
+ ng generate component component-name
11
+ ```
12
+
13
+ For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
14
+
15
+ ```bash
16
+ ng generate --help
17
+ ```
18
+
19
+ ## Building
20
+
21
+ To build the library, run:
22
+
23
+ ```bash
24
+ ng build reusable-components
25
+ ```
26
+
27
+ This command will compile your project, and the build artifacts will be placed in the `dist/` directory.
28
+
29
+ ### Publishing the Library
30
+
31
+ Once the project is built, you can publish your library by following these steps:
32
+
33
+ 1. Navigate to the `dist` directory:
34
+ ```bash
35
+ cd dist/reusable-components
36
+ ```
37
+
38
+ 2. Run the `npm publish` command to publish your library to the npm registry:
39
+ ```bash
40
+ npm publish
41
+ ```
42
+
43
+ ## Running unit tests
44
+
45
+ To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
46
+
47
+ ```bash
48
+ ng test
49
+ ```
50
+
51
+ ## Running end-to-end tests
52
+
53
+ For end-to-end (e2e) testing, run:
54
+
55
+ ```bash
56
+ ng e2e
57
+ ```
58
+
59
+ Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
60
+
61
+ ## Additional Resources
62
+
63
+ For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
@@ -0,0 +1,485 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, Component, signal, EventEmitter, Output, Input, Directive, HostListener } from '@angular/core';
3
+ import * as i1 from 'ng-primitives/button';
4
+ import { NgpButton } from 'ng-primitives/button';
5
+ import { NgFor, NgIf } from '@angular/common';
6
+
7
+ class Button {
8
+ /**
9
+ * The size of the button.
10
+ */
11
+ size = input("md", ...(ngDevMode ? [{ debugName: "size" }] : []));
12
+ /**
13
+ * The variant of the button.
14
+ */
15
+ variant = input("primary", ...(ngDevMode ? [{ debugName: "variant" }] : []));
16
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: Button, deps: [], target: i0.ɵɵFactoryTarget.Component });
17
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.2", type: Button, isStandalone: true, selector: "button[app-button]", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-size": "size()", "attr.data-variant": "variant()" } }, hostDirectives: [{ directive: i1.NgpButton, inputs: ["disabled", "disabled"] }], ngImport: i0, template: `
18
+ <ng-content />
19
+ `, isInline: true, styles: [":host{border:none;border-radius:var(--radiusRound);width:100%;max-width:var(--width400);display:flex;align-items:center;justify-content:center;font-family:var(--fontFamily);font-weight:var(--semi);line-height:var(--line-height-large);cursor:pointer}:host[data-hover]{background-color:var(--ngp-background-hover)}:host[data-focus-visible]{outline:2px solid var(--ngp-focus-ring)}:host[data-press]{background-color:var(--ngp-background-active)}:host[data-size=sm]{font-size:var(--fontSize12);height:var(--height-height28, 28px);padding:var(--space0, 0) var(--space12, 12px)}:host[data-size=md],:host:not([data-size]){font-size:var(--fontSize14);height:var(--height-height36, 36px);padding:var(--space4, 4px) var(--space16, 16px)}:host[data-size=lg]{font-size:var(--fontSize16);height:var(--height-height48, 48px);padding:var(--space12, 12px) var(--space16, 16px)}:host[data-size=xl]{height:3.5rem;padding-left:1.5rem;padding-right:1.5rem;font-size:1.125rem;--ng-icon__size: 1.125rem}:host[data-variant=primary],:host:not([data-variant]){background-color:var(--button-primary-background-color);color:var(--button-primary-font-color)}:host[data-variant=primary][data-hover],:host:not([data-variant])[data-hover]{background-color:var(--button-primary-background-color)}:host[data-variant=primary][data-press],:host:not([data-variant])[data-press]{background-color:var(--button-primary-background-color)}:host[data-variant=secondary]{background-color:var(--button-secondary-background-color);color:var(--button-secondary-font-color);border:1px solid var(--button-secondary-border-color, var(--accent-color))}:host[data-variant=secondary][data-hover]{background-color:var(--button-secondary-background-color)}:host[data-variant=secondary][data-press]{background-color:var(--button-secondary-background-color)}:host[data-variant=destructive]{background-color:var(--ngp-destructive-background, #ef4444);color:var(--ngp-destructive-text, #ffffff);border:none}:host[data-variant=destructive][data-hover]{background-color:var(--ngp-destructive-background-hover, #dc2626)}:host[data-variant=destructive][data-press]{background-color:var(--ngp-destructive-background-active, #b91c1c)}:host[data-variant=outline]{background-color:transparent;color:var(--ngp-text-primary);border:1px solid var(--ngp-outline-border, #e2e8f0);box-shadow:none}:host[data-variant=outline][data-hover]{background-color:var(--ngp-background-hover);border-color:var(--ngp-outline-border-hover, #cbd5e1)}:host[data-variant=outline][data-press]{background-color:var( --ngp-outline-background-active, rgba(15, 23, 42, .1) )}:host[data-variant=ghost]{background-color:transparent;color:var(--ngp-text-primary);border:none;box-shadow:none}:host[data-variant=ghost][data-hover]{background-color:var(--ngp-background-hover)}:host[data-variant=ghost][data-press]{background-color:var(--ngp-background-active)}:host[data-variant=link]{background-color:transparent;color:var(--ngp-link-color, #3b82f6);border:none;box-shadow:none;text-decoration:underline;text-underline-offset:4px}:host[data-variant=link][data-hover]{text-decoration-thickness:2px}:host[data-variant=primary]:host[disabled]{background-color:var(--button-primary-disabled-background-color);cursor:not-allowed}:host[data-variant=secondary]:host[disabled]{background-color:var(--button-secondary-disabled-background-color);cursor:not-allowed}\n"] });
20
+ }
21
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: Button, decorators: [{
22
+ type: Component,
23
+ args: [{ selector: "button[app-button]", hostDirectives: [{ directive: NgpButton, inputs: ["disabled"] }], template: `
24
+ <ng-content />
25
+ `, host: {
26
+ "[attr.data-size]": "size()",
27
+ "[attr.data-variant]": "variant()",
28
+ }, styles: [":host{border:none;border-radius:var(--radiusRound);width:100%;max-width:var(--width400);display:flex;align-items:center;justify-content:center;font-family:var(--fontFamily);font-weight:var(--semi);line-height:var(--line-height-large);cursor:pointer}:host[data-hover]{background-color:var(--ngp-background-hover)}:host[data-focus-visible]{outline:2px solid var(--ngp-focus-ring)}:host[data-press]{background-color:var(--ngp-background-active)}:host[data-size=sm]{font-size:var(--fontSize12);height:var(--height-height28, 28px);padding:var(--space0, 0) var(--space12, 12px)}:host[data-size=md],:host:not([data-size]){font-size:var(--fontSize14);height:var(--height-height36, 36px);padding:var(--space4, 4px) var(--space16, 16px)}:host[data-size=lg]{font-size:var(--fontSize16);height:var(--height-height48, 48px);padding:var(--space12, 12px) var(--space16, 16px)}:host[data-size=xl]{height:3.5rem;padding-left:1.5rem;padding-right:1.5rem;font-size:1.125rem;--ng-icon__size: 1.125rem}:host[data-variant=primary],:host:not([data-variant]){background-color:var(--button-primary-background-color);color:var(--button-primary-font-color)}:host[data-variant=primary][data-hover],:host:not([data-variant])[data-hover]{background-color:var(--button-primary-background-color)}:host[data-variant=primary][data-press],:host:not([data-variant])[data-press]{background-color:var(--button-primary-background-color)}:host[data-variant=secondary]{background-color:var(--button-secondary-background-color);color:var(--button-secondary-font-color);border:1px solid var(--button-secondary-border-color, var(--accent-color))}:host[data-variant=secondary][data-hover]{background-color:var(--button-secondary-background-color)}:host[data-variant=secondary][data-press]{background-color:var(--button-secondary-background-color)}:host[data-variant=destructive]{background-color:var(--ngp-destructive-background, #ef4444);color:var(--ngp-destructive-text, #ffffff);border:none}:host[data-variant=destructive][data-hover]{background-color:var(--ngp-destructive-background-hover, #dc2626)}:host[data-variant=destructive][data-press]{background-color:var(--ngp-destructive-background-active, #b91c1c)}:host[data-variant=outline]{background-color:transparent;color:var(--ngp-text-primary);border:1px solid var(--ngp-outline-border, #e2e8f0);box-shadow:none}:host[data-variant=outline][data-hover]{background-color:var(--ngp-background-hover);border-color:var(--ngp-outline-border-hover, #cbd5e1)}:host[data-variant=outline][data-press]{background-color:var( --ngp-outline-background-active, rgba(15, 23, 42, .1) )}:host[data-variant=ghost]{background-color:transparent;color:var(--ngp-text-primary);border:none;box-shadow:none}:host[data-variant=ghost][data-hover]{background-color:var(--ngp-background-hover)}:host[data-variant=ghost][data-press]{background-color:var(--ngp-background-active)}:host[data-variant=link]{background-color:transparent;color:var(--ngp-link-color, #3b82f6);border:none;box-shadow:none;text-decoration:underline;text-underline-offset:4px}:host[data-variant=link][data-hover]{text-decoration-thickness:2px}:host[data-variant=primary]:host[disabled]{background-color:var(--button-primary-disabled-background-color);cursor:not-allowed}:host[data-variant=secondary]:host[disabled]{background-color:var(--button-secondary-disabled-background-color);cursor:not-allowed}\n"] }]
29
+ }], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }] } });
30
+
31
+ class InputComponent {
32
+ /**
33
+ * The floating label text.
34
+ */
35
+ label = input("Label", ...(ngDevMode ? [{ debugName: "label" }] : []));
36
+ /**
37
+ * Optional placeholder (kept for accessibility, primary label floats).
38
+ */
39
+ placeholder = input("", ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
40
+ /**
41
+ * Internal value signal for the input's value.
42
+ */
43
+ value = signal("", ...(ngDevMode ? [{ debugName: "value" }] : []));
44
+ /**
45
+ * Focus state signal used to float the label when focused.
46
+ */
47
+ focused = signal(false, ...(ngDevMode ? [{ debugName: "focused" }] : []));
48
+ onInput(e) {
49
+ const target = e.target;
50
+ this.value.set(target.value);
51
+ }
52
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: InputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
53
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.2", type: InputComponent, isStandalone: true, selector: "app-input", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
54
+ <label class="ngp-field">
55
+ <input
56
+ type="text"
57
+ [value]="value()"
58
+ (input)="onInput($event)"
59
+ (focus)="focused.set(true)"
60
+ (blur)="focused.set(false)"
61
+ class="ngp-input"
62
+ [attr.placeholder]="placeholder()"
63
+ />
64
+ <span class="ngp-label" [attr.data-active]="(value() || focused()) ? '' : null">{{ label() }}</span>
65
+ </label>
66
+ `, isInline: true, styles: [":host{display:block;width:100%;max-width:var(--width400);font-family:var(--fontFamily)}.ngp-field{position:relative;display:block}.ngp-input{width:100%;padding:1rem .75rem .5rem;font-size:var(--fontSize14, 14px);border:1px solid var(--ngp-outline-border, #e2e8f0);border-radius:8px;background:var(--ngp-input-background, #fff);box-sizing:border-box;transition:border-color .12s ease,box-shadow .12s ease,background .12s ease}.ngp-input:hover{border-color:var(--ngp-outline-border-hover, #cbd5e1)}.ngp-input:focus{outline:none;border-color:var(--shuttleGray);box-shadow:0 0 0 4px #3b82f614}.ngp-input:disabled{background:var(--ngp-disabled-background, #f8fafc);color:var(--ngp-text-muted, #9ca3af);cursor:not-allowed}.ngp-label{position:absolute;left:.75rem;top:.8rem;transform-origin:left top;transition:transform .12s ease,top .12s ease,font-size .12s ease,color .12s ease;color:var(--ngp-text-muted, #6b7280);pointer-events:none;background:transparent;padding:0 .125rem;font-weight:500}.ngp-label[data-active]{transform:translateY(-.85rem) scale(.82);top:.9rem;font-weight:600;color:var(--midnightGray);background:transparent}:host([data-invalid]) .ngp-input,.ngp-field[data-invalid] .ngp-input{border-color:var(--ngp-destructive-background, #ef4444)}:host([data-invalid]) .ngp-label,.ngp-field[data-invalid] .ngp-label{color:var(--ngp-destructive-background, #ef4444)}\n"] });
67
+ }
68
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: InputComponent, decorators: [{
69
+ type: Component,
70
+ args: [{ selector: 'app-input', template: `
71
+ <label class="ngp-field">
72
+ <input
73
+ type="text"
74
+ [value]="value()"
75
+ (input)="onInput($event)"
76
+ (focus)="focused.set(true)"
77
+ (blur)="focused.set(false)"
78
+ class="ngp-input"
79
+ [attr.placeholder]="placeholder()"
80
+ />
81
+ <span class="ngp-label" [attr.data-active]="(value() || focused()) ? '' : null">{{ label() }}</span>
82
+ </label>
83
+ `, styles: [":host{display:block;width:100%;max-width:var(--width400);font-family:var(--fontFamily)}.ngp-field{position:relative;display:block}.ngp-input{width:100%;padding:1rem .75rem .5rem;font-size:var(--fontSize14, 14px);border:1px solid var(--ngp-outline-border, #e2e8f0);border-radius:8px;background:var(--ngp-input-background, #fff);box-sizing:border-box;transition:border-color .12s ease,box-shadow .12s ease,background .12s ease}.ngp-input:hover{border-color:var(--ngp-outline-border-hover, #cbd5e1)}.ngp-input:focus{outline:none;border-color:var(--shuttleGray);box-shadow:0 0 0 4px #3b82f614}.ngp-input:disabled{background:var(--ngp-disabled-background, #f8fafc);color:var(--ngp-text-muted, #9ca3af);cursor:not-allowed}.ngp-label{position:absolute;left:.75rem;top:.8rem;transform-origin:left top;transition:transform .12s ease,top .12s ease,font-size .12s ease,color .12s ease;color:var(--ngp-text-muted, #6b7280);pointer-events:none;background:transparent;padding:0 .125rem;font-weight:500}.ngp-label[data-active]{transform:translateY(-.85rem) scale(.82);top:.9rem;font-weight:600;color:var(--midnightGray);background:transparent}:host([data-invalid]) .ngp-input,.ngp-field[data-invalid] .ngp-input{border-color:var(--ngp-destructive-background, #ef4444)}:host([data-invalid]) .ngp-label,.ngp-field[data-invalid] .ngp-label{color:var(--ngp-destructive-background, #ef4444)}\n"] }]
84
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }] } });
85
+
86
+ /**
87
+ * Simple select/dropdown component with floating label behavior similar to the input.
88
+ * Accepts `options` as an array of strings or objects { value, label }.
89
+ */
90
+ class SelectComponent {
91
+ label = input('Select', ...(ngDevMode ? [{ debugName: "label" }] : []));
92
+ placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
93
+ /** Accepts Array<string> or Array<{value,label}> */
94
+ options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
95
+ value = signal('', ...(ngDevMode ? [{ debugName: "value" }] : []));
96
+ onChange(e) {
97
+ const target = e.target;
98
+ const v = target.value;
99
+ this.value.set(v);
100
+ }
101
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: SelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
102
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.2", type: SelectComponent, isStandalone: true, selector: "app-select", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
103
+ <label class="ngp-field">
104
+ <select
105
+ class="ngp-select"
106
+ (change)="onChange($event)"
107
+ [value]="value()"
108
+ >
109
+ <!-- placeholder option shown inside the native select when no value is selected; fall back to label text -->
110
+ <option *ngIf="(placeholder() || label())" value="">{{ placeholder() || label() }}</option>
111
+ <option *ngFor="let opt of options()" [value]="opt.value ?? opt">{{ opt.label ?? opt }}</option>
112
+ </select>
113
+ <!-- floating label is hidden by default; it becomes visible only when a value exists -->
114
+ <!-- <span class="ngp-label" [attr.data-active]="(value()) ? '' : null">{{ label() }}</span> -->
115
+ </label>
116
+ `, isInline: true, styles: [":host{display:block;width:100%;max-width:var(--width400);font-family:var(--fontFamily)}.ngp-field{position:relative}.ngp-select{width:100%;padding:.875rem .75rem .5rem;font-size:var(--fontSize14, 14px);border:1px solid var(--ngp-outline-border, #e2e8f0);border-radius:8px;box-sizing:border-box;color:var(--shuttleGray);display:inline-flex;flex-direction:column;align-items:center;gap:var(--space16, 16px)}option{background-color:violet}.ngp-select:focus{outline:none;border-color:var(--shuttleGray);box-shadow:0 0 0 4px #3b82f614}// .ngp-label{// position: absolute;// left: .75rem;// top: .85rem;// transform-origin: left top;// transition: transform .12s ease,top .12s ease,font-size .12s ease;// color: var(--ngp-text-muted, #6b7280);// pointer-events: none;// padding: 0 .125rem;// font-weight: 500;//}// .ngp-label[data-active]{// transform: translateY(-.85rem) scale(.82);// top: .45rem;// font-weight: 600;// color: var(--accent-color, #3b82f6);//}\n"], dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
117
+ }
118
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: SelectComponent, decorators: [{
119
+ type: Component,
120
+ args: [{ standalone: true, imports: [NgFor, NgIf], selector: 'app-select', template: `
121
+ <label class="ngp-field">
122
+ <select
123
+ class="ngp-select"
124
+ (change)="onChange($event)"
125
+ [value]="value()"
126
+ >
127
+ <!-- placeholder option shown inside the native select when no value is selected; fall back to label text -->
128
+ <option *ngIf="(placeholder() || label())" value="">{{ placeholder() || label() }}</option>
129
+ <option *ngFor="let opt of options()" [value]="opt.value ?? opt">{{ opt.label ?? opt }}</option>
130
+ </select>
131
+ <!-- floating label is hidden by default; it becomes visible only when a value exists -->
132
+ <!-- <span class="ngp-label" [attr.data-active]="(value()) ? '' : null">{{ label() }}</span> -->
133
+ </label>
134
+ `, styles: [":host{display:block;width:100%;max-width:var(--width400);font-family:var(--fontFamily)}.ngp-field{position:relative}.ngp-select{width:100%;padding:.875rem .75rem .5rem;font-size:var(--fontSize14, 14px);border:1px solid var(--ngp-outline-border, #e2e8f0);border-radius:8px;box-sizing:border-box;color:var(--shuttleGray);display:inline-flex;flex-direction:column;align-items:center;gap:var(--space16, 16px)}option{background-color:violet}.ngp-select:focus{outline:none;border-color:var(--shuttleGray);box-shadow:0 0 0 4px #3b82f614}// .ngp-label{// position: absolute;// left: .75rem;// top: .85rem;// transform-origin: left top;// transition: transform .12s ease,top .12s ease,font-size .12s ease;// color: var(--ngp-text-muted, #6b7280);// pointer-events: none;// padding: 0 .125rem;// font-weight: 500;//}// .ngp-label[data-active]{// transform: translateY(-.85rem) scale(.82);// top: .45rem;// font-weight: 600;// color: var(--accent-color, #3b82f6);//}\n"] }]
135
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }] } });
136
+
137
+ class PinEntryDirective {
138
+ el;
139
+ renderer;
140
+ length = 4; // default 4 digits
141
+ theme = 'light'; // theme switch
142
+ pinEntered = new EventEmitter();
143
+ svgCircles = [];
144
+ values = [];
145
+ constructor(el, renderer) {
146
+ this.el = el;
147
+ this.renderer = renderer;
148
+ }
149
+ ngOnInit() {
150
+ // Inject directive-specific CSS once
151
+ this.injectStyles();
152
+ const parent = this.renderer.createElement('div');
153
+ this.renderer.addClass(parent, 'pin-svg-container');
154
+ this.renderer.addClass(parent, this.theme === 'dark' ? 'dark-theme' : 'light-theme');
155
+ // Remove original input
156
+ const originalInput = this.el.nativeElement;
157
+ this.renderer.insertBefore(originalInput.parentNode, parent, originalInput);
158
+ this.renderer.removeChild(originalInput.parentNode, originalInput);
159
+ // Hidden input to capture actual value
160
+ const hiddenInput = this.renderer.createElement('input');
161
+ this.renderer.setAttribute(hiddenInput, 'type', 'tel');
162
+ this.renderer.setStyle(hiddenInput, 'opacity', '0');
163
+ this.renderer.setStyle(hiddenInput, 'position', 'absolute');
164
+ this.renderer.setStyle(hiddenInput, 'pointer-events', 'none');
165
+ this.renderer.appendChild(parent, hiddenInput);
166
+ // Create SVG circles
167
+ for (let i = 0; i < this.length; i++) {
168
+ const svg = this.renderer.createElement('svg', 'svg');
169
+ this.renderer.setAttribute(svg, 'xmlns', 'http://www.w3.org/2000/svg');
170
+ this.renderer.setAttribute(svg, 'width', '40');
171
+ this.renderer.setAttribute(svg, 'height', '40');
172
+ this.renderer.setAttribute(svg, 'viewBox', '0 0 24 24');
173
+ const circle = this.renderer.createElement('circle', 'svg');
174
+ this.renderer.setAttribute(circle, 'cx', '12');
175
+ this.renderer.setAttribute(circle, 'cy', '12');
176
+ this.renderer.setAttribute(circle, 'r', '9.5');
177
+ // Stroke color depends on theme
178
+ this.renderer.setAttribute(circle, 'stroke', this.theme === 'dark' ? 'white' : 'black');
179
+ this.renderer.setAttribute(circle, 'fill', 'transparent');
180
+ this.renderer.appendChild(svg, circle);
181
+ this.renderer.addClass(svg, 'pin-svg');
182
+ this.renderer.appendChild(parent, svg);
183
+ this.svgCircles.push(svg);
184
+ }
185
+ // Listen for input
186
+ this.renderer.listen(hiddenInput, 'input', (event) => {
187
+ const val = event.target.value.replace(/\D/g, '').slice(0, this.length);
188
+ this.values = val.split('');
189
+ // Update SVG fill
190
+ this.svgCircles.forEach((svg, idx) => {
191
+ const circle = svg.querySelector('circle');
192
+ if (circle) {
193
+ if (this.values[idx]) {
194
+ circle.setAttribute('fill', this.theme === 'dark' ? 'white' : 'black');
195
+ }
196
+ else {
197
+ circle.setAttribute('fill', 'transparent');
198
+ }
199
+ }
200
+ });
201
+ // Emit PIN when fully entered
202
+ if (this.values.length === this.length) {
203
+ this.pinEntered.emit(this.values.join(''));
204
+ }
205
+ });
206
+ // Focus hidden input when container clicked
207
+ this.renderer.listen(parent, 'click', () => {
208
+ hiddenInput.focus();
209
+ });
210
+ }
211
+ injectStyles() {
212
+ const style = this.renderer.createElement('style');
213
+ style.textContent = `
214
+ .pin-svg-container {
215
+ display: flex;
216
+ gap: 20px;
217
+ align-items: center;
218
+ justify-content: center;
219
+ margin: 20px;
220
+ }
221
+ .pin-svg {
222
+ cursor: pointer;
223
+ }
224
+ .light-theme {
225
+ color: #000;
226
+ }
227
+ .dark-theme {
228
+ background-color: #000;
229
+ color: #fff;
230
+ } `;
231
+ document.head.appendChild(style);
232
+ }
233
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: PinEntryDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
234
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.2", type: PinEntryDirective, isStandalone: true, selector: "input[appPinEntry]", inputs: { length: "length", theme: "theme" }, outputs: { pinEntered: "pinEntered" }, ngImport: i0 });
235
+ }
236
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: PinEntryDirective, decorators: [{
237
+ type: Directive,
238
+ args: [{
239
+ selector: 'input[appPinEntry]',
240
+ standalone: true
241
+ }]
242
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { length: [{
243
+ type: Input
244
+ }], theme: [{
245
+ type: Input
246
+ }], pinEntered: [{
247
+ type: Output
248
+ }] } });
249
+
250
+ class FloatingLabelDirective {
251
+ el;
252
+ renderer;
253
+ label;
254
+ labelElement;
255
+ constructor(el, renderer) {
256
+ this.el = el;
257
+ this.renderer = renderer;
258
+ }
259
+ ngOnInit() {
260
+ // Inject directive-specific CSS once
261
+ this.injectStyles();
262
+ const parent = this.renderer.createElement('div');
263
+ this.renderer.addClass(parent, 'floating-label-container');
264
+ const input = this.el.nativeElement;
265
+ this.renderer.insertBefore(input.parentNode, parent, input);
266
+ this.renderer.appendChild(parent, input);
267
+ this.labelElement = this.renderer.createElement('label');
268
+ this.renderer.addClass(this.labelElement, 'floating-label');
269
+ this.labelElement.innerText = this.label;
270
+ this.renderer.appendChild(parent, this.labelElement);
271
+ if (input.value) {
272
+ this.renderer.addClass(this.labelElement, 'active');
273
+ }
274
+ }
275
+ onFocus() {
276
+ this.renderer.addClass(this.labelElement, 'active');
277
+ }
278
+ onBlur() {
279
+ if (!this.el.nativeElement.value) {
280
+ this.renderer.removeClass(this.labelElement, 'active');
281
+ }
282
+ }
283
+ injectStyles() {
284
+ const style = this.renderer.createElement('style');
285
+ style.textContent = `
286
+
287
+ .floating-label-container {
288
+ position: relative;
289
+ width: var(--fullWidth);
290
+ display: flex;
291
+ align-items: center;
292
+ }
293
+
294
+ .floating-label-container input {
295
+ border: 1px solid var(--steelGray);
296
+ border-radius: 4px;
297
+ padding: 14px 10px 6px 10px; /* extra top padding for label space */
298
+ width: var(--fullWidth);
299
+ outline: none;
300
+ font-size: var(--fontSize16);
301
+ }
302
+
303
+ .floating-label-container input:focus {
304
+ border-color: var(--shuttleGray);
305
+ }
306
+
307
+ .floating-label {
308
+ position: absolute;
309
+ left: var(--space12);
310
+ top: auto;
311
+ color: #777;
312
+ font-size: var(--fontSize16);
313
+ transition: all 0.1s ease-out;
314
+ transition-property: transform;
315
+ pointer-events: none;
316
+
317
+ }
318
+
319
+ .floating-label.active {
320
+ top: 2px;
321
+ font-size: var(--fontSize12);
322
+ color: var(--midnightGray);
323
+ }
324
+
325
+
326
+ `;
327
+ document.head.appendChild(style);
328
+ }
329
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: FloatingLabelDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
330
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.2", type: FloatingLabelDirective, isStandalone: true, selector: "input[appFloatingLabel]", inputs: { label: "label" }, host: { listeners: { "focus": "onFocus()", "blur": "onBlur()" } }, ngImport: i0 });
331
+ }
332
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: FloatingLabelDirective, decorators: [{
333
+ type: Directive,
334
+ args: [{
335
+ selector: 'input[appFloatingLabel]',
336
+ standalone: true
337
+ }]
338
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { label: [{
339
+ type: Input
340
+ }], onFocus: [{
341
+ type: HostListener,
342
+ args: ['focus']
343
+ }], onBlur: [{
344
+ type: HostListener,
345
+ args: ['blur']
346
+ }] } });
347
+
348
+ class FloatingLabelPinDirective {
349
+ el;
350
+ renderer;
351
+ label;
352
+ labelElement;
353
+ toggleButton;
354
+ isVisible = false;
355
+ constructor(el, renderer) {
356
+ this.el = el;
357
+ this.renderer = renderer;
358
+ }
359
+ ngOnInit() {
360
+ // Inject directive-specific CSS once
361
+ this.injectStyles();
362
+ const parent = this.renderer.createElement('div');
363
+ this.renderer.addClass(parent, 'floating-label-pin-container');
364
+ const input = this.el.nativeElement;
365
+ input.type = 'password'; // default hidden
366
+ this.renderer.insertBefore(input.parentNode, parent, input);
367
+ this.renderer.appendChild(parent, input);
368
+ // Create label
369
+ this.labelElement = this.renderer.createElement('label');
370
+ this.renderer.addClass(this.labelElement, 'floating-label');
371
+ this.labelElement.innerText = this.label;
372
+ this.renderer.appendChild(parent, this.labelElement);
373
+ // Create toggle button
374
+ this.toggleButton = this.renderer.createElement('button');
375
+ this.renderer.addClass(this.toggleButton, 'pin-toggle');
376
+ this.toggleButton.type = 'button';
377
+ this.toggleButton.innerText = 'Show';
378
+ this.renderer.appendChild(parent, this.toggleButton);
379
+ // Toggle logic
380
+ this.renderer.listen(this.toggleButton, 'click', () => {
381
+ this.isVisible = !this.isVisible;
382
+ input.type = this.isVisible ? 'text' : 'password';
383
+ this.toggleButton.innerText = this.isVisible ? 'Hide' : 'Show';
384
+ });
385
+ // Initial state
386
+ if (input.value) {
387
+ this.renderer.addClass(this.labelElement, 'active');
388
+ }
389
+ }
390
+ onFocus() {
391
+ this.renderer.addClass(this.labelElement, 'active');
392
+ }
393
+ onBlur() {
394
+ if (!this.el.nativeElement.value) {
395
+ this.renderer.removeClass(this.labelElement, 'active');
396
+ }
397
+ }
398
+ injectStyles() {
399
+ const style = this.renderer.createElement('style');
400
+ style.textContent = `
401
+
402
+ .floating-label-pin-container {
403
+ position: relative;
404
+ width: var(--fullWidth);
405
+ display: flex;
406
+ justify-content: flex-end;
407
+ align-items: center;
408
+ }
409
+
410
+ .floating-label-pin-container input {
411
+ border: 1px solid #ccc;
412
+ border-radius: 4px;
413
+ padding: 14px 40px 6px 10px; /* space for toggle button */
414
+ /* width: 100%; */
415
+ font-size: var(--fontSize16);
416
+ outline: none;
417
+ }
418
+
419
+ .floating-label-pin-container input:focus {
420
+ border-color: var(--shuttleGray);
421
+ }
422
+
423
+ .floating-label {
424
+ position: absolute;
425
+ left: var(--fontSize12);
426
+ top: auto;
427
+ /* top: 12px; */
428
+ color: #777;
429
+ font-size: var(--fontSize16);
430
+ transition: all 0.1s ease-out;
431
+ transition-property: transform;
432
+ pointer-events: none;
433
+ }
434
+
435
+ .floating-label.active {
436
+ top: 2px;
437
+ font-size: var(--fontSize12);
438
+ color: var(--midnightGray);
439
+ }
440
+
441
+ .pin-toggle {
442
+ position: absolute;
443
+ background: none;
444
+ border: none;
445
+ color: var(--seaBlue);
446
+ cursor: pointer;
447
+ font-family: var(--fontFamily);
448
+ font-size: var(--fontSize14);
449
+ font-style: normal;
450
+ font-weight: var(--strong);
451
+ }
452
+
453
+
454
+ `;
455
+ document.head.appendChild(style);
456
+ }
457
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: FloatingLabelPinDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
458
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.2", type: FloatingLabelPinDirective, isStandalone: true, selector: "input[appFloatingLabelPin]", inputs: { label: "label" }, host: { listeners: { "focus": "onFocus()", "blur": "onBlur()" } }, ngImport: i0 });
459
+ }
460
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: FloatingLabelPinDirective, decorators: [{
461
+ type: Directive,
462
+ args: [{
463
+ selector: 'input[appFloatingLabelPin]',
464
+ standalone: true,
465
+ }]
466
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { label: [{
467
+ type: Input
468
+ }], onFocus: [{
469
+ type: HostListener,
470
+ args: ['focus']
471
+ }], onBlur: [{
472
+ type: HostListener,
473
+ args: ['blur']
474
+ }] } });
475
+
476
+ /*
477
+ * Public API Surface of reusable-components
478
+ */
479
+
480
+ /**
481
+ * Generated bundle index. Do not edit.
482
+ */
483
+
484
+ export { Button, FloatingLabelDirective, FloatingLabelPinDirective, InputComponent, PinEntryDirective, SelectComponent };
485
+ //# sourceMappingURL=reusable-components.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reusable-components.mjs","sources":["../../../projects/reusable-components/src/lib/buttons/button.component.ts","../../../projects/reusable-components/src/lib/input/input.component.ts","../../../projects/reusable-components/src/lib/select/select.component.ts","../../../projects/reusable-components/src/lib/pin-entry/pin-entry.directive.ts","../../../projects/reusable-components/src/lib/floating-label/floating-label.directive.ts","../../../projects/reusable-components/src/lib/floating-label-pin/floating-label-pin.directive.ts","../../../projects/reusable-components/src/public-api.ts","../../../projects/reusable-components/src/reusable-components.ts"],"sourcesContent":["import { Component, input } from \"@angular/core\";\nimport { NgpButton } from \"ng-primitives/button\";\n\n/**\n * The size of the button.\n */\nexport type ButtonSize = \"sm\" | \"md\" | \"lg\" | \"xl\";\n/**\n * The variant of the button.\n */\nexport type ButtonVariant =\n | \"primary\"\n | \"secondary\"\n | \"destructive\"\n | \"outline\"\n | \"ghost\"\n | \"link\";\n@Component({\n selector: \"button[app-button]\",\n hostDirectives: [{ directive: NgpButton, inputs: [\"disabled\"] }],\n template: `\n <ng-content />\n `,\n host: {\n \"[attr.data-size]\": \"size()\",\n \"[attr.data-variant]\": \"variant()\",\n },\n styles: `\n :host {\n border: none;\n border-radius: var(--radiusRound);\n width: 100%;\n max-width: var(--width400);\n display: flex;\n align-items: center;\n justify-content: center;\n font-family: var(--fontFamily);\n font-weight: var(--semi);\n line-height: var(--line-height-large);\n cursor: pointer;\n }\n :host[data-hover] {\n background-color: var(--ngp-background-hover);\n }\n :host[data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n }\n :host[data-press] {\n background-color: var(--ngp-background-active);\n }\n /* Size variants */\n :host[data-size=\"sm\"] {\n font-size: var(--fontSize12);\n height: var(--height-height28, 28px);\n padding: var(--space0, 0) var(--space12, 12px);\n }\n :host[data-size=\"md\"],\n :host:not([data-size]) {\n font-size: var(--fontSize14);\n height: var(--height-height36, 36px);\n padding: var(--space4, 4px) var(--space16, 16px);\n }\n :host[data-size=\"lg\"] {\n font-size: var(--fontSize16);\n height: var(--height-height48, 48px);\n padding: var(--space12, 12px) var(--space16, 16px);\n }\n :host[data-size=\"xl\"] {\n height: 3.5rem;\n padding-left: 1.5rem;\n padding-right: 1.5rem;\n font-size: 1.125rem;\n --ng-icon__size: 1.125rem;\n }\n /* Variant styles */\n :host[data-variant=\"primary\"],\n :host:not([data-variant]) {\n background-color: var(--button-primary-background-color);\n color: var(--button-primary-font-color);\n }\n :host[data-variant=\"primary\"][data-hover],\n :host:not([data-variant])[data-hover] {\n background-color: var(--button-primary-background-color);\n }\n :host[data-variant=\"primary\"][data-press],\n :host:not([data-variant])[data-press] {\n background-color: var(--button-primary-background-color);\n }\n :host[data-variant=\"secondary\"] {\n background-color: var(--button-secondary-background-color);\n color: var(--button-secondary-font-color);\n border: 1px solid var(--button-secondary-border-color, var(--accent-color));\n }\n :host[data-variant=\"secondary\"][data-hover] {\n background-color: var(--button-secondary-background-color);\n }\n :host[data-variant=\"secondary\"][data-press] {\n background-color: var(--button-secondary-background-color);\n }\n :host[data-variant=\"destructive\"] {\n background-color: var(--ngp-destructive-background, #ef4444);\n color: var(--ngp-destructive-text, #ffffff);\n border: none;\n }\n :host[data-variant=\"destructive\"][data-hover] {\n background-color: var(--ngp-destructive-background-hover, #dc2626);\n }\n :host[data-variant=\"destructive\"][data-press] {\n background-color: var(--ngp-destructive-background-active, #b91c1c);\n }\n :host[data-variant=\"outline\"] {\n background-color: transparent;\n color: var(--ngp-text-primary);\n border: 1px solid var(--ngp-outline-border, #e2e8f0);\n box-shadow: none;\n }\n :host[data-variant=\"outline\"][data-hover] {\n background-color: var(--ngp-background-hover);\n border-color: var(--ngp-outline-border-hover, #cbd5e1);\n }\n :host[data-variant=\"outline\"][data-press] {\n background-color: var(\n --ngp-outline-background-active,\n rgba(15, 23, 42, 0.1)\n );\n }\n :host[data-variant=\"ghost\"] {\n background-color: transparent;\n color: var(--ngp-text-primary);\n border: none;\n box-shadow: none;\n }\n :host[data-variant=\"ghost\"][data-hover] {\n background-color: var(--ngp-background-hover);\n }\n :host[data-variant=\"ghost\"][data-press] {\n background-color: var(--ngp-background-active);\n }\n :host[data-variant=\"link\"] {\n background-color: transparent;\n color: var(--ngp-link-color, #3b82f6);\n border: none;\n box-shadow: none;\n text-decoration: underline;\n text-underline-offset: 4px;\n }\n :host[data-variant=\"link\"][data-hover] {\n text-decoration-thickness: 2px;\n }\n :host[data-variant=\"primary\"]:host[disabled] {\n background-color: var(--button-primary-disabled-background-color);\n cursor: not-allowed;\n }\n :host[data-variant=\"secondary\"]:host[disabled] {\n background-color: var(--button-secondary-disabled-background-color);\n cursor: not-allowed;\n }\n `,\n})\nexport class Button {\n /**\n * The size of the button.\n */\n readonly size = input<ButtonSize>(\"md\");\n /**\n * The variant of the button.\n */\n readonly variant = input<ButtonVariant>(\"primary\");\n}","import { Component, input, signal } from \"@angular/core\";\n\n@Component({\n selector: 'app-input',\n template: `\n <label class=\"ngp-field\">\n <input\n type=\"text\"\n [value]=\"value()\"\n (input)=\"onInput($event)\"\n (focus)=\"focused.set(true)\"\n (blur)=\"focused.set(false)\"\n class=\"ngp-input\"\n [attr.placeholder]=\"placeholder()\"\n />\n <span class=\"ngp-label\" [attr.data-active]=\"(value() || focused()) ? '' : null\">{{ label() }}</span>\n </label>\n `,\n styles: `\n :host { display: block; width: 100%; max-width: var(--width400); font-family: var(--fontFamily); }\n .ngp-field { position: relative; display: block; }\n .ngp-input {\n width: 100%;\n padding: 1rem 0.75rem 0.5rem 0.75rem;\n font-size: var(--fontSize14, 14px);\n border: 1px solid var(--ngp-outline-border, #e2e8f0);\n border-radius: 8px;\n background: var(--ngp-input-background, #fff);\n box-sizing: border-box;\n transition: border-color 0.12s ease, box-shadow 0.12s ease, background 0.12s ease;\n }\n .ngp-input:hover {\n border-color: var(--ngp-outline-border-hover, #cbd5e1);\n }\n .ngp-input:focus {\n outline: none;\n border-color: var(--shuttleGray);\n box-shadow: 0 0 0 4px rgba(59,130,246,0.08);\n }\n .ngp-input:disabled {\n background: var(--ngp-disabled-background, #f8fafc);\n color: var(--ngp-text-muted, #9ca3af);\n cursor: not-allowed;\n }\n .ngp-label {\n position: absolute;\n left: 0.75rem;\n top: 0.8rem;\n transform-origin: left top;\n transition: transform 0.12s ease, top 0.12s ease, font-size 0.12s ease, color 0.12s ease;\n color: var(--ngp-text-muted, #6b7280);\n pointer-events: none;\n background: transparent;\n padding: 0 0.125rem;\n font-weight: 500;\n }\n .ngp-label[data-active] {\n transform: translateY(-0.85rem) scale(0.82);\n top: 0.9rem;\n font-weight: 600;\n color: var(--midnightGray);\n background: transparent;\n }\n /* error state when field has data-invalid attribute */\n :host([data-invalid]) .ngp-input,\n .ngp-field[data-invalid] .ngp-input {\n border-color: var(--ngp-destructive-background, #ef4444);\n }\n :host([data-invalid]) .ngp-label,\n .ngp-field[data-invalid] .ngp-label {\n color: var(--ngp-destructive-background, #ef4444);\n }\n `,\n})\nexport class InputComponent {\n /**\n * The floating label text.\n */\n readonly label = input<string>(\"Label\");\n\n /**\n * Optional placeholder (kept for accessibility, primary label floats).\n */\n readonly placeholder = input<string>(\"\");\n\n /**\n * Internal value signal for the input's value.\n */\n readonly value = signal(\"\");\n\n /**\n * Focus state signal used to float the label when focused.\n */\n readonly focused = signal(false);\n\n onInput(e: Event) {\n const target = e.target as HTMLInputElement;\n this.value.set(target.value);\n }\n}\n","import { Component, input, signal } from \"@angular/core\";\nimport { NgFor, NgIf } from '@angular/common';\n\n/**\n * Simple select/dropdown component with floating label behavior similar to the input.\n * Accepts `options` as an array of strings or objects { value, label }.\n */\n@Component({\n standalone: true,\n imports: [NgFor, NgIf],\n selector: 'app-select',\n template: `\n <label class=\"ngp-field\">\n <select\n class=\"ngp-select\"\n (change)=\"onChange($event)\"\n [value]=\"value()\"\n >\n <!-- placeholder option shown inside the native select when no value is selected; fall back to label text -->\n <option *ngIf=\"(placeholder() || label())\" value=\"\">{{ placeholder() || label() }}</option>\n <option *ngFor=\"let opt of options()\" [value]=\"opt.value ?? opt\">{{ opt.label ?? opt }}</option>\n </select>\n <!-- floating label is hidden by default; it becomes visible only when a value exists -->\n <!-- <span class=\"ngp-label\" [attr.data-active]=\"(value()) ? '' : null\">{{ label() }}</span> -->\n </label>\n `,\n styles: `\n :host { display: block; width: 100%; max-width: var(--width400); font-family: var(--fontFamily); }\n .ngp-field { position: relative;}\n .ngp-select {\n width: 100%;\n padding: 0.875rem 0.75rem 0.5rem 0.75rem;\n font-size: var(--fontSize14, 14px);\n border: 1px solid var(--ngp-outline-border, #e2e8f0);\n border-radius: 8px;\n box-sizing: border-box;\n color: var(--shuttleGray);\n display: inline-flex;\n flex-direction: column;\n align-items: center;\n gap: var(--space16, 16px);\n\n }\n\n option {\n background-color: violet;\n }\n\n .ngp-select:focus { outline: none; border-color: var(--shuttleGray); box-shadow: 0 0 0 4px rgba(59,130,246,0.08); }\n // .ngp-label {\n // position: absolute;\n // left: 0.75rem;\n // top: 0.85rem;\n // transform-origin: left top;\n // transition: transform 0.12s ease, top 0.12s ease, font-size 0.12s ease;\n // color: var(--ngp-text-muted, #6b7280);\n // pointer-events: none;\n // padding: 0 0.125rem;\n // font-weight: 500;\n // }\n // .ngp-label[data-active] {\n // transform: translateY(-0.85rem) scale(0.82);\n // top: 0.45rem;\n // font-weight: 600;\n // color: var(--accent-color, #3b82f6);\n // }\n `,\n})\nexport class SelectComponent {\n readonly label = input<string>('Select');\n readonly placeholder = input<string>('');\n /** Accepts Array<string> or Array<{value,label}> */\n readonly options = input<any[]>([]);\n readonly value = signal('');\n\n onChange(e: Event) {\n const target = e.target as HTMLSelectElement;\n const v = target.value;\n this.value.set(v);\n }\n}\n","import { Directive, Input, Output, EventEmitter, ElementRef, Renderer2, OnInit } from '@angular/core';\n\n@Directive({\n selector: 'input[appPinEntry]',\n standalone: true\n})\nexport class PinEntryDirective implements OnInit {\n @Input() length: number = 4; // default 4 digits\n @Input() theme: 'light' | 'dark' = 'light'; // theme switch\n @Output() pinEntered = new EventEmitter<string>();\n\n private svgCircles: SVGSVGElement[] = [];\n private values: string[] = [];\n\n constructor(private el: ElementRef, private renderer: Renderer2) {}\n\n ngOnInit(): void {\n\n // Inject directive-specific CSS once\n this.injectStyles();\n\n const parent = this.renderer.createElement('div');\n this.renderer.addClass(parent, 'pin-svg-container');\n this.renderer.addClass(parent, this.theme === 'dark' ? 'dark-theme' : 'light-theme');\n\n // Remove original input\n const originalInput = this.el.nativeElement;\n this.renderer.insertBefore(originalInput.parentNode, parent, originalInput);\n this.renderer.removeChild(originalInput.parentNode, originalInput);\n\n // Hidden input to capture actual value\n const hiddenInput = this.renderer.createElement('input');\n this.renderer.setAttribute(hiddenInput, 'type', 'tel');\n this.renderer.setStyle(hiddenInput, 'opacity', '0');\n this.renderer.setStyle(hiddenInput, 'position', 'absolute');\n this.renderer.setStyle(hiddenInput, 'pointer-events', 'none');\n this.renderer.appendChild(parent, hiddenInput);\n\n // Create SVG circles\n for (let i = 0; i < this.length; i++) {\n const svg = this.renderer.createElement('svg', 'svg');\n this.renderer.setAttribute(svg, 'xmlns', 'http://www.w3.org/2000/svg');\n this.renderer.setAttribute(svg, 'width', '40');\n this.renderer.setAttribute(svg, 'height', '40');\n this.renderer.setAttribute(svg, 'viewBox', '0 0 24 24');\n\n const circle = this.renderer.createElement('circle', 'svg');\n this.renderer.setAttribute(circle, 'cx', '12');\n this.renderer.setAttribute(circle, 'cy', '12');\n this.renderer.setAttribute(circle, 'r', '9.5');\n\n // Stroke color depends on theme\n this.renderer.setAttribute(circle, 'stroke', this.theme === 'dark' ? 'white' : 'black');\n this.renderer.setAttribute(circle, 'fill', 'transparent');\n\n this.renderer.appendChild(svg, circle);\n this.renderer.addClass(svg, 'pin-svg');\n this.renderer.appendChild(parent, svg);\n\n this.svgCircles.push(svg);\n }\n\n // Listen for input\n this.renderer.listen(hiddenInput, 'input', (event: any) => {\n const val = event.target.value.replace(/\\D/g, '').slice(0, this.length);\n this.values = val.split('');\n\n // Update SVG fill\n this.svgCircles.forEach((svg, idx) => {\n const circle = svg.querySelector('circle');\n if (circle) {\n if (this.values[idx]) {\n circle.setAttribute('fill', this.theme === 'dark' ? 'white' : 'black');\n } else {\n circle.setAttribute('fill', 'transparent');\n }\n }\n });\n\n // Emit PIN when fully entered\n if (this.values.length === this.length) {\n this.pinEntered.emit(this.values.join(''));\n }\n });\n\n // Focus hidden input when container clicked\n this.renderer.listen(parent, 'click', () => {\n hiddenInput.focus();\n });\n }\n\n private injectStyles() {\n const style = this.renderer.createElement('style');\n style.textContent = `\n .pin-svg-container {\n display: flex;\n gap: 20px;\n align-items: center;\n justify-content: center;\n margin: 20px;\n }\n .pin-svg {\n cursor: pointer;\n }\n .light-theme {\n color: #000;\n }\n .dark-theme {\n background-color: #000;\n color: #fff;\n } `;\n document.head.appendChild(style);\n }\n}\n","import { Directive, Input, ElementRef, Renderer2, OnInit, HostListener } from '@angular/core';\n\n@Directive({\n selector: 'input[appFloatingLabel]',\n standalone: true\n})\nexport class FloatingLabelDirective implements OnInit {\n @Input() label!: string;\n private labelElement!: HTMLLabelElement;\n\n constructor(private el: ElementRef, private renderer: Renderer2) {}\n\n ngOnInit(): void {\n\n // Inject directive-specific CSS once\n this.injectStyles();\n\n const parent = this.renderer.createElement('div');\n this.renderer.addClass(parent, 'floating-label-container');\n\n const input = this.el.nativeElement;\n this.renderer.insertBefore(input.parentNode, parent, input);\n this.renderer.appendChild(parent, input);\n\n this.labelElement = this.renderer.createElement('label');\n this.renderer.addClass(this.labelElement, 'floating-label');\n this.labelElement.innerText = this.label;\n\n this.renderer.appendChild(parent, this.labelElement);\n\n if (input.value) {\n this.renderer.addClass(this.labelElement, 'active');\n }\n }\n\n @HostListener('focus')\n onFocus() {\n this.renderer.addClass(this.labelElement, 'active');\n }\n\n @HostListener('blur')\n onBlur() {\n if (!this.el.nativeElement.value) {\n this.renderer.removeClass(this.labelElement, 'active');\n }\n }\n\n private injectStyles() {\n const style = this.renderer.createElement('style');\n style.textContent = `\n\n .floating-label-container {\n position: relative;\n width: var(--fullWidth);\n display: flex;\n align-items: center;\n }\n\n .floating-label-container input {\n border: 1px solid var(--steelGray);\n border-radius: 4px;\n padding: 14px 10px 6px 10px; /* extra top padding for label space */\n width: var(--fullWidth);\n outline: none;\n font-size: var(--fontSize16);\n }\n\n .floating-label-container input:focus {\n border-color: var(--shuttleGray);\n }\n\n .floating-label {\n position: absolute;\n left: var(--space12);\n top: auto;\n color: #777;\n font-size: var(--fontSize16);\n transition: all 0.1s ease-out;\n transition-property: transform;\n pointer-events: none;\n\n }\n\n .floating-label.active {\n top: 2px;\n font-size: var(--fontSize12);\n color: var(--midnightGray);\n }\n\n\n `;\n document.head.appendChild(style);\n }\n}\n","import { Directive, Input, ElementRef, Renderer2, OnInit, HostListener } from '@angular/core';\n\n@Directive({\n selector: 'input[appFloatingLabelPin]',\n standalone: true,\n})\nexport class FloatingLabelPinDirective implements OnInit {\n @Input() label!: string;\n\n private labelElement!: HTMLLabelElement;\n private toggleButton!: HTMLButtonElement;\n private isVisible = false;\n\n constructor(private el: ElementRef, private renderer: Renderer2) {}\n\n ngOnInit(): void {\n\n // Inject directive-specific CSS once\n this.injectStyles();\n \n const parent = this.renderer.createElement('div');\n this.renderer.addClass(parent, 'floating-label-pin-container');\n\n const input = this.el.nativeElement;\n input.type = 'password'; // default hidden\n\n this.renderer.insertBefore(input.parentNode, parent, input);\n this.renderer.appendChild(parent, input);\n\n // Create label\n this.labelElement = this.renderer.createElement('label');\n this.renderer.addClass(this.labelElement, 'floating-label');\n this.labelElement.innerText = this.label;\n this.renderer.appendChild(parent, this.labelElement);\n\n // Create toggle button\n this.toggleButton = this.renderer.createElement('button');\n this.renderer.addClass(this.toggleButton, 'pin-toggle');\n this.toggleButton.type = 'button';\n this.toggleButton.innerText = 'Show';\n this.renderer.appendChild(parent, this.toggleButton);\n\n // Toggle logic\n this.renderer.listen(this.toggleButton, 'click', () => {\n this.isVisible = !this.isVisible;\n input.type = this.isVisible ? 'text' : 'password';\n this.toggleButton.innerText = this.isVisible ? 'Hide' : 'Show';\n });\n\n // Initial state\n if (input.value) {\n this.renderer.addClass(this.labelElement, 'active');\n }\n }\n\n @HostListener('focus')\n onFocus() {\n this.renderer.addClass(this.labelElement, 'active');\n }\n\n @HostListener('blur')\n onBlur() {\n if (!this.el.nativeElement.value) {\n this.renderer.removeClass(this.labelElement, 'active');\n }\n }\n\n private injectStyles() {\n const style = this.renderer.createElement('style');\n style.textContent = `\n\n .floating-label-pin-container {\n position: relative;\n width: var(--fullWidth);\n display: flex;\n justify-content: flex-end;\n align-items: center;\n }\n\n .floating-label-pin-container input {\n border: 1px solid #ccc;\n border-radius: 4px;\n padding: 14px 40px 6px 10px; /* space for toggle button */\n /* width: 100%; */\n font-size: var(--fontSize16);\n outline: none;\n }\n\n .floating-label-pin-container input:focus {\n border-color: var(--shuttleGray);\n }\n\n .floating-label {\n position: absolute;\n left: var(--fontSize12);\n top: auto;\n /* top: 12px; */\n color: #777;\n font-size: var(--fontSize16);\n transition: all 0.1s ease-out;\n transition-property: transform;\n pointer-events: none;\n }\n\n .floating-label.active {\n top: 2px;\n font-size: var(--fontSize12);\n color: var(--midnightGray);\n }\n\n .pin-toggle {\n position: absolute;\n background: none;\n border: none;\n color: var(--seaBlue);\n cursor: pointer;\n font-family: var(--fontFamily);\n font-size: var(--fontSize14);\n font-style: normal;\n font-weight: var(--strong);\n }\n\n\n `;\n document.head.appendChild(style);\n }\n}\n","/*\n * Public API Surface of reusable-components\n */\n\nexport * from './lib/buttons/button.component';\nexport * from './lib/input/input.component';\nexport * from './lib/select/select.component';\nexport * from './lib/pin-entry/pin-entry.directive';\nexport * from './lib/floating-label/floating-label.directive';\nexport * from './lib/floating-label-pin/floating-label-pin.directive';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "everipackage-reusable-components",
3
+ "version": "1.0.0",
4
+ "peerDependencies": {
5
+ "@angular/common": "^21.1.0",
6
+ "@angular/core": "^21.1.0"
7
+ },
8
+ "dependencies": {
9
+ "tslib": "^2.3.0"
10
+ },
11
+ "sideEffects": false,
12
+ "module": "fesm2022/reusable-components.mjs",
13
+ "typings": "types/reusable-components.d.ts",
14
+ "exports": {
15
+ "./package.json": {
16
+ "default": "./package.json"
17
+ },
18
+ ".": {
19
+ "types": "./types/reusable-components.d.ts",
20
+ "default": "./fesm2022/reusable-components.mjs"
21
+ }
22
+ }
23
+ }
@@ -0,0 +1,109 @@
1
+ import * as i0 from '@angular/core';
2
+ import { OnInit, EventEmitter, ElementRef, Renderer2 } from '@angular/core';
3
+ import * as i1 from 'ng-primitives/button';
4
+
5
+ /**
6
+ * The size of the button.
7
+ */
8
+ type ButtonSize = "sm" | "md" | "lg" | "xl";
9
+ /**
10
+ * The variant of the button.
11
+ */
12
+ type ButtonVariant = "primary" | "secondary" | "destructive" | "outline" | "ghost" | "link";
13
+ declare class Button {
14
+ /**
15
+ * The size of the button.
16
+ */
17
+ readonly size: i0.InputSignal<ButtonSize>;
18
+ /**
19
+ * The variant of the button.
20
+ */
21
+ readonly variant: i0.InputSignal<ButtonVariant>;
22
+ static ɵfac: i0.ɵɵFactoryDeclaration<Button, never>;
23
+ static ɵcmp: i0.ɵɵComponentDeclaration<Button, "button[app-button]", never, { "size": { "alias": "size"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, [{ directive: typeof i1.NgpButton; inputs: { "disabled": "disabled"; }; outputs: {}; }]>;
24
+ }
25
+
26
+ declare class InputComponent {
27
+ /**
28
+ * The floating label text.
29
+ */
30
+ readonly label: i0.InputSignal<string>;
31
+ /**
32
+ * Optional placeholder (kept for accessibility, primary label floats).
33
+ */
34
+ readonly placeholder: i0.InputSignal<string>;
35
+ /**
36
+ * Internal value signal for the input's value.
37
+ */
38
+ readonly value: i0.WritableSignal<string>;
39
+ /**
40
+ * Focus state signal used to float the label when focused.
41
+ */
42
+ readonly focused: i0.WritableSignal<boolean>;
43
+ onInput(e: Event): void;
44
+ static ɵfac: i0.ɵɵFactoryDeclaration<InputComponent, never>;
45
+ static ɵcmp: i0.ɵɵComponentDeclaration<InputComponent, "app-input", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
46
+ }
47
+
48
+ /**
49
+ * Simple select/dropdown component with floating label behavior similar to the input.
50
+ * Accepts `options` as an array of strings or objects { value, label }.
51
+ */
52
+ declare class SelectComponent {
53
+ readonly label: i0.InputSignal<string>;
54
+ readonly placeholder: i0.InputSignal<string>;
55
+ /** Accepts Array<string> or Array<{value,label}> */
56
+ readonly options: i0.InputSignal<any[]>;
57
+ readonly value: i0.WritableSignal<string>;
58
+ onChange(e: Event): void;
59
+ static ɵfac: i0.ɵɵFactoryDeclaration<SelectComponent, never>;
60
+ static ɵcmp: i0.ɵɵComponentDeclaration<SelectComponent, "app-select", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
61
+ }
62
+
63
+ declare class PinEntryDirective implements OnInit {
64
+ private el;
65
+ private renderer;
66
+ length: number;
67
+ theme: 'light' | 'dark';
68
+ pinEntered: EventEmitter<string>;
69
+ private svgCircles;
70
+ private values;
71
+ constructor(el: ElementRef, renderer: Renderer2);
72
+ ngOnInit(): void;
73
+ private injectStyles;
74
+ static ɵfac: i0.ɵɵFactoryDeclaration<PinEntryDirective, never>;
75
+ static ɵdir: i0.ɵɵDirectiveDeclaration<PinEntryDirective, "input[appPinEntry]", never, { "length": { "alias": "length"; "required": false; }; "theme": { "alias": "theme"; "required": false; }; }, { "pinEntered": "pinEntered"; }, never, never, true, never>;
76
+ }
77
+
78
+ declare class FloatingLabelDirective implements OnInit {
79
+ private el;
80
+ private renderer;
81
+ label: string;
82
+ private labelElement;
83
+ constructor(el: ElementRef, renderer: Renderer2);
84
+ ngOnInit(): void;
85
+ onFocus(): void;
86
+ onBlur(): void;
87
+ private injectStyles;
88
+ static ɵfac: i0.ɵɵFactoryDeclaration<FloatingLabelDirective, never>;
89
+ static ɵdir: i0.ɵɵDirectiveDeclaration<FloatingLabelDirective, "input[appFloatingLabel]", never, { "label": { "alias": "label"; "required": false; }; }, {}, never, never, true, never>;
90
+ }
91
+
92
+ declare class FloatingLabelPinDirective implements OnInit {
93
+ private el;
94
+ private renderer;
95
+ label: string;
96
+ private labelElement;
97
+ private toggleButton;
98
+ private isVisible;
99
+ constructor(el: ElementRef, renderer: Renderer2);
100
+ ngOnInit(): void;
101
+ onFocus(): void;
102
+ onBlur(): void;
103
+ private injectStyles;
104
+ static ɵfac: i0.ɵɵFactoryDeclaration<FloatingLabelPinDirective, never>;
105
+ static ɵdir: i0.ɵɵDirectiveDeclaration<FloatingLabelPinDirective, "input[appFloatingLabelPin]", never, { "label": { "alias": "label"; "required": false; }; }, {}, never, never, true, never>;
106
+ }
107
+
108
+ export { Button, FloatingLabelDirective, FloatingLabelPinDirective, InputComponent, PinEntryDirective, SelectComponent };
109
+ export type { ButtonSize, ButtonVariant };