ps-helix 3.0.7 → 3.0.8
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 +3 -3
- package/fesm2022/ps-helix.mjs +126 -37
- package/fesm2022/ps-helix.mjs.map +1 -1
- package/index.d.ts +44 -25
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A comprehensive Angular component library built with Angular 21+ featuring modern design patterns, accessibility-first development, and optimal developer experience.
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/ps-helix)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
[](https://angular.dev/)
|
|
8
8
|
[](https://www.typescriptlang.org/)
|
|
@@ -118,7 +118,7 @@ After installation, verify that ps-helix is in your `package.json`:
|
|
|
118
118
|
```json
|
|
119
119
|
{
|
|
120
120
|
"dependencies": {
|
|
121
|
-
"ps-helix": "^3.0.
|
|
121
|
+
"ps-helix": "^3.0.8"
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
```
|
|
@@ -1173,7 +1173,7 @@ Copyright (c) 2025 PACK Solutions
|
|
|
1173
1173
|
|
|
1174
1174
|
---
|
|
1175
1175
|
|
|
1176
|
-
**Version**: 3.0.
|
|
1176
|
+
**Version**: 3.0.8
|
|
1177
1177
|
**Built with**: Angular 21.0.3, TypeScript 5.9.0, Phosphor Icons 2.0.3
|
|
1178
1178
|
**Author**: Fabrice PEREZ | Product Designer at PACK Solutions
|
|
1179
1179
|
**Last Updated**: January 2026
|
package/fesm2022/ps-helix.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, output, computed, ChangeDetectionStrategy, Component, model, inject, ElementRef, signal, PLATFORM_ID, ViewEncapsulation, InjectionToken, viewChild, effect, ChangeDetectorRef, DestroyRef, forwardRef, Injectable, Renderer2, contentChild, contentChildren, afterNextRender } from '@angular/core';
|
|
2
|
+
import { input, output, computed, ChangeDetectionStrategy, Component, model, inject, ElementRef, signal, PLATFORM_ID, ViewEncapsulation, InjectionToken, viewChild, EventEmitter, effect, Output, Input, ChangeDetectorRef, DestroyRef, forwardRef, Injectable, Renderer2, contentChild, contentChildren, afterNextRender } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/common';
|
|
4
4
|
import { CommonModule, isPlatformBrowser, NgTemplateOutlet } from '@angular/common';
|
|
5
5
|
import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';
|
|
@@ -953,16 +953,25 @@ const CHECKBOX_CONFIG = new InjectionToken('CHECKBOX_CONFIG', {
|
|
|
953
953
|
});
|
|
954
954
|
let checkboxIdCounter = 0;
|
|
955
955
|
class PshCheckboxComponent {
|
|
956
|
+
set checkedInput(v) { this.checked.set(v); }
|
|
957
|
+
set disabledInput(v) { this.disabled.set(v); }
|
|
958
|
+
set indeterminateInput(v) { this.indeterminate.set(v); }
|
|
956
959
|
constructor() {
|
|
957
960
|
this.config = inject(CHECKBOX_CONFIG);
|
|
958
961
|
this.uniqueId = `checkbox-${++checkboxIdCounter}`;
|
|
959
962
|
this.checkboxInput = viewChild('checkboxInput', ...(ngDevMode ? [{ debugName: "checkboxInput" }] : []));
|
|
960
963
|
this.onChange = (value) => { };
|
|
961
964
|
this.onTouched = () => { };
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
this.
|
|
965
|
-
this.
|
|
965
|
+
// CVA-managed state: plain signals + manual @Input/@Output to prevent
|
|
966
|
+
// auto-emission during writeValue()/setDisabledState().
|
|
967
|
+
this.checked = signal(this.config.checked ?? false, ...(ngDevMode ? [{ debugName: "checked" }] : []));
|
|
968
|
+
this.disabled = signal(this.config.disabled ?? false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
969
|
+
this.indeterminate = signal(this.config.indeterminate ?? false, ...(ngDevMode ? [{ debugName: "indeterminate" }] : []));
|
|
970
|
+
this.required = input(this.config.required ?? false, ...(ngDevMode ? [{ debugName: "required" }] : []));
|
|
971
|
+
// Outputs — EventEmitter to decouple from signal writes.
|
|
972
|
+
this.checkedChange = new EventEmitter();
|
|
973
|
+
this.disabledChange = new EventEmitter();
|
|
974
|
+
this.indeterminateChange = new EventEmitter();
|
|
966
975
|
this.label = input(this.config.label ?? '', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
967
976
|
this.error = input('', ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
968
977
|
this.success = input('', ...(ngDevMode ? [{ debugName: "success" }] : []));
|
|
@@ -1004,6 +1013,7 @@ class PshCheckboxComponent {
|
|
|
1004
1013
|
this.checked.update(v => !v);
|
|
1005
1014
|
this.indeterminate.set(false);
|
|
1006
1015
|
this.onChange(this.checked());
|
|
1016
|
+
this.checkedChange.emit(this.checked());
|
|
1007
1017
|
this.onTouched();
|
|
1008
1018
|
}
|
|
1009
1019
|
}
|
|
@@ -1044,7 +1054,7 @@ class PshCheckboxComponent {
|
|
|
1044
1054
|
}
|
|
1045
1055
|
}
|
|
1046
1056
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: PshCheckboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1047
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: PshCheckboxComponent, isStandalone: true, selector: "psh-checkbox", inputs: {
|
|
1057
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: PshCheckboxComponent, isStandalone: true, selector: "psh-checkbox", inputs: { checkedInput: { classPropertyName: "checkedInput", publicName: "checked", isSignal: false, isRequired: false, transformFunction: null }, disabledInput: { classPropertyName: "disabledInput", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, indeterminateInput: { classPropertyName: "indeterminateInput", publicName: "indeterminate", isSignal: false, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, success: { classPropertyName: "success", publicName: "success", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, labelPosition: { classPropertyName: "labelPosition", publicName: "labelPosition", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checkedChange: "checkedChange", disabledChange: "disabledChange", indeterminateChange: "indeterminateChange" }, host: { properties: { "class.checkbox-disabled": "disabled()", "class.checkbox-error": "!!error()", "class.checkbox-success": "!!success()", "class.checkbox-small": "size() === \"small\"", "class.checkbox-large": "size() === \"large\"", "attr.data-state": "state()" } }, providers: [{
|
|
1048
1058
|
provide: NG_VALUE_ACCESSOR,
|
|
1049
1059
|
useExisting: PshCheckboxComponent,
|
|
1050
1060
|
multi: true
|
|
@@ -1064,7 +1074,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
1064
1074
|
'[class.checkbox-large]': 'size() === "large"',
|
|
1065
1075
|
'[attr.data-state]': 'state()'
|
|
1066
1076
|
}, template: "<div class=\"checkbox-container\">\n <label class=\"checkbox-label\" [class.label-left]=\"labelPosition() === 'left'\">\n <input\n #checkboxInput\n type=\"checkbox\"\n class=\"checkbox-input\"\n [checked]=\"checked()\"\n [disabled]=\"disabled()\"\n [required]=\"required()\"\n [attr.aria-label]=\"computedAriaLabel()\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n [attr.aria-checked]=\"ariaChecked()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n (change)=\"toggle()\"\n (keydown)=\"handleKeydown($event)\"\n />\n <span \n class=\"checkbox-control\"\n [class.error]=\"!!error()\"\n [class.success]=\"!!success()\"\n [class.indeterminate]=\"indeterminate()\"\n >\n @if (checked() && !indeterminate()) {\n <i class=\"ph ph-check\" aria-hidden=\"true\"></i>\n }\n @if (indeterminate()) {\n <i class=\"ph ph-minus\" aria-hidden=\"true\"></i>\n }\n </span>\n <span class=\"checkbox-text\">\n @if (label()) {\n {{ label() }}\n } @else {\n <ng-content></ng-content>\n }\n </span>\n </label>\n\n @if (error()) {\n <div [id]=\"errorMessageId()\" class=\"checkbox-error\" role=\"alert\">\n {{ error() }}\n </div>\n }\n\n @if (success()) {\n <div [id]=\"successMessageId()\" class=\"checkbox-success\" role=\"status\">\n {{ success() }}\n </div>\n }\n</div>", styles: [".checkbox-container{display:inline-flex;flex-direction:column;gap:var(--spacing-xs)}.checkbox-label{display:inline-flex;align-items:center;gap:var(--spacing-sm);cursor:pointer;-webkit-user-select:none;user-select:none;color:var(--text-color)}.checkbox-label.label-left{flex-direction:row-reverse;justify-content:space-between}.checkbox-input{position:absolute;opacity:0;width:0;height:0}.checkbox-control{display:flex;align-items:center;justify-content:center;width:var(--size-4-5);height:var(--size-4-5);min-width:var(--size-4-5);min-height:var(--size-4-5);border:var(--border-width-2) solid var(--surface-border);border-radius:var(--border-radius);background:var(--surface-card);transition:background-color var(--animation-duration-fast) var(--animation-easing-default),border-color var(--animation-duration-fast) var(--animation-easing-default);color:var(--primary-color-text);position:relative;flex-shrink:0}.checkbox-input:checked+.checkbox-control{background:var(--primary-color);border-color:var(--primary-color)}.checkbox-input:focus-visible+.checkbox-control{outline:var(--focus-outline-width) var(--focus-outline-style) var(--focus-outline-color);outline-offset:var(--focus-outline-offset)}.checkbox-control i{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%) scale(0);font-size:var(--font-size-xs);opacity:0;transition:opacity var(--animation-duration-fast) var(--animation-easing-default),transform var(--animation-duration-fast) var(--animation-easing-default)}.checkbox-input:checked+.checkbox-control i,.checkbox-control.indeterminate i{opacity:1;transform:translate(-50%,-50%) scale(1.1)}.checkbox-control.indeterminate{background:var(--primary-color);border-color:var(--primary-color)}:host(.checkbox-disabled) .checkbox-label{opacity:var(--opacity-disabled);cursor:not-allowed}:host(.checkbox-error) .checkbox-control{border-color:var(--danger-color)}:host(.checkbox-error) .checkbox-input:checked+.checkbox-control{background:var(--danger-color);border-color:var(--danger-color)}:host(.checkbox-success) .checkbox-control{border-color:var(--success-color)}:host(.checkbox-success) .checkbox-input:checked+.checkbox-control{background:var(--success-color);border-color:var(--success-color)}.checkbox-error{font-size:var(--font-size-sm);color:var(--danger-color)}.checkbox-success{font-size:var(--font-size-sm);color:var(--success-color)}:host(.checkbox-small) .checkbox-control{width:var(--size-4);height:var(--size-4);min-width:var(--size-4);min-height:var(--size-4)}:host(.checkbox-small) .checkbox-text{font-size:var(--font-size-sm)}:host(.checkbox-large) .checkbox-control{width:var(--size-5-5);height:var(--size-5-5);min-width:var(--size-5-5);min-height:var(--size-5-5)}:host(.checkbox-large) .checkbox-text{font-size:var(--font-size-lg)}.checkbox-text{color:var(--text-color)}\n"] }]
|
|
1067
|
-
}], ctorParameters: () => [], propDecorators: { checkboxInput: [{ type: i0.ViewChild, args: ['checkboxInput', { isSignal: true }] }],
|
|
1077
|
+
}], ctorParameters: () => [], propDecorators: { checkboxInput: [{ type: i0.ViewChild, args: ['checkboxInput', { isSignal: true }] }], checkedInput: [{
|
|
1078
|
+
type: Input,
|
|
1079
|
+
args: ['checked']
|
|
1080
|
+
}], disabledInput: [{
|
|
1081
|
+
type: Input,
|
|
1082
|
+
args: ['disabled']
|
|
1083
|
+
}], indeterminateInput: [{
|
|
1084
|
+
type: Input,
|
|
1085
|
+
args: ['indeterminate']
|
|
1086
|
+
}], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], checkedChange: [{
|
|
1087
|
+
type: Output
|
|
1088
|
+
}], disabledChange: [{
|
|
1089
|
+
type: Output
|
|
1090
|
+
}], indeterminateChange: [{
|
|
1091
|
+
type: Output
|
|
1092
|
+
}], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], success: [{ type: i0.Input, args: [{ isSignal: true, alias: "success", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], labelPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelPosition", required: false }] }] } });
|
|
1068
1093
|
|
|
1069
1094
|
class PshCollapseComponent {
|
|
1070
1095
|
constructor() {
|
|
@@ -1402,6 +1427,8 @@ const INPUT_LABELS = {
|
|
|
1402
1427
|
|
|
1403
1428
|
class PshInputComponent {
|
|
1404
1429
|
static { this.nextId = 0; }
|
|
1430
|
+
set valueInput(v) { this.value.set(v ?? ''); }
|
|
1431
|
+
set disabledInput(v) { this.disabled.set(v); }
|
|
1405
1432
|
getState() {
|
|
1406
1433
|
if (this.disabled())
|
|
1407
1434
|
return 'disabled';
|
|
@@ -1422,9 +1449,11 @@ class PshInputComponent {
|
|
|
1422
1449
|
this.cdr = inject(ChangeDetectorRef);
|
|
1423
1450
|
this.destroyRef = inject(DestroyRef);
|
|
1424
1451
|
this.inputId = `psh-input-${PshInputComponent.nextId++}`;
|
|
1425
|
-
//
|
|
1426
|
-
|
|
1427
|
-
this.
|
|
1452
|
+
// CVA-managed state: plain signals + manual @Input/@Output to prevent
|
|
1453
|
+
// auto-emission during writeValue()/setDisabledState().
|
|
1454
|
+
this.value = signal('', ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
1455
|
+
this.disabled = signal(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
1456
|
+
// Non-CVA model inputs (two-way bindable, not written by CVA methods)
|
|
1428
1457
|
this.readonly = model(false, ...(ngDevMode ? [{ debugName: "readonly" }] : []));
|
|
1429
1458
|
this.loading = model(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
1430
1459
|
// Configuration inputs (one-directional)
|
|
@@ -1456,8 +1485,9 @@ class PshInputComponent {
|
|
|
1456
1485
|
this.passwordVisibleSignal = signal(false, ...(ngDevMode ? [{ debugName: "passwordVisibleSignal" }] : []));
|
|
1457
1486
|
this.blurTimeoutId = null;
|
|
1458
1487
|
this.debounceTimeoutId = null;
|
|
1459
|
-
// Outputs
|
|
1460
|
-
this.valueChange =
|
|
1488
|
+
// Outputs — valueChange/disabledChange use EventEmitter to decouple from signal writes.
|
|
1489
|
+
this.valueChange = new EventEmitter();
|
|
1490
|
+
this.disabledChange = new EventEmitter();
|
|
1461
1491
|
this.inputFocus = output();
|
|
1462
1492
|
this.inputBlur = output();
|
|
1463
1493
|
this.suggestionSelect = output();
|
|
@@ -1617,7 +1647,7 @@ class PshInputComponent {
|
|
|
1617
1647
|
}
|
|
1618
1648
|
}
|
|
1619
1649
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: PshInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1620
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: PshInputComponent, isStandalone: true, selector: "psh-input", inputs: {
|
|
1650
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: PshInputComponent, isStandalone: true, selector: "psh-input", inputs: { valueInput: { classPropertyName: "valueInput", publicName: "value", isSignal: false, isRequired: false, transformFunction: null }, disabledInput: { classPropertyName: "disabledInput", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, fullWidth: { classPropertyName: "fullWidth", publicName: "fullWidth", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, showLabel: { classPropertyName: "showLabel", publicName: "showLabel", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, iconStart: { classPropertyName: "iconStart", publicName: "iconStart", isSignal: true, isRequired: false, transformFunction: null }, iconEnd: { classPropertyName: "iconEnd", publicName: "iconEnd", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, success: { classPropertyName: "success", publicName: "success", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, suggestions: { classPropertyName: "suggestions", publicName: "suggestions", isSignal: true, isRequired: false, transformFunction: null }, autocompleteConfig: { classPropertyName: "autocompleteConfig", publicName: "autocompleteConfig", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { readonly: "readonlyChange", loading: "loadingChange", valueChange: "valueChange", disabledChange: "disabledChange", inputFocus: "inputFocus", inputBlur: "inputBlur", suggestionSelect: "suggestionSelect" }, providers: [
|
|
1621
1651
|
{
|
|
1622
1652
|
provide: NG_VALUE_ACCESSOR,
|
|
1623
1653
|
useExisting: forwardRef(() => PshInputComponent),
|
|
@@ -1634,7 +1664,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
1634
1664
|
multi: true
|
|
1635
1665
|
}
|
|
1636
1666
|
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div \n class=\"input-container\"\n [class.full-width]=\"fullWidth()\"\n [class.small]=\"size() === 'small'\"\n [class.large]=\"size() === 'large'\"\n [class.error]=\"!!error()\"\n [class.success]=\"!!success()\"\n [class.disabled]=\"disabled()\"\n [class.readonly]=\"readonly()\"\n [class.loading]=\"loading()\"\n [class.focused]=\"focused()\"\n [class.has-start-icon]=\"!!iconStart()\"\n [class.has-end-icon]=\"!!iconEnd() || type() === 'password'\"\n [class.outlined]=\"variant() === 'outlined'\"\n [class.filled]=\"variant() === 'filled'\"\n>\n <!-- Label slot -->\n @if (showLabel()) {\n <label class=\"input-label\" [for]=\"inputId\" (click)=\"focusSelect()\" [class.required]=\"required()\">\n <ng-content select=\"[input-label]\"></ng-content>\n @if (!hasLabelContent()) {\n {{ label() }}\n }\n </label>\n }\n\n <div class=\"input-wrapper\">\n @if (iconStart()) {\n <i class=\"ph ph-{{ iconStart() }}\" aria-hidden=\"true\"></i>\n }\n\n <input\n [id]=\"inputId\"\n [type]=\"effectiveType()\"\n [attr.placeholder]=\"placeholder()\"\n [attr.aria-label]=\"computedAriaLabel()\"\n [attr.aria-invalid]=\"!!error()\"\n [attr.aria-required]=\"required()\"\n [attr.aria-describedby]=\"error() ? 'error-message' : success() ? 'success-message' : hint() ? 'hint-message' : null\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [value]=\"value()\"\n (input)=\"handleInput($event)\"\n (keydown)=\"handleKeydown($event)\"\n (focus)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n [attr.data-state]=\"state()\"\n />\n\n @if (iconEnd()) {\n <i class=\"ph ph-{{ iconEnd() }}\" aria-hidden=\"true\"></i>\n }\n\n @if (type() === 'password') {\n <button\n type=\"button\"\n class=\"password-toggle\"\n (click)=\"togglePasswordVisibility()\"\n [attr.aria-label]=\"passwordToggleLabel()\"\n [disabled]=\"disabled() || readonly()\"\n >\n <i \n [class]=\"'ph ph-' + (passwordVisible() ? 'eye-slash' : 'eye')\"\n aria-hidden=\"true\"\n ></i>\n </button>\n }\n\n @if (loading()) {\n <div class=\"input-loader\" aria-hidden=\"true\">\n <div class=\"loader\"></div>\n </div>\n }\n\n @if (showSuggestions()) {\n <div class=\"suggestions-list\" role=\"listbox\">\n @for (suggestion of filteredSuggestions(); track suggestion; let i = $index) {\n <div \n class=\"suggestion-item\"\n [class.focused]=\"i === focusedSuggestionIndex()\"\n role=\"option\"\n [attr.aria-selected]=\"i === focusedSuggestionIndex()\"\n (click)=\"handleSuggestionClick(suggestion)\"\n (mouseenter)=\"focusedSuggestionIndex.set(i)\"\n >\n {{ suggestion }}\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Error message slot -->\n @if (error()) {\n <div id=\"error-message\" class=\"input-error\" role=\"alert\">\n <ng-content select=\"[input-error]\">\n {{ error() }}\n </ng-content>\n </div>\n }\n\n <!-- Success message slot -->\n @if (success()) {\n <div id=\"success-message\" class=\"input-success\" role=\"status\">\n <ng-content select=\"[input-success]\">\n {{ success() }}\n </ng-content>\n </div>\n }\n\n <!-- Hint message slot -->\n @if (hint()) {\n <div id=\"hint-message\" class=\"input-hint\">\n <ng-content select=\"[input-hint]\">\n {{ hint() }}\n </ng-content>\n </div>\n }\n</div>", styles: [".input-container{position:relative;width:100%;max-width:300px}.input-container.full-width{max-width:none}.input-label{display:block;color:var(--text-color);font-size:var(--font-size-sm);font-weight:500;margin-bottom:var(--spacing-xs);width:100%;cursor:pointer}.input-label.required:after{content:\"*\";color:var(--danger-color);margin-left:var(--spacing-xxs)}.input-wrapper{position:relative;display:flex;align-items:center;width:100%}input{width:100%;height:var(--height-input-md);padding:0 var(--spacing-md);font-family:inherit;font-size:var(--font-size-base);color:var(--text-color);background:var(--surface-0);border:var(--border-width-1) solid var(--surface-border);border-radius:var(--border-radius);transition:all var(--animation-duration-default) var(--animation-easing-default)}input:hover:not(:disabled):not(:focus){border-color:var(--primary-color)}input::placeholder{color:var(--text-color-tertiary);opacity:1}input:focus{outline:none;border-color:var(--primary-color);box-shadow:0 0 0 var(--focus-ring-width) var(--focus-ring-color)}.input-container.outlined input{background:transparent;border:var(--border-width-2) solid var(--surface-border)}.input-container.outlined input:hover:not(:disabled):not(:focus){border-color:var(--primary-color)}.input-container.outlined input:focus{border-color:var(--primary-color);box-shadow:0 0 0 var(--focus-ring-width) var(--focus-ring-color)}.input-container.filled input{background:var(--surface-ground);border:var(--border-width-1) solid transparent}.input-container.filled input:hover:not(:disabled):not(:focus){background:var(--surface-hover)}.input-container.filled input:focus{background:var(--surface-0);border-color:var(--primary-color);box-shadow:0 0 0 var(--focus-ring-width) var(--focus-ring-color)}.input-container.error input{border-color:var(--danger-color)}.input-container.error input:focus{box-shadow:0 0 0 var(--focus-ring-width) var(--focus-ring-error)}.input-container.success input{border-color:var(--success-color)}.input-container.success input:focus{box-shadow:0 0 0 var(--focus-ring-width) var(--focus-ring-success)}.input-container.disabled input{background:var(--surface-ground);cursor:not-allowed;opacity:var(--opacity-disabled)}.input-container.readonly input{background:var(--surface-ground);cursor:default}.input-container.has-start-icon input{padding-left:calc(var(--spacing-md) * 2 + 1rem)}.input-container.has-end-icon input{padding-right:calc(var(--spacing-md) * 2 + 1rem)}.input-wrapper i{position:absolute;font-size:var(--icon-size-md);color:var(--text-color-secondary);pointer-events:none}.input-wrapper i:first-child{left:var(--spacing-md)}.input-wrapper i:last-child{right:var(--spacing-md)}.password-toggle{position:absolute;right:var(--spacing-md);background:transparent;border:none;color:var(--text-color-secondary);cursor:pointer;padding:var(--spacing-xs);border-radius:var(--border-radius);display:flex;align-items:center;justify-content:center;transition:all .2s ease}.password-toggle:hover{background:var(--surface-hover);color:var(--text-color)}.password-toggle:focus{outline:none;box-shadow:0 0 0 var(--focus-ring-width) var(--focus-ring-color)}.password-toggle i{font-size:var(--icon-size-md);position:static;pointer-events:auto}.input-container.small input{height:var(--height-input-sm);padding:0 var(--spacing-md);font-size:var(--font-size-sm)}.input-container.large input{height:var(--height-input-lg);padding:0 var(--spacing-lg);font-size:var(--font-size-lg)}.input-error,.input-success,.input-hint{font-size:var(--font-size-sm);margin-top:var(--spacing-xs)}.input-error{color:var(--danger-color);display:flex;align-items:center;gap:var(--spacing-xs)}.input-error i{font-size:var(--icon-size-sm)}.input-success{color:var(--success-color)}.input-hint{color:var(--text-color-secondary)}.input-loader{position:absolute;right:var(--spacing-md);display:flex;align-items:center;justify-content:center}.loader{width:var(--icon-size-sm);height:var(--icon-size-sm);border:var(--border-width-2) solid var(--surface-border);border-top-color:var(--primary-color);border-radius:50%;animation:spin .8s linear infinite}.suggestions-list{position:absolute;top:100%;left:0;right:0;background:var(--surface-0);border:var(--border-width-1) solid var(--surface-border);border-radius:var(--border-radius);box-shadow:var(--shadow-lg);z-index:var(--z-index-dropdown);max-height:var(--size-48);overflow-y:auto;margin-top:var(--spacing-xs)}.suggestion-item{padding:var(--spacing-sm) var(--spacing-md);cursor:pointer;transition:all var(--animation-duration-default) var(--animation-easing-default);color:var(--text-color)}.suggestion-item:hover,.suggestion-item.focused{background:var(--surface-hover);color:var(--primary-color)}@keyframes spin{to{transform:rotate(360deg)}}\n"] }]
|
|
1637
|
-
}], ctorParameters: () => [], propDecorators: {
|
|
1667
|
+
}], ctorParameters: () => [], propDecorators: { valueInput: [{
|
|
1668
|
+
type: Input,
|
|
1669
|
+
args: ['value']
|
|
1670
|
+
}], disabledInput: [{
|
|
1671
|
+
type: Input,
|
|
1672
|
+
args: ['disabled']
|
|
1673
|
+
}], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }, { type: i0.Output, args: ["readonlyChange"] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }, { type: i0.Output, args: ["loadingChange"] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], showLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLabel", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], iconStart: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconStart", required: false }] }], iconEnd: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconEnd", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], success: [{ type: i0.Input, args: [{ isSignal: true, alias: "success", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], suggestions: [{ type: i0.Input, args: [{ isSignal: true, alias: "suggestions", required: false }] }], autocompleteConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocompleteConfig", required: false }] }], valueChange: [{
|
|
1674
|
+
type: Output
|
|
1675
|
+
}], disabledChange: [{
|
|
1676
|
+
type: Output
|
|
1677
|
+
}], inputFocus: [{ type: i0.Output, args: ["inputFocus"] }], inputBlur: [{ type: i0.Output, args: ["inputBlur"] }], suggestionSelect: [{ type: i0.Output, args: ["suggestionSelect"] }] } });
|
|
1638
1678
|
|
|
1639
1679
|
const TOOLTIP_CONFIG = new InjectionToken('TOOLTIP_CONFIG', {
|
|
1640
1680
|
factory: () => ({
|
|
@@ -2763,14 +2803,18 @@ const RADIO_STYLES = new InjectionToken('RADIO_STYLES', {
|
|
|
2763
2803
|
*/
|
|
2764
2804
|
let radioIdCounter = 0;
|
|
2765
2805
|
class PshRadioComponent {
|
|
2806
|
+
set checkedInput(v) { this.checked.set(v); }
|
|
2807
|
+
set disabledInput(v) { this.disabled.set(v); }
|
|
2766
2808
|
constructor() {
|
|
2767
2809
|
this.config = inject(RADIO_CONFIG);
|
|
2768
2810
|
this.styles = inject(RADIO_STYLES, { optional: true }) ?? [];
|
|
2769
2811
|
this.uniqueId = `radio-${++radioIdCounter}`;
|
|
2770
|
-
//
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
this.
|
|
2812
|
+
// Plain signals + manual @Input/@Output to prevent auto-emission
|
|
2813
|
+
// when parent sets [checked] or [disabled] via template binding.
|
|
2814
|
+
// model() would auto-emit checkedChange/disabledChange on .set().
|
|
2815
|
+
this.checked = signal(this.config.checked ?? false, ...(ngDevMode ? [{ debugName: "checked" }] : []));
|
|
2816
|
+
this.disabled = signal(this.config.disabled ?? false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
2817
|
+
this.required = input(this.config.required ?? false, ...(ngDevMode ? [{ debugName: "required" }] : []));
|
|
2774
2818
|
// Regular inputs
|
|
2775
2819
|
this.label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
2776
2820
|
this.error = input('', ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
@@ -2783,9 +2827,10 @@ class PshRadioComponent {
|
|
|
2783
2827
|
// Content projection tracking
|
|
2784
2828
|
this.radioText = contentChild('.radio-text', ...(ngDevMode ? [{ debugName: "radioText" }] : []));
|
|
2785
2829
|
this.hasProjectedContent = signal(false, ...(ngDevMode ? [{ debugName: "hasProjectedContent" }] : []));
|
|
2786
|
-
// Outputs
|
|
2830
|
+
// Outputs — checkedChange/disabledChange use EventEmitter to decouple from signal writes.
|
|
2831
|
+
this.checkedChange = new EventEmitter();
|
|
2832
|
+
this.disabledChange = new EventEmitter();
|
|
2787
2833
|
this.valueChange = output();
|
|
2788
|
-
this.checkedChange = output();
|
|
2789
2834
|
// Computed values
|
|
2790
2835
|
this.customStyles = computed(() => Object.assign({}, ...this.styles), ...(ngDevMode ? [{ debugName: "customStyles" }] : []));
|
|
2791
2836
|
this.state = computed(() => this.getState(), ...(ngDevMode ? [{ debugName: "state" }] : []));
|
|
@@ -2867,7 +2912,7 @@ class PshRadioComponent {
|
|
|
2867
2912
|
// Implementation requires radio group context
|
|
2868
2913
|
}
|
|
2869
2914
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: PshRadioComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2870
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: PshRadioComponent, isStandalone: true, selector: "psh-radio", inputs: {
|
|
2915
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: PshRadioComponent, isStandalone: true, selector: "psh-radio", inputs: { checkedInput: { classPropertyName: "checkedInput", publicName: "checked", isSignal: false, isRequired: false, transformFunction: null }, disabledInput: { classPropertyName: "disabledInput", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, success: { classPropertyName: "success", publicName: "success", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, labelPosition: { classPropertyName: "labelPosition", publicName: "labelPosition", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checkedChange: "checkedChange", disabledChange: "disabledChange", valueChange: "valueChange" }, host: { properties: { "class.radio-disabled": "disabled()", "class.radio-error": "!!error()", "class.radio-success": "!!success()", "class.radio-small": "size() === \"small\"", "class.radio-large": "size() === \"large\"", "attr.data-state": "state()" } }, queries: [{ propertyName: "radioText", first: true, predicate: [".radio-text"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"radio-container\">\n <label class=\"radio-label\" [class.label-left]=\"labelPosition() === 'left'\">\n <input\n type=\"radio\"\n class=\"radio-input\"\n [checked]=\"checked()\"\n [disabled]=\"disabled()\"\n [required]=\"required()\"\n [name]=\"name()\"\n [value]=\"value()\"\n [attr.aria-label]=\"computedAriaLabel()\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n [attr.aria-checked]=\"checked()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n (change)=\"handleChange()\"\n (keydown)=\"handleKeydown($event)\"\n />\n <span \n class=\"radio-control\"\n [class.error]=\"!!error()\"\n [class.success]=\"!!success()\"\n >\n <span class=\"radio-dot\"></span>\n </span>\n <span class=\"radio-text\">\n @if (label()) {\n {{ label() }}\n } @else {\n <ng-content>Radio</ng-content>\n }\n </span>\n </label>\n\n @if (error()) {\n <div [id]=\"errorMessageId()\" class=\"radio-error\" role=\"alert\">\n {{ error() }}\n </div>\n }\n\n @if (success()) {\n <div [id]=\"successMessageId()\" class=\"radio-success\" role=\"status\">\n {{ success() }}\n </div>\n }\n</div>", styles: [".radio-container{display:inline-flex;flex-direction:column;gap:var(--spacing-xs)}.radio-label{display:inline-flex;align-items:center;gap:var(--spacing-sm);cursor:pointer;-webkit-user-select:none;user-select:none;color:var(--text-color)}.radio-label.label-left{flex-direction:row-reverse;justify-content:space-between}.radio-input{position:absolute;opacity:0;width:0;height:0}.radio-control{display:flex;align-items:center;justify-content:center;width:var(--size-5);height:var(--size-5);min-width:var(--size-5);min-height:var(--size-5);border:var(--border-width-2) solid var(--surface-border);border-radius:var(--radius-full);background:var(--surface-card);transition:all var(--animation-duration-fast) var(--animation-easing-default);flex-shrink:0}.radio-dot{width:var(--size-2);height:var(--size-2);border-radius:var(--radius-full);background:var(--primary-color-text);opacity:0;transform:scale(.8);transition:all var(--animation-duration-fast) var(--animation-easing-default)}.radio-input:checked+.radio-control{background:var(--primary-color);border-color:var(--primary-color)}.radio-input:checked+.radio-control .radio-dot{opacity:1;transform:scale(1)}.radio-input:focus-visible+.radio-control{box-shadow:0 0 0 var(--focus-outline-width) var(--focus-ring-color)}:host(.radio-disabled) .radio-label{opacity:var(--opacity-disabled);cursor:not-allowed}:host(.radio-error) .radio-control{border-color:var(--danger-color)}:host(.radio-error) .radio-input:checked+.radio-control{background:var(--danger-color);border-color:var(--danger-color)}:host(.radio-success) .radio-control{border-color:var(--success-color)}:host(.radio-success) .radio-input:checked+.radio-control{background:var(--success-color);border-color:var(--success-color)}.radio-error{font-size:var(--font-size-sm);color:var(--danger-color)}.radio-success{font-size:var(--font-size-sm);color:var(--success-color)}:host(.radio-small) .radio-control{width:var(--size-4);height:var(--size-4);min-width:var(--size-4);min-height:var(--size-4)}:host(.radio-small) .radio-dot{width:var(--size-1-5);height:var(--size-1-5)}:host(.radio-small) .radio-text{font-size:var(--font-size-sm)}:host(.radio-large) .radio-control{width:var(--size-6);height:var(--size-6);min-width:var(--size-6);min-height:var(--size-6)}:host(.radio-large) .radio-dot{width:var(--size-3);height:var(--size-3)}:host(.radio-large) .radio-text{font-size:var(--font-size-lg)}.radio-text{color:var(--text-color)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2871
2916
|
}
|
|
2872
2917
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: PshRadioComponent, decorators: [{
|
|
2873
2918
|
type: Component,
|
|
@@ -2879,18 +2924,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
2879
2924
|
'[class.radio-large]': 'size() === "large"',
|
|
2880
2925
|
'[attr.data-state]': 'state()'
|
|
2881
2926
|
}, template: "<div class=\"radio-container\">\n <label class=\"radio-label\" [class.label-left]=\"labelPosition() === 'left'\">\n <input\n type=\"radio\"\n class=\"radio-input\"\n [checked]=\"checked()\"\n [disabled]=\"disabled()\"\n [required]=\"required()\"\n [name]=\"name()\"\n [value]=\"value()\"\n [attr.aria-label]=\"computedAriaLabel()\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n [attr.aria-checked]=\"checked()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n (change)=\"handleChange()\"\n (keydown)=\"handleKeydown($event)\"\n />\n <span \n class=\"radio-control\"\n [class.error]=\"!!error()\"\n [class.success]=\"!!success()\"\n >\n <span class=\"radio-dot\"></span>\n </span>\n <span class=\"radio-text\">\n @if (label()) {\n {{ label() }}\n } @else {\n <ng-content>Radio</ng-content>\n }\n </span>\n </label>\n\n @if (error()) {\n <div [id]=\"errorMessageId()\" class=\"radio-error\" role=\"alert\">\n {{ error() }}\n </div>\n }\n\n @if (success()) {\n <div [id]=\"successMessageId()\" class=\"radio-success\" role=\"status\">\n {{ success() }}\n </div>\n }\n</div>", styles: [".radio-container{display:inline-flex;flex-direction:column;gap:var(--spacing-xs)}.radio-label{display:inline-flex;align-items:center;gap:var(--spacing-sm);cursor:pointer;-webkit-user-select:none;user-select:none;color:var(--text-color)}.radio-label.label-left{flex-direction:row-reverse;justify-content:space-between}.radio-input{position:absolute;opacity:0;width:0;height:0}.radio-control{display:flex;align-items:center;justify-content:center;width:var(--size-5);height:var(--size-5);min-width:var(--size-5);min-height:var(--size-5);border:var(--border-width-2) solid var(--surface-border);border-radius:var(--radius-full);background:var(--surface-card);transition:all var(--animation-duration-fast) var(--animation-easing-default);flex-shrink:0}.radio-dot{width:var(--size-2);height:var(--size-2);border-radius:var(--radius-full);background:var(--primary-color-text);opacity:0;transform:scale(.8);transition:all var(--animation-duration-fast) var(--animation-easing-default)}.radio-input:checked+.radio-control{background:var(--primary-color);border-color:var(--primary-color)}.radio-input:checked+.radio-control .radio-dot{opacity:1;transform:scale(1)}.radio-input:focus-visible+.radio-control{box-shadow:0 0 0 var(--focus-outline-width) var(--focus-ring-color)}:host(.radio-disabled) .radio-label{opacity:var(--opacity-disabled);cursor:not-allowed}:host(.radio-error) .radio-control{border-color:var(--danger-color)}:host(.radio-error) .radio-input:checked+.radio-control{background:var(--danger-color);border-color:var(--danger-color)}:host(.radio-success) .radio-control{border-color:var(--success-color)}:host(.radio-success) .radio-input:checked+.radio-control{background:var(--success-color);border-color:var(--success-color)}.radio-error{font-size:var(--font-size-sm);color:var(--danger-color)}.radio-success{font-size:var(--font-size-sm);color:var(--success-color)}:host(.radio-small) .radio-control{width:var(--size-4);height:var(--size-4);min-width:var(--size-4);min-height:var(--size-4)}:host(.radio-small) .radio-dot{width:var(--size-1-5);height:var(--size-1-5)}:host(.radio-small) .radio-text{font-size:var(--font-size-sm)}:host(.radio-large) .radio-control{width:var(--size-6);height:var(--size-6);min-width:var(--size-6);min-height:var(--size-6)}:host(.radio-large) .radio-dot{width:var(--size-3);height:var(--size-3)}:host(.radio-large) .radio-text{font-size:var(--font-size-lg)}.radio-text{color:var(--text-color)}\n"] }]
|
|
2882
|
-
}], ctorParameters: () => [], propDecorators: {
|
|
2927
|
+
}], ctorParameters: () => [], propDecorators: { checkedInput: [{
|
|
2928
|
+
type: Input,
|
|
2929
|
+
args: ['checked']
|
|
2930
|
+
}], disabledInput: [{
|
|
2931
|
+
type: Input,
|
|
2932
|
+
args: ['disabled']
|
|
2933
|
+
}], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], success: [{ type: i0.Input, args: [{ isSignal: true, alias: "success", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], labelPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelPosition", required: false }] }], radioText: [{ type: i0.ContentChild, args: ['.radio-text', { isSignal: true }] }], checkedChange: [{
|
|
2934
|
+
type: Output
|
|
2935
|
+
}], disabledChange: [{
|
|
2936
|
+
type: Output
|
|
2937
|
+
}], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
|
|
2883
2938
|
|
|
2884
2939
|
class PshSelectComponent {
|
|
2940
|
+
set valueInput(v) { this.value.set(v); }
|
|
2941
|
+
set disabledInput(v) { this.disabled.set(v); }
|
|
2885
2942
|
constructor() {
|
|
2886
2943
|
this.elementRef = inject(ElementRef);
|
|
2887
2944
|
this.cdr = inject(ChangeDetectorRef);
|
|
2888
2945
|
this.destroyRef = inject(DestroyRef);
|
|
2889
2946
|
// Unique ID for the select
|
|
2890
2947
|
this.selectId = `select-${Math.random().toString(36).substring(2, 11)}`;
|
|
2891
|
-
//
|
|
2892
|
-
|
|
2893
|
-
|
|
2948
|
+
// CVA-managed state: plain signals + manual @Input/@Output to prevent
|
|
2949
|
+
// auto-emission during writeValue()/setDisabledState().
|
|
2950
|
+
// model() would auto-emit on .set(), breaking CVA semantics.
|
|
2951
|
+
this.value = signal(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
2952
|
+
this.disabled = signal(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
2894
2953
|
this.size = input('medium', ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
2895
2954
|
this.searchable = input(false, ...(ngDevMode ? [{ debugName: "searchable" }] : []));
|
|
2896
2955
|
this.multiple = input(false, ...(ngDevMode ? [{ debugName: "multiple" }] : []));
|
|
@@ -2923,8 +2982,10 @@ class PshSelectComponent {
|
|
|
2923
2982
|
this.hasLabelContentSignal = signal(false, ...(ngDevMode ? [{ debugName: "hasLabelContentSignal" }] : []));
|
|
2924
2983
|
this.initializedSignal = signal(false, ...(ngDevMode ? [{ debugName: "initializedSignal" }] : []));
|
|
2925
2984
|
this.activeDescendantId = signal(null, ...(ngDevMode ? [{ debugName: "activeDescendantId" }] : []));
|
|
2926
|
-
// Outputs
|
|
2927
|
-
|
|
2985
|
+
// Outputs — valueChange/disabledChange use EventEmitter to decouple from signal writes.
|
|
2986
|
+
// output() auto-subscribes to model signals; EventEmitter does not.
|
|
2987
|
+
this.valueChange = new EventEmitter();
|
|
2988
|
+
this.disabledChange = new EventEmitter();
|
|
2928
2989
|
this.opened = output();
|
|
2929
2990
|
this.closed = output();
|
|
2930
2991
|
this.scrollEnd = output();
|
|
@@ -3291,7 +3352,7 @@ class PshSelectComponent {
|
|
|
3291
3352
|
}, []);
|
|
3292
3353
|
}
|
|
3293
3354
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: PshSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3294
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: PshSelectComponent, isStandalone: true, selector: "psh-select", inputs: {
|
|
3355
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: PshSelectComponent, isStandalone: true, selector: "psh-select", inputs: { valueInput: { classPropertyName: "valueInput", publicName: "value", isSignal: false, isRequired: false, transformFunction: null }, disabledInput: { classPropertyName: "disabledInput", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, fullWidth: { classPropertyName: "fullWidth", publicName: "fullWidth", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, multiplePlaceholder: { classPropertyName: "multiplePlaceholder", publicName: "multiplePlaceholder", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, success: { classPropertyName: "success", publicName: "success", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, maxSelections: { classPropertyName: "maxSelections", publicName: "maxSelections", isSignal: true, isRequired: false, transformFunction: null }, minSelections: { classPropertyName: "minSelections", publicName: "minSelections", isSignal: true, isRequired: false, transformFunction: null }, compareWith: { classPropertyName: "compareWith", publicName: "compareWith", isSignal: true, isRequired: false, transformFunction: null }, searchConfig: { classPropertyName: "searchConfig", publicName: "searchConfig", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", disabledChange: "disabledChange", opened: "opened", closed: "closed", scrollEnd: "scrollEnd", searched: "searched" }, host: { properties: { "class.full-width": "fullWidth()", "class.small": "size() === \"small\"", "class.large": "size() === \"large\"", "class.error": "!!error()", "class.success": "!!success()", "class.disabled": "disabled()", "class.loading": "loading()" } }, providers: [
|
|
3295
3356
|
{
|
|
3296
3357
|
provide: NG_VALUE_ACCESSOR,
|
|
3297
3358
|
useExisting: PshSelectComponent,
|
|
@@ -3316,7 +3377,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
3316
3377
|
'[class.disabled]': 'disabled()',
|
|
3317
3378
|
'[class.loading]': 'loading()',
|
|
3318
3379
|
}, template: "<div class=\"select-container\">\n <!-- Label slot -->\n @if (label() || hasLabelContent()) {\n <label class=\"select-label\" [for]=\"selectId\" (click)=\"focusSelect()\" [class.required]=\"!!required()\">\n <ng-content select=\"[select-label]\" />\n @if (!hasLabelContent()) {\n {{ label() }}\n }\n </label>\n }\n\n <div class=\"select-trigger-wrapper\">\n <div\n class=\"select-trigger\"\n [id]=\"selectId\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-controls]=\"selectId + '-listbox'\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.aria-busy]=\"loading() ? 'true' : null\"\n [attr.aria-required]=\"required() ? 'true' : 'false'\"\n [attr.aria-invalid]=\"!!error()\"\n [attr.aria-label]=\"computedAriaLabel()\"\n [attr.aria-describedby]=\"error() ? 'error-message' : success() ? 'success-message' : hint() ? 'hint-message' : null\"\n [attr.aria-activedescendant]=\"activeDescendant()\"\n [attr.tabindex]=\"disabled() || loading() ? -1 : 0\"\n (click)=\"toggle()\"\n (keydown)=\"handleKeyDown($event)\"\n >\n <div class=\"select-value\">\n <span [class.placeholder]=\"!hasValue()\">{{ selectedLabel() }}</span>\n </div>\n\n <div class=\"select-actions\">\n @if (clearable() && hasValue() && !loading()) {\n <button\n type=\"button\"\n class=\"select-clear\"\n (click)=\"clear($event)\"\n [attr.aria-label]=\"'Effacer la s\u00E9lection'\"\n [tabindex]=\"disabled() ? -1 : 0\"\n >\n <i class=\"ph ph-x\" aria-hidden=\"true\"></i>\n </button>\n }\n @if (loading()) {\n <div class=\"select-loader-trigger\" aria-hidden=\"true\"></div>\n } @else {\n <i\n class=\"ph ph-caret-down select-arrow\"\n [class.open]=\"isOpen()\"\n aria-hidden=\"true\"\n ></i>\n }\n </div>\n </div>\n\n @if (isOpen()) {\n <div\n class=\"select-dropdown\"\n role=\"listbox\"\n [id]=\"selectId + '-listbox'\"\n [attr.aria-multiselectable]=\"multiple()\"\n >\n @if (searchable()) {\n <div class=\"select-search\">\n <input\n type=\"text\"\n [placeholder]=\"searchConfig().placeholder\"\n [value]=\"searchTerm()\"\n (input)=\"onSearch($event)\"\n (click)=\"$event.stopPropagation()\"\n [attr.aria-label]=\"searchConfig().placeholder\"\n />\n </div>\n }\n\n <div class=\"select-options\" (scroll)=\"onScroll($event)\">\n @if (loading()) {\n <div class=\"select-loading\">\n <div class=\"select-loader\"></div>\n </div>\n } @else if (filteredOptions().length === 0) {\n <div class=\"select-no-results\">\n Aucun r\u00E9sultat\n </div>\n } @else {\n @for (option of filteredOptions(); track getOptionKey(option)) {\n @if (isOptionGroup(option)) {\n <div class=\"select-group\">\n <div class=\"select-group-label\">{{ option.label }}</div>\n @for (groupOption of option.options; track getOptionKey(groupOption)) {\n <div\n class=\"select-option\"\n role=\"option\"\n [class.selected]=\"isSelected(groupOption)\"\n [class.focused]=\"isFocused(groupOption)\"\n [class.disabled]=\"option.disabled || groupOption.disabled\"\n [attr.aria-selected]=\"isSelected(groupOption)\"\n [attr.aria-disabled]=\"(option.disabled || groupOption.disabled) || null\"\n [attr.id]=\"selectId + '-option-' + groupOption.value\"\n [attr.tabindex]=\"option.disabled || groupOption.disabled ? -1 : 0\"\n (click)=\"!option.disabled && select(groupOption)\"\n (keydown)=\"handleOptionKeyDown($event, groupOption)\"\n >\n @if (multiple()) {\n <div class=\"select-checkbox\">\n <i class=\"ph ph-check\" aria-hidden=\"true\"></i>\n </div>\n }\n @if (groupOption.icon) {\n <i class=\"ph ph-{{ groupOption.icon }}\" aria-hidden=\"true\"></i>\n }\n <div class=\"option-content\">\n <div class=\"option-label\">{{ groupOption.label }}</div>\n @if (groupOption.description) {\n <div class=\"option-description\">{{ groupOption.description }}</div>\n }\n </div>\n </div>\n }\n </div>\n } @else {\n <div\n class=\"select-option\"\n role=\"option\"\n [class.selected]=\"isSelected(option)\"\n [class.focused]=\"isFocused(option)\"\n [class.disabled]=\"option.disabled\"\n [attr.aria-selected]=\"isSelected(option)\"\n [attr.aria-disabled]=\"option.disabled || null\"\n [attr.id]=\"selectId + '-option-' + option.value\"\n [attr.tabindex]=\"option.disabled ? -1 : 0\"\n (click)=\"select(option)\"\n (keydown)=\"handleOptionKeyDown($event, option)\"\n >\n @if (multiple()) {\n <div class=\"select-checkbox\">\n <i class=\"ph ph-check\" aria-hidden=\"true\"></i>\n </div>\n }\n @if (option.icon) {\n <i class=\"ph ph-{{ option.icon }}\" aria-hidden=\"true\"></i>\n }\n <div class=\"option-content\">\n <div class=\"option-label\">{{ option.label }}</div>\n @if (option.description) {\n <div class=\"option-description\">{{ option.description }}</div>\n }\n </div>\n </div>\n }\n }\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Error message slot -->\n @if (error()) {\n <div id=\"error-message\" class=\"select-error\" role=\"alert\">\n <ng-content select=\"[select-error]\">\n {{ error() }}\n </ng-content>\n </div>\n }\n\n <!-- Success message slot -->\n @if (success()) {\n <div id=\"success-message\" class=\"select-success\" role=\"status\">\n <ng-content select=\"[select-success]\">\n {{ success() }}\n </ng-content>\n </div>\n }\n\n <!-- Hint message slot -->\n @if (hint()) {\n <div id=\"hint-message\" class=\"select-hint\">\n <ng-content select=\"[select-hint]\">\n {{ hint() }}\n </ng-content>\n </div>\n }\n</div>", styles: [":host{display:block;width:100%;max-width:var(--select-max-width)}:host(.full-width){max-width:none}.select-container{width:100%}.select-trigger-wrapper{position:relative;width:100%}.select-label{display:block;color:var(--text-color);font-size:var(--font-size-sm);font-weight:500;margin-bottom:var(--spacing-xs);width:100%;cursor:pointer}.select-label.required:after{content:\"*\";color:var(--danger-color);margin-left:var(--spacing-xxs)}.select-trigger{display:flex;align-items:center;width:100%;min-width:12rem;height:var(--height-input-md);padding:0 var(--spacing-md);background:var(--surface-card);border:var(--border-width-1) solid var(--surface-border);border-radius:var(--border-radius);cursor:pointer;transition:all var(--animation-duration-normal) var(--animation-easing-default);outline:none}.select-trigger:hover{border-color:var(--primary-color)}:host(.disabled) .select-trigger:hover,:host(.loading) .select-trigger:hover{border-color:var(--surface-border)}.select-trigger:focus-visible{border-color:var(--primary-color);box-shadow:0 0 0 .125rem rgba(var(--primary-color-rgb),.2)}.select-value{display:flex;align-items:center;gap:var(--spacing-xs);flex:1;min-width:0;margin-right:var(--spacing-sm)}.select-value span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--text-color)}.select-value span.placeholder{color:var(--text-color-secondary)}.select-actions{display:flex;align-items:center;gap:var(--spacing-sm);flex-shrink:0}.select-arrow{transition:transform var(--animation-duration-normal) var(--animation-easing-default);font-size:var(--icon-size-sm);color:var(--text-color-secondary);flex-shrink:0}.select-arrow.open{transform:rotate(180deg)}.select-clear{display:flex;align-items:center;justify-content:center;width:var(--size-5);height:var(--size-5);padding:0;background:transparent;border:none;border-radius:50%;color:var(--text-color-secondary);cursor:pointer;transition:all var(--animation-duration-normal) var(--animation-easing-default);flex-shrink:0}.select-clear:hover{background:rgba(var(--danger-color-rgb),.1);color:var(--danger-color)}.select-dropdown{position:absolute;top:calc(100% + var(--spacing-xs));left:0;width:100%;background:var(--surface-card);border:var(--border-width-1) solid var(--surface-border);border-radius:var(--border-radius);box-shadow:var(--shadow-lg);z-index:1000;animation:fadeIn var(--animation-duration-normal) var(--animation-easing-default)}.select-search{display:flex;align-items:center;gap:var(--spacing-sm);padding:var(--spacing-sm);border-bottom:var(--border-width-1) solid var(--surface-border)}.select-search input{width:100%;padding:var(--spacing-xs) var(--spacing-sm);border:var(--border-width-1) solid var(--surface-border);border-radius:var(--border-radius);background:var(--surface-ground)}.select-search input:focus{outline:none;border-color:var(--primary-color)}.select-options{max-height:var(--dropdown-max-height);overflow-y:auto}.select-group{padding:var(--spacing-xs) 0}.select-group-label{padding:var(--spacing-xs) var(--spacing-md);color:var(--text-color-secondary);font-weight:500;font-size:var(--font-size-sm)}.select-option{display:flex;align-items:center;gap:var(--spacing-md);padding:var(--spacing-sm) var(--spacing-md);cursor:pointer;transition:all var(--animation-duration-normal) var(--animation-easing-default)}.select-option:hover:not(.disabled){background:var(--surface-hover)}.select-option.focused:not(.disabled){background:var(--surface-hover);outline:2px solid var(--primary-color);outline-offset:-2px}.select-option.selected{background:rgba(var(--primary-color-rgb),.1);color:var(--primary-color)}.select-option.selected.focused{background:rgba(var(--primary-color-rgb),.15);outline:2px solid var(--primary-color);outline-offset:-2px}.select-option.disabled{opacity:.6;cursor:not-allowed}.select-option i{font-size:var(--icon-size-md);color:var(--text-color-secondary);flex-shrink:0}.select-option.selected i{color:var(--primary-color)}.option-content{flex:1;min-width:0}.option-label{color:inherit;font-size:var(--font-size-base)}.option-description{color:var(--text-color-secondary);font-size:var(--font-size-sm);margin-top:var(--spacing-xs)}.select-checkbox{display:flex;align-items:center;justify-content:center;width:var(--select-checkbox-size);height:var(--select-checkbox-size);border:var(--border-width-2) solid var(--surface-border);border-radius:var(--border-radius);transition:all var(--animation-duration-normal) var(--animation-easing-default)}.selected .select-checkbox{background:var(--primary-gradient);border-color:var(--primary-color);color:var(--primary-color-text)}.select-no-results{padding:var(--spacing-md);text-align:center;color:var(--text-color-secondary)}.select-loading{padding:var(--spacing-md);text-align:center}.select-loader{width:var(--size-6);height:var(--size-6);border:var(--border-width-2) solid var(--surface-border);border-top-color:var(--primary-color);border-radius:50%;animation:spin var(--animation-duration-slow) linear infinite;margin:0 auto}.select-loader-trigger{width:var(--icon-size-sm);height:var(--icon-size-sm);border:var(--border-width-2) solid var(--surface-border);border-top-color:var(--primary-color);border-radius:50%;animation:spin var(--animation-duration-slow) linear infinite;flex-shrink:0}.select-error{margin-top:var(--spacing-xs);color:var(--danger-color);font-size:var(--font-size-sm)}.select-success{margin-top:var(--spacing-xs);color:var(--success-color);font-size:var(--font-size-sm)}.select-hint{font-size:var(--font-size-sm);color:var(--text-color-secondary);margin-top:var(--spacing-xs)}.virtual-scroll{position:relative;overflow:hidden}:host(.disabled) .select-trigger{background:var(--surface-ground);cursor:not-allowed;opacity:.6}:host(.loading) .select-trigger{cursor:wait;opacity:.7}:host(.error) .select-trigger{border-color:var(--danger-color)}:host(.success) .select-trigger{border-color:var(--success-color)}:host(.small) .select-trigger{height:var(--height-input-sm);font-size:var(--font-size-sm);padding:0 var(--spacing-sm)}:host(.small) .select-arrow{font-size:var(--icon-size-xs)}:host(.small) .select-value{margin-right:var(--spacing-xs)}:host(.small) .select-actions{gap:var(--spacing-xs)}:host(.small) .select-dropdown{font-size:var(--font-size-sm)}:host(.small) .select-search{padding:var(--spacing-xs)}:host(.small) .select-search input{padding:var(--spacing-xxs) var(--spacing-xs);font-size:var(--font-size-sm)}:host(.small) .select-option{padding:var(--spacing-xs) var(--spacing-sm);gap:var(--spacing-sm)}:host(.small) .select-option i{font-size:var(--icon-size-sm)}:host(.small) .option-label{font-size:var(--font-size-sm)}:host(.small) .option-description{font-size:var(--font-size-xs);margin-top:var(--spacing-xxs)}:host(.small) .select-group-label{padding:var(--spacing-xxs) var(--spacing-sm);font-size:var(--font-size-xs)}:host(.small) .select-checkbox{width:calc(var(--select-checkbox-size) * .85);height:calc(var(--select-checkbox-size) * .85)}:host(.large) .select-trigger{height:var(--height-input-lg);font-size:var(--font-size-lg);padding:0 var(--spacing-lg)}:host(.large) .select-arrow{font-size:var(--icon-size-md)}:host(.large) .select-value{margin-right:var(--spacing-md)}:host(.large) .select-actions{gap:var(--spacing-md)}:host(.large) .select-dropdown{font-size:var(--font-size-lg)}:host(.large) .select-search{padding:var(--spacing-md)}:host(.large) .select-search input{padding:var(--spacing-sm) var(--spacing-md);font-size:var(--font-size-lg)}:host(.large) .select-option{padding:var(--spacing-md) var(--spacing-lg);gap:var(--spacing-lg)}:host(.large) .select-option i{font-size:var(--icon-size-lg)}:host(.large) .option-label{font-size:var(--font-size-lg)}:host(.large) .option-description{font-size:var(--font-size-base);margin-top:var(--spacing-xs)}:host(.large) .select-group-label{padding:var(--spacing-sm) var(--spacing-lg);font-size:var(--font-size-base)}:host(.large) .select-checkbox{width:calc(var(--select-checkbox-size) * 1.15);height:calc(var(--select-checkbox-size) * 1.15)}@media (max-width: 36em){:host{max-width:none}}@keyframes fadeIn{0%{opacity:0;transform:translateY(calc(-1 * var(--spacing-sm)))}to{opacity:1;transform:translateY(0)}}@keyframes spin{to{transform:rotate(360deg)}}\n"] }]
|
|
3319
|
-
}], ctorParameters: () => [], propDecorators: {
|
|
3380
|
+
}], ctorParameters: () => [], propDecorators: { valueInput: [{
|
|
3381
|
+
type: Input,
|
|
3382
|
+
args: ['value']
|
|
3383
|
+
}], disabledInput: [{
|
|
3384
|
+
type: Input,
|
|
3385
|
+
args: ['disabled']
|
|
3386
|
+
}], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], multiplePlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiplePlaceholder", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], success: [{ type: i0.Input, args: [{ isSignal: true, alias: "success", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], maxSelections: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSelections", required: false }] }], minSelections: [{ type: i0.Input, args: [{ isSignal: true, alias: "minSelections", required: false }] }], compareWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "compareWith", required: false }] }], searchConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchConfig", required: false }] }], valueChange: [{
|
|
3387
|
+
type: Output
|
|
3388
|
+
}], disabledChange: [{
|
|
3389
|
+
type: Output
|
|
3390
|
+
}], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], scrollEnd: [{ type: i0.Output, args: ["scrollEnd"] }], searched: [{ type: i0.Output, args: ["searched"] }] } });
|
|
3320
3391
|
|
|
3321
3392
|
const SIDEBAR_CONFIG = new InjectionToken('SIDEBAR_CONFIG', {
|
|
3322
3393
|
factory: () => ({
|
|
@@ -3819,12 +3890,17 @@ class PshSwitchComponent {
|
|
|
3819
3890
|
this.switchInput = viewChild('switchInput', ...(ngDevMode ? [{ debugName: "switchInput" }] : []));
|
|
3820
3891
|
this.onChange = (value) => { };
|
|
3821
3892
|
this.onTouched = () => { };
|
|
3822
|
-
//
|
|
3823
|
-
|
|
3824
|
-
this.
|
|
3825
|
-
this.
|
|
3826
|
-
|
|
3827
|
-
this.
|
|
3893
|
+
// CVA-managed state: plain signals + manual @Input/@Output to prevent
|
|
3894
|
+
// auto-emission during writeValue()/setDisabledState().
|
|
3895
|
+
this.checked = signal(this.config.checked ?? false, ...(ngDevMode ? [{ debugName: "checked" }] : []));
|
|
3896
|
+
this.disabled = signal(this.config.disabled ?? false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
3897
|
+
// Outputs — EventEmitter to decouple from signal writes.
|
|
3898
|
+
this.checkedChange = new EventEmitter();
|
|
3899
|
+
this.disabledChange = new EventEmitter();
|
|
3900
|
+
// Configuration inputs (not CVA-managed, not written internally)
|
|
3901
|
+
this.required = input(this.config.required ?? false, ...(ngDevMode ? [{ debugName: "required" }] : []));
|
|
3902
|
+
this.size = input(this.config.size ?? 'medium', ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
3903
|
+
this.labelPosition = input(this.config.labelPosition ?? 'right', ...(ngDevMode ? [{ debugName: "labelPosition" }] : []));
|
|
3828
3904
|
// Regular inputs
|
|
3829
3905
|
this.label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
3830
3906
|
this.error = input('', ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
@@ -3848,10 +3924,13 @@ class PshSwitchComponent {
|
|
|
3848
3924
|
return ids.length > 0 ? ids.join(' ') : null;
|
|
3849
3925
|
}, ...(ngDevMode ? [{ debugName: "describedBy" }] : []));
|
|
3850
3926
|
}
|
|
3927
|
+
set checkedInput(v) { this.checked.set(v); }
|
|
3928
|
+
set disabledInput(v) { this.disabled.set(v); }
|
|
3851
3929
|
toggle() {
|
|
3852
3930
|
if (!this.disabled()) {
|
|
3853
3931
|
this.checked.update(v => !v);
|
|
3854
3932
|
this.onChange(this.checked());
|
|
3933
|
+
this.checkedChange.emit(this.checked());
|
|
3855
3934
|
this.onTouched();
|
|
3856
3935
|
}
|
|
3857
3936
|
}
|
|
@@ -3882,7 +3961,7 @@ class PshSwitchComponent {
|
|
|
3882
3961
|
}
|
|
3883
3962
|
}
|
|
3884
3963
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: PshSwitchComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3885
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: PshSwitchComponent, isStandalone: true, selector: "psh-switch", inputs: {
|
|
3964
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: PshSwitchComponent, isStandalone: true, selector: "psh-switch", inputs: { checkedInput: { classPropertyName: "checkedInput", publicName: "checked", isSignal: false, isRequired: false, transformFunction: null }, disabledInput: { classPropertyName: "disabledInput", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, labelPosition: { classPropertyName: "labelPosition", publicName: "labelPosition", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, success: { classPropertyName: "success", publicName: "success", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checkedChange: "checkedChange", disabledChange: "disabledChange" }, host: { properties: { "class.switch-wrapper": "true", "class.switch-disabled": "disabled()", "class.switch-error": "!!error()", "class.switch-success": "!!success()" } }, providers: [{
|
|
3886
3965
|
provide: NG_VALUE_ACCESSOR,
|
|
3887
3966
|
useExisting: PshSwitchComponent,
|
|
3888
3967
|
multi: true
|
|
@@ -3900,7 +3979,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
3900
3979
|
'[class.switch-error]': '!!error()',
|
|
3901
3980
|
'[class.switch-success]': '!!success()'
|
|
3902
3981
|
}, template: "<div\n class=\"switch-container\"\n [class.small]=\"size() === 'small'\"\n [class.large]=\"size() === 'large'\"\n>\n <label class=\"switch-label\" [class]=\"labelPosition() === 'left' ? 'label-left' : 'label-right'\">\n <input\n #switchInput\n type=\"checkbox\"\n class=\"switch-input\"\n [id]=\"id()\"\n [name]=\"name() || id()\"\n [checked]=\"checked()\"\n [disabled]=\"disabled()\"\n [required]=\"required()\"\n [attr.aria-label]=\"computedAriaLabel()\"\n [attr.aria-required]=\"required()\"\n [attr.aria-invalid]=\"!!error()\"\n [attr.aria-checked]=\"checked()\"\n [attr.aria-describedby]=\"describedBy()\"\n (change)=\"toggle()\"\n />\n <span class=\"switch-control\">\n <span class=\"switch-thumb\"></span>\n </span>\n <span class=\"switch-text\">\n @if (label()) {\n {{ label() }}\n } @else {\n <ng-content>Switch</ng-content>\n }\n </span>\n </label>\n\n @if (error()) {\n <div [id]=\"errorId()!\" class=\"switch-error\" role=\"alert\" aria-live=\"polite\">\n {{ error() }}\n </div>\n }\n\n @if (success()) {\n <div [id]=\"successId()!\" class=\"switch-success\" role=\"status\" aria-live=\"polite\">\n {{ success() }}\n </div>\n }\n</div>", styles: [".switch-wrapper{display:inline-block}.switch-container{display:inline-flex;flex-direction:column;gap:var(--spacing-xs)}.switch-label{display:inline-flex;align-items:center;cursor:pointer;-webkit-user-select:none;user-select:none;color:var(--text-color);width:100%}.switch-label.label-right{flex-direction:row;gap:var(--spacing-sm)}.switch-label.label-left{flex-direction:row-reverse;justify-content:space-between;gap:var(--spacing-md)}.switch-input{position:absolute;opacity:0;width:0;height:0}.switch-control{position:relative;display:inline-block;width:var(--size-10);height:var(--size-5-5);background:var(--surface-border);border-radius:var(--radius-full);transition:background var(--animation-duration-fast) var(--animation-easing-default),border-color var(--animation-duration-fast) var(--animation-easing-default)}.switch-thumb{position:absolute;top:var(--size-0-5);left:var(--size-0-5);width:var(--size-4-5);height:var(--size-4-5);background:var(--surface-card);border-radius:var(--radius-full);transition:transform var(--animation-duration-fast) var(--animation-easing-default),left var(--animation-duration-fast) var(--animation-easing-default)}.switch-input:checked+.switch-control{background:var(--primary-color)}.switch-input:checked+.switch-control .switch-thumb{left:calc(100% - var(--size-4-5) - var(--size-0-5))}.switch-input:focus-visible+.switch-control{outline:var(--focus-outline-width) var(--focus-outline-style) var(--focus-outline-color);outline-offset:var(--focus-outline-offset);box-shadow:0 0 0 var(--focus-ring-width) var(--focus-ring-color)}.switch-wrapper.switch-disabled .switch-label{opacity:var(--opacity-disabled);cursor:not-allowed;pointer-events:none}.switch-wrapper.switch-error .switch-input:not(:checked)+.switch-control{background:color-mix(in srgb,var(--danger-color) 15%,var(--surface-border));border:var(--border-width-2) solid var(--danger-color)}.switch-wrapper.switch-error .switch-input:focus-visible+.switch-control{box-shadow:0 0 0 var(--focus-ring-width) var(--focus-ring-error)}.switch-wrapper.switch-success .switch-input:checked+.switch-control{background:var(--success-color)}.switch-wrapper.switch-success .switch-input:focus-visible+.switch-control{box-shadow:0 0 0 var(--focus-ring-width) var(--focus-ring-success)}.switch-error{font-size:var(--font-size-sm);color:var(--danger-color)}.switch-success{font-size:var(--font-size-sm);color:var(--success-color)}.switch-container.small .switch-control{width:var(--size-8-5);height:var(--size-5)}.switch-container.small .switch-thumb{width:var(--size-4);height:var(--size-4)}.switch-container.small .switch-input:checked+.switch-control .switch-thumb{left:calc(100% - var(--size-4) - var(--size-0-5))}.switch-container.large .switch-control{width:var(--size-12);height:var(--size-6-5)}.switch-container.large .switch-thumb{width:var(--size-5-5);height:var(--size-5-5)}.switch-container.large .switch-input:checked+.switch-control .switch-thumb{left:calc(100% - var(--size-5-5) - var(--size-0-5))}@media (prefers-reduced-motion: reduce){.switch-control,.switch-thumb{transition:none}}\n"] }]
|
|
3903
|
-
}], propDecorators: { switchInput: [{ type: i0.ViewChild, args: ['switchInput', { isSignal: true }] }],
|
|
3982
|
+
}], propDecorators: { switchInput: [{ type: i0.ViewChild, args: ['switchInput', { isSignal: true }] }], checkedInput: [{
|
|
3983
|
+
type: Input,
|
|
3984
|
+
args: ['checked']
|
|
3985
|
+
}], disabledInput: [{
|
|
3986
|
+
type: Input,
|
|
3987
|
+
args: ['disabled']
|
|
3988
|
+
}], checkedChange: [{
|
|
3989
|
+
type: Output
|
|
3990
|
+
}], disabledChange: [{
|
|
3991
|
+
type: Output
|
|
3992
|
+
}], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], labelPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelPosition", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], success: [{ type: i0.Input, args: [{ isSignal: true, alias: "success", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }] } });
|
|
3904
3993
|
|
|
3905
3994
|
/**
|
|
3906
3995
|
* Token d'injection pour la configuration globale de la barre d'onglets
|