@yuuvis/client-framework 3.22.1 → 3.23.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.
@@ -9,7 +9,7 @@ import { MatSelectModule } from '@angular/material/select';
9
9
  import { SystemService, TranslateService, Classification, TranslatePipe, Situation, Utils, Operator, OperatorLabel, CatalogService, LocaleNumberPipe, FileSizePipe, IdmService, UserService, AppCacheService, FREE_TEXT_OPTION, USER_ID_REGEX, STORAGE_ROLES_KEY, SearchUtils, LocaleDatePipe, SearchService, DmsService, ObjectConfigService, DmsObject, BaseObjectTypeField, ClassificationPrefix } from '@yuuvis/client-core';
10
10
  import { AbstractMatFormField, injectNgControl, FormTranslateService, DialogComponent, ScrollButtonsComponent } from '@yuuvis/client-framework/common';
11
11
  import * as i1$3 from '@angular/common';
12
- import { NgClass, CommonModule } from '@angular/common';
12
+ import { CommonModule, NgClass } from '@angular/common';
13
13
  import { MatButtonModule } from '@angular/material/button';
14
14
  import { MAT_DIALOG_DATA, MatDialogRef, MatDialogModule, MatDialog } from '@angular/material/dialog';
15
15
  import * as i2 from '@angular/material/icon';
@@ -152,6 +152,96 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImpo
152
152
  args: [{ selector: 'yuv-catalog', imports: [MatSelectModule, ReactiveFormsModule, TranslatePipe], providers: [{ provide: MatFormFieldControl, useExisting: CatalogComponent }], template: "<mat-select [multiple]=\"multiple()\" [disabled]=\"readonly()\" [formControl]=\"formCtrl\">\n @if (!multiple() && !required) {\n <mat-option [value]=\"null\">{{ 'yuv.form.element.catalog.option.none' | translate }}</mat-option>\n }\n @for (o of _options(); track o) {\n <mat-option [value]=\"o.value\">{{ o.label }}</mat-option>\n }\n</mat-select>\n" }]
153
153
  }], propDecorators: { readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], classifications: [{ type: i0.Input, args: [{ isSignal: true, alias: "classifications", required: false }] }], situation: [{ type: i0.Input, args: [{ isSignal: true, alias: "situation", required: false }] }] } });
154
154
 
155
+ const HEX_PATTERN = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
156
+ /**
157
+ * Form input for a color value. Renders a hex text input alongside a native color picker
158
+ * swatch; both stay in sync. The value is a hex color string (e.g. `#2A70AC`).
159
+ *
160
+ * Implements `ControlValueAccessor` so it can be used within Angular forms and Material form
161
+ * fields.
162
+ *
163
+ * @example
164
+ * <mat-form-field>
165
+ * <mat-label>Primary color</mat-label>
166
+ * <yuv-color formControlName="primaryColor"></yuv-color>
167
+ * </mat-form-field>
168
+ */
169
+ class ColorComponent extends AbstractMatFormField {
170
+ constructor() {
171
+ super(...arguments);
172
+ this.#dRef = inject(DestroyRef);
173
+ /** the color swatch (native `<input type="color">`, always a full 6-digit hex) */
174
+ this.colorFc = new FormControl('#000000', { nonNullable: true });
175
+ /** the editable hex text input (source of truth for the value) */
176
+ this.textFc = new FormControl(null);
177
+ this.ngControl = injectNgControl(this);
178
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
179
+ this.propagateChange = (_) => { };
180
+ }
181
+ #dRef;
182
+ writeValue(value) {
183
+ this.value = value;
184
+ this.textFc.setValue(value ?? null, { emitEvent: false });
185
+ if (value && HEX_PATTERN.test(value)) {
186
+ this.colorFc.setValue(value, { emitEvent: false });
187
+ }
188
+ }
189
+ registerOnChange(fn) {
190
+ this.propagateChange = fn;
191
+ }
192
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
193
+ registerOnTouched() { }
194
+ setDisabledState(isDisabled) {
195
+ if (isDisabled) {
196
+ this.colorFc.disable();
197
+ this.textFc.disable();
198
+ }
199
+ else {
200
+ this.colorFc.enable();
201
+ this.textFc.enable();
202
+ }
203
+ this.disabled = isDisabled;
204
+ }
205
+ ngOnInit() {
206
+ const validators = [(control) => this.#hexValidator(control.value)];
207
+ if (this.required)
208
+ validators.push(() => (this.value ? null : { required: true }));
209
+ this.textFc.setValidators(validators);
210
+ this.textFc.statusChanges.pipe(takeUntilDestroyed(this.#dRef)).subscribe(() => {
211
+ this.errorState = FormUtils.getErrorState(this.textFc);
212
+ this.ngControl?.control?.setErrors(this.textFc.errors);
213
+ });
214
+ // hex text drives the value; keep the swatch in sync when the text is a valid hex
215
+ this.textFc.valueChanges.pipe(takeUntilDestroyed(this.#dRef)).subscribe((v) => {
216
+ const hex = v?.trim() || null;
217
+ this.value = hex;
218
+ if (hex && HEX_PATTERN.test(hex)) {
219
+ this.colorFc.setValue(hex, { emitEvent: false });
220
+ }
221
+ this.propagateChange(hex);
222
+ });
223
+ // swatch changes update the hex text (which re-propagates)
224
+ this.colorFc.valueChanges.pipe(takeUntilDestroyed(this.#dRef)).subscribe((v) => {
225
+ this.textFc.setValue(v);
226
+ });
227
+ this.textFc.updateValueAndValidity();
228
+ }
229
+ ngOnDestroy() {
230
+ super.onNgOnDestroy();
231
+ }
232
+ #hexValidator(value) {
233
+ if (!value)
234
+ return null;
235
+ return HEX_PATTERN.test(value.trim()) ? null : { color: { valid: false } };
236
+ }
237
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: ColorComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
238
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.20", type: ColorComponent, isStandalone: true, selector: "yuv-color", providers: [{ provide: MatFormFieldControl, useExisting: ColorComponent }], usesInheritance: true, ngImport: i0, template: "<span class=\"yuv-color\">\n <label class=\"yuv-color__swatch\" [style.background-color]=\"colorFc.value\">\n <input type=\"color\" [formControl]=\"colorFc\" aria-hidden=\"true\" tabindex=\"-1\" />\n </label>\n <input class=\"yuv-color__hex\" type=\"text\" autocomplete=\"off\" spellcheck=\"false\" [formControl]=\"textFc\" />\n</span>\n", styles: [".yuv-color{display:inline-flex;align-items:center;gap:var(--ymt-spacing-xs);width:100%;margin-block-start:var(--ymt-spacing-xs)}.yuv-color__swatch{position:relative;flex:0 0 auto;inline-size:var(--ymt-sizing-m);block-size:var(--ymt-sizing-m);border-radius:var(--ymt-corner-xs);border:var(--ymt-outline-width) solid var(--ymt-outline-variant);overflow:hidden;cursor:pointer;outline:2px solid currentColor;outline-offset:-1px}.yuv-color__swatch input[type=color]{position:absolute;inset:0;inline-size:100%;block-size:100%;padding:0;border:none;opacity:0;cursor:pointer}.yuv-color__hex{flex:1 1 auto;min-inline-size:0;border:none;outline:none;background:transparent;color:var(--ymt-text-color);font:var(--ymt-font-body)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] }); }
239
+ }
240
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: ColorComponent, decorators: [{
241
+ type: Component,
242
+ args: [{ selector: 'yuv-color', standalone: true, imports: [CommonModule, ReactiveFormsModule], providers: [{ provide: MatFormFieldControl, useExisting: ColorComponent }], template: "<span class=\"yuv-color\">\n <label class=\"yuv-color__swatch\" [style.background-color]=\"colorFc.value\">\n <input type=\"color\" [formControl]=\"colorFc\" aria-hidden=\"true\" tabindex=\"-1\" />\n </label>\n <input class=\"yuv-color__hex\" type=\"text\" autocomplete=\"off\" spellcheck=\"false\" [formControl]=\"textFc\" />\n</span>\n", styles: [".yuv-color{display:inline-flex;align-items:center;gap:var(--ymt-spacing-xs);width:100%;margin-block-start:var(--ymt-spacing-xs)}.yuv-color__swatch{position:relative;flex:0 0 auto;inline-size:var(--ymt-sizing-m);block-size:var(--ymt-sizing-m);border-radius:var(--ymt-corner-xs);border:var(--ymt-outline-width) solid var(--ymt-outline-variant);overflow:hidden;cursor:pointer;outline:2px solid currentColor;outline-offset:-1px}.yuv-color__swatch input[type=color]{position:absolute;inset:0;inline-size:100%;block-size:100%;padding:0;border:none;opacity:0;cursor:pointer}.yuv-color__hex{flex:1 1 auto;min-inline-size:0;border:none;outline:none;background:transparent;color:var(--ymt-text-color);font:var(--ymt-font-body)}\n"] }]
243
+ }] });
244
+
155
245
  class EditTableDataComponent {
156
246
  constructor() {
157
247
  this.#fb = inject(FormBuilder);
@@ -2903,5 +2993,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImpo
2903
2993
  * Generated bundle index. Do not edit.
2904
2994
  */
2905
2995
 
2906
- export { CatalogComponent, DataGridComponent, DatetimeComponent, DatetimeRangeComponent, DynamicCatalogComponent, FormUtils, I18nCatalogComponent, NumberComponent, NumberRangeComponent, OrganizationComponent, OrganizationSetComponent, RangeSelectDateComponent, RangeSelectFilesizeComponent, ReferenceComponent, StringComponent, YuvFormsModule };
2996
+ export { CatalogComponent, ColorComponent, DataGridComponent, DatetimeComponent, DatetimeRangeComponent, DynamicCatalogComponent, FormUtils, I18nCatalogComponent, NumberComponent, NumberRangeComponent, OrganizationComponent, OrganizationSetComponent, RangeSelectDateComponent, RangeSelectFilesizeComponent, ReferenceComponent, StringComponent, YuvFormsModule };
2907
2997
  //# sourceMappingURL=yuuvis-client-framework-forms.mjs.map