@moatamed-sce/ui-components 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -13,7 +13,7 @@ import * as i1$1 from 'primeng/button';
|
|
|
13
13
|
import { ButtonModule, Button } from 'primeng/button';
|
|
14
14
|
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
|
|
15
15
|
import { ToggleSwitch } from 'primeng/toggleswitch';
|
|
16
|
-
import { sanitizeNonNegativeNumericInput, DigitPipe, ModalService, LanguageService, formatFileSize as formatFileSize$1, LOADING_DELAY_MS, SCE_ICON_ASSETS_BASE_TOKEN, resolveSceIconAssetPath, getEngineeringOfficeVerificationBadgeVariant, LoadingService, truncateWords as truncateWords$1, OrganizationServiceProviderStatus, RoutePrefetchDirective, SceRouteActiveDirective, ThemeService, ConnectivityService, shouldShowUserProfilePhoto, isGeoLookupRestricted, JEDDAH_MAP_CENTER, NominatimService, GeoMapPositionValidationService, ToastService, resolveInitialCenter, mapPositionValidationMessage, PHONE_CONFIG, INPUT_TYPES, VALIDATION_LENGTHS, ERROR_KEYS, DEFAULT_TOAST_KEY, TOAST_BASE_Z_INDEX, downloadUrlAsFile, downloadBlob, copyToClipboard, LocalizedDatePipe, ImgFallbackDirective, REGEX, ExportPdfService } from '@moatamed-sce/core';
|
|
16
|
+
import { sanitizeNonNegativeNumericInput, DigitPipe, ModalService, LanguageService, formatFileSize as formatFileSize$1, LOADING_DELAY_MS, SCE_ICON_ASSETS_BASE_TOKEN, resolveSceIconAssetPath, getEngineeringOfficeVerificationBadgeVariant, LoadingService, truncateWords as truncateWords$1, OrganizationServiceProviderStatus, RoutePrefetchDirective, SceRouteActiveDirective, ThemeService, ConnectivityService, shouldShowUserProfilePhoto, isGeoLookupRestricted, JEDDAH_MAP_CENTER, NominatimService, GeoMapPositionValidationService, ToastService, resolveInitialCenter, mapPositionValidationMessage, PHONE_CONFIG, INPUT_TYPES, VALIDATION_LENGTHS, ERROR_KEYS, DEFAULT_TOAST_KEY, TOAST_BASE_Z_INDEX, SceLibraryAccessService, SCE_LIBRARY_ACCESS_CONTACT, downloadUrlAsFile, downloadBlob, copyToClipboard, LocalizedDatePipe, ImgFallbackDirective, REGEX, ExportPdfService } from '@moatamed-sce/core';
|
|
17
17
|
import { DOCUMENT, NgTemplateOutlet, isPlatformBrowser, Location, CommonModule, DecimalPipe, DatePipe } from '@angular/common';
|
|
18
18
|
import { Dialog } from 'primeng/dialog';
|
|
19
19
|
import { HttpClient } from '@angular/common/http';
|
|
@@ -52,6 +52,7 @@ import { RadioButtonModule } from 'primeng/radiobutton';
|
|
|
52
52
|
import * as i1$4 from 'primeng/drawer';
|
|
53
53
|
import { DrawerModule } from 'primeng/drawer';
|
|
54
54
|
|
|
55
|
+
/** Radio group that renders each option as a selectable card with an optional icon and description; unlike the other sce field components it is a ControlValueAccessor, so it accepts `formControlName`. */
|
|
55
56
|
class SceCardRadioGroupComponent {
|
|
56
57
|
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
57
58
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
@@ -113,6 +114,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
113
114
|
], template: "@if (label()) {\n <p class=\"sce-card-radio-group__label\">{{ label() }}</p>\n}\n\n<div class=\"sce-card-radio-group__grid\" role=\"radiogroup\" [attr.aria-label]=\"label() || null\">\n @for (view of optionViews(); track view.option.value) {\n <div\n class=\"sce-card-radio-group__card\"\n [class.sce-card-radio-group__card--selected]=\"view.selected\"\n [class.sce-card-radio-group__card--disabled]=\"isDisabled() || disabled()\"\n [attr.aria-checked]=\"view.selected\"\n [attr.aria-disabled]=\"isDisabled() || disabled()\"\n role=\"radio\"\n tabindex=\"0\"\n (click)=\"select(view.option)\"\n (keydown.space)=\"select(view.option)\"\n (keydown.enter)=\"select(view.option)\"\n >\n <span class=\"sce-card-radio-group__dot-ring\" [class.sce-card-radio-group__dot-ring--selected]=\"view.selected\" aria-hidden=\"true\">\n @if (view.selected) {\n <span class=\"sce-card-radio-group__dot\"></span>\n }\n </span>\n\n <span class=\"sce-card-radio-group__content\">\n @if (view.option.icon) {\n <img class=\"sce-card-radio-group__icon\" [src]=\"view.option.icon\" alt=\"\" aria-hidden=\"true\" />\n }\n <span class=\"sce-card-radio-group__option-label\" [class.sce-card-radio-group__option-label--selected]=\"view.selected\">\n {{ view.option.label }}\n </span>\n @if (view.option.description) {\n <span class=\"sce-card-radio-group__description\">\n {{ view.option.description }}\n </span>\n }\n </span>\n </div>\n }\n</div>\n", styles: [":host{display:block}.sce-card-radio-group__label{margin-block-end:var(--space-12);font-size:var(--font-size-md);font-weight:600;color:var(--text-text-primary-900);text-align:start}.sce-card-radio-group__grid{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--space-12)}@media(max-width:768px){.sce-card-radio-group__grid{grid-template-columns:1fr}}.sce-card-radio-group__card{display:flex;flex-direction:row-reverse;justify-content:space-between;align-items:center;gap:var(--space-16);padding-block:var(--space-16);padding-inline:var(--space-24);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl);background:var(--color-surface);cursor:pointer;transition:border-color var(--transition-base),box-shadow var(--transition-base)}.sce-card-radio-group__card:hover:not(.sce-card-radio-group__card--disabled){border-color:var(--color-neutral-300)}.sce-card-radio-group__card:focus-visible{outline:2px solid var(--color-sucess-500);outline-offset:2px}.sce-card-radio-group__card--selected{border-color:var(--color-sucess-500)}.sce-card-radio-group__card--disabled{opacity:.6;cursor:not-allowed;pointer-events:none}.sce-card-radio-group__dot-ring{display:flex;align-items:center;justify-content:center;flex-shrink:0;block-size:var(--size-20);inline-size:var(--size-20);border:2px solid var(--color-neutral-300);border-radius:var(--radius-full);transition:border-color var(--transition-base)}.sce-card-radio-group__dot-ring--selected{border-color:var(--color-sucess-500)}.sce-card-radio-group__dot{block-size:var(--space-10);inline-size:var(--space-10);border-radius:var(--radius-full);background-color:var(--color-sucess-500)}.sce-card-radio-group__content{display:flex;flex:1;flex-direction:column;text-align:start}.sce-card-radio-group__icon{block-size:var(--size-24);inline-size:var(--size-24);object-fit:contain;margin-block-end:var(--space-4)}.sce-card-radio-group__option-label{font-size:var(--font-size-md);font-weight:700;color:var(--text-text-primary-900);transition:color var(--transition-base)}.sce-card-radio-group__option-label--selected{color:var(--text-text-primary-900)}.sce-card-radio-group__description{display:block;margin-block-start:var(--space-4);font-size:var(--font-size-xs);color:var(--color-neutral-500)}\n"] }]
|
|
114
115
|
}], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
|
|
115
116
|
|
|
117
|
+
/** Shared form-field wrapper that renders the label, required marker, projected control, help text and error message for the other sce field components; `id` and `label` are required. */
|
|
116
118
|
class SceFieldComponent {
|
|
117
119
|
id = input.required(...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
118
120
|
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
@@ -209,6 +211,7 @@ function createFieldErrorSignal(sources) {
|
|
|
209
211
|
});
|
|
210
212
|
}
|
|
211
213
|
|
|
214
|
+
/** Single-line text form field built on PrimeNG InputText, with a shared validation engine and an optional inline or absolute prefix; validation is opt-in, since `validationMode` defaults to `'never'`. */
|
|
212
215
|
class SceTextFieldComponent {
|
|
213
216
|
mirrorLabelAsPlaceholder = inject(SCE_MIRROR_LABEL_AS_PLACEHOLDER, {
|
|
214
217
|
optional: true,
|
|
@@ -299,6 +302,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
299
302
|
args: [{ selector: 'sce-text-field', standalone: true, imports: [FormsModule, InputText, SceFieldComponent], encapsulation: ViewEncapsulation.None, host: { class: 'sce-text-field' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<sce-field [id]=\"id()\" [label]=\"label()\" [required]=\"required()\" [helpText]=\"helpText()\" [error]=\"computedError()\">\n <div\n class=\"sce-text-field__control\"\n [class.inlineContainer]=\"isInlinePrefix()\"\n [class.inlineContainerInvalid]=\"isInlinePrefix() && computedError()\"\n [attr.dir]=\"dir() ?? null\"\n >\n @if (prefix() && prefixMode() === 'absolute') {\n <span class=\"sce-text-field__prefix\" aria-hidden=\"true\">{{ prefix() }}</span>\n }\n <input\n pInputText\n [id]=\"id()\"\n [class]=\"inputClasses()\"\n [type]=\"type()\"\n [attr.dir]=\"dir() ?? null\"\n [attr.name]=\"name() ?? null\"\n [attr.autocomplete]=\"autocomplete() ?? null\"\n [attr.maxlength]=\"maxLength() ?? null\"\n [attr.list]=\"listId() ?? null\"\n [placeholder]=\"resolvedPlaceholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [ngModel]=\"value()\"\n (ngModelChange)=\"onValueChange($event)\"\n (focus)=\"onFocus($event)\"\n (blur)=\"onBlur($event)\"\n [attr.aria-invalid]=\"computedError() ? true : null\"\n />\n @if (prefix() && prefixMode() === 'inline') {\n <span class=\"inlinePrefix\" aria-hidden=\"true\">{{ prefix() }}</span>\n }\n </div>\n</sce-field>\n", styles: ["@charset \"UTF-8\";sce-text-field{display:block}sce-text-field .w-full{width:100%}.sce-text-field__control{position:relative;display:flex;align-items:center;width:100%}.sce-text-field__control[dir=rtl] .p-inputtext.w-full{direction:ltr;text-align:end}.sce-text-field__control[dir=rtl] .p-inputtext.w-full::placeholder{text-align:end}.sce-text-field__control[dir=rtl] .inlineContainer .inlineInput.p-inputtext{direction:ltr;text-align:end}.sce-text-field__control[dir=rtl] .inlineContainer .inlineInput.p-inputtext::placeholder{text-align:end}.sce-text-field__prefix{position:absolute;inset-inline-end:var(--space-16);top:50%;transform:translateY(-50%);color:var(--color-muted-fg);-webkit-user-select:none;user-select:none;pointer-events:none;z-index:1}.sce-text-field__input--prefixed{padding-inline-end:calc(var(--space-4) + var(--space-6))}.inlineContainer{display:flex;align-items:center;justify-content:flex-end;width:100%;min-width:0;min-height:var(--size-52);box-sizing:border-box;padding-inline:var(--space-16);border:1px solid var(--color-neutral-200);border-radius:var(--radius-brand-sm);background:var(--app-surface);transition:border-color .2s;direction:ltr}.inlineContainer:focus-within{border-color:var(--button-background-primary-bg-primary)}.inlineContainerInvalid{border-color:var(--color-red-500);border-width:1.5px}.inlinePrefix{flex:0 0 auto;order:-1;color:var(--color-muted-fg);font-weight:var(--font-weight-regular);white-space:nowrap;margin-inline-end:var(--space-8)}.inlineContainer .inlineInput.p-inputtext,.inlineContainer input.p-inputtext.inlineInput{flex:0 1 auto;width:auto;min-width:0;max-width:100%;min-height:auto;padding:0;border:none;border-radius:0;background:transparent;box-shadow:none;field-sizing:content}.inlineContainer .inlineInput.p-inputtext:enabled:focus,.inlineContainer input.p-inputtext.inlineInput:enabled:focus{background:transparent;box-shadow:none}.inlineContainer .inlineInput.p-inputtext:focus,.inlineContainer input.p-inputtext.inlineInput:focus{outline:none;box-shadow:none}\n"] }]
|
|
300
303
|
}], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], helpText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helpText", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], inputClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputClassName", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], listId: [{ type: i0.Input, args: [{ isSignal: true, alias: "listId", required: false }] }], validationMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMode", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], pattern: [{ type: i0.Input, args: [{ isSignal: true, alias: "pattern", required: false }] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], validate: [{ type: i0.Input, args: [{ isSignal: true, alias: "validate", required: false }] }], prefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefix", required: false }] }], prefixMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefixMode", required: false }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], focused: [{ type: i0.Output, args: ["focused"] }], blurred: [{ type: i0.Output, args: ["blurred"] }] } });
|
|
301
304
|
|
|
305
|
+
/** Multi-line textarea form field built on PrimeNG Textarea with the shared validation engine; validation is opt-in, since `validationMode` defaults to `'never'`. */
|
|
302
306
|
class SceTextareaFieldComponent {
|
|
303
307
|
mirrorLabelAsPlaceholder = inject(SCE_MIRROR_LABEL_AS_PLACEHOLDER, {
|
|
304
308
|
optional: true,
|
|
@@ -369,6 +373,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
369
373
|
args: [{ selector: 'sce-textarea-field', standalone: true, imports: [FormsModule, Textarea, SceFieldComponent], encapsulation: ViewEncapsulation.None, host: { class: 'sce-textarea-field' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<sce-field [id]=\"id()\" [label]=\"label()\" [required]=\"required()\" [helpText]=\"helpText()\" [error]=\"computedError()\">\n <textarea\n pTextarea\n [id]=\"id()\"\n [rows]=\"rows()\"\n [placeholder]=\"resolvedPlaceholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [attr.name]=\"name() ?? null\"\n [attr.maxlength]=\"maxLength() ?? null\"\n [class]=\"inputClasses()\"\n [ngModel]=\"value()\"\n (ngModelChange)=\"onValueChange($event)\"\n (blur)=\"onBlur($event)\"\n [attr.aria-invalid]=\"computedError() ? true : null\"\n ></textarea>\n</sce-field>\n" }]
|
|
370
374
|
}], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], helpText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helpText", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], inputClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputClassName", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], validationMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMode", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], pattern: [{ type: i0.Input, args: [{ isSignal: true, alias: "pattern", required: false }] }], validate: [{ type: i0.Input, args: [{ isSignal: true, alias: "validate", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], blurred: [{ type: i0.Output, args: ["blurred"] }] } });
|
|
371
375
|
|
|
376
|
+
/** Password form field built on PrimeNG Password with a reveal toggle enabled by default and an optional strength-feedback panel; `id` and `label` are required. */
|
|
372
377
|
class ScePasswordFieldComponent {
|
|
373
378
|
id = input.required(...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
374
379
|
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
@@ -399,6 +404,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
399
404
|
args: [{ selector: 'sce-password-field', standalone: true, imports: [FormsModule, Password, SceFieldComponent], encapsulation: ViewEncapsulation.None, host: { class: 'sce-password-field' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<sce-field [id]=\"id()\" [label]=\"label()\" [required]=\"required()\" [helpText]=\"helpText()\" [error]=\"error()\">\n <p-password\n [inputId]=\"id()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [toggleMask]=\"toggleMask()\"\n [feedback]=\"feedback()\"\n [promptLabel]=\"promptLabel() ?? ''\"\n [weakLabel]=\"weakLabel() ?? ''\"\n [mediumLabel]=\"mediumLabel() ?? ''\"\n [strongLabel]=\"strongLabel() ?? ''\"\n [attr.name]=\"name() ?? null\"\n [attr.autocomplete]=\"autocomplete() ?? null\"\n [ngModel]=\"value()\"\n (ngModelChange)=\"valueChange.emit($event)\"\n [styleClass]=\"wrapperClasses()\"\n [inputStyleClass]=\"inputClasses()\"\n [attr.aria-invalid]=\"error() ? true : null\"\n />\n</sce-field>\n", styles: ["sce-password-field{display:block}.sce-password-field .p-password,.sce-password-field .p-password-input{width:100%}\n"] }]
|
|
400
405
|
}], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], helpText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helpText", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], toggleMask: [{ type: i0.Input, args: [{ isSignal: true, alias: "toggleMask", required: false }] }], feedback: [{ type: i0.Input, args: [{ isSignal: true, alias: "feedback", required: false }] }], inputClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputClassName", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], promptLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "promptLabel", required: false }] }], weakLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "weakLabel", required: false }] }], mediumLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "mediumLabel", required: false }] }], strongLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "strongLabel", required: false }] }], panelClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClassName", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
|
|
401
406
|
|
|
407
|
+
/** Single-select form field built on PrimeNG Select with a built-in validation engine that shows errors once the control is touched; when no placeholder is given it falls back to the label if the `SCE_MIRROR_LABEL_AS_PLACEHOLDER` token is provided. */
|
|
402
408
|
class SceSelectFieldComponent {
|
|
403
409
|
mirrorLabelAsPlaceholder = inject(SCE_MIRROR_LABEL_AS_PLACEHOLDER, {
|
|
404
410
|
optional: true,
|
|
@@ -483,6 +489,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
483
489
|
args: [{ selector: 'sce-select-field', standalone: true, imports: [FormsModule, Select, SceFieldComponent], encapsulation: ViewEncapsulation.None, host: { class: 'sce-select-field' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"containerClassName()\" [attr.dir]=\"dir()\" [class]=\"fieldClassName()\">\n <sce-field\n [id]=\"id()\"\n [label]=\"label()\"\n [required]=\"required()\"\n [helpText]=\"helpText()\"\n [error]=\"displayError()\"\n [labelClassName]=\"labelClassName()\"\n [fieldClassName]=\"fieldClassName()\"\n >\n <p-select\n [inputId]=\"id()\"\n [ariaLabel]=\"label() || resolvedPlaceholder()\"\n [options]=\"options()\"\n optionLabel=\"label\"\n optionValue=\"value\"\n optionDisabled=\"disabled\"\n [placeholder]=\"resolvedPlaceholder()\"\n [disabled]=\"disabled()\"\n [filter]=\"filter()\"\n [filterPlaceholder]=\"filterPlaceholder() ?? ''\"\n [showClear]=\"showClear()\"\n [ngModel]=\"value()\"\n (ngModelChange)=\"onValueChange($event)\"\n (onBlur)=\"onBlur()\"\n [class.p-invalid]=\"displayError()\"\n [class.sce-select--borderless]=\"borderless()\"\n [styleClass]=\"'w-full ' + inputClassName()\"\n [panelStyleClass]=\"panelClassName()\"\n appendTo=\"body\"\n />\n </sce-field>\n</div>\n", styles: ["@charset \"UTF-8\";.root .p-select{width:100%;min-height:var(--space-56);border-radius:var(--radius-xl);border:1px solid var(--color-neutral-200);background:var(--color-surface);transition:border-color .15s ease}.root .p-select:not(.p-disabled).p-focus{box-shadow:none;border-color:var(--button-background-primary-bg-primary)}.root .p-select.sce-select--borderless:not(.p-invalid){border-color:transparent;border-radius:var(--radius-2xl, var(--radius-2xl))}.root .p-select.p-select.p-invalid{border-color:var(--text-text-error-primary)}.root .p-select.p-select.p-invalid:not(.p-disabled).p-focus{border-color:var(--text-text-error-primary);box-shadow:none}.root[dir=rtl] .p-select{display:flex;align-items:center;direction:ltr}.root[dir=rtl] .p-select .p-select-dropdown{order:-2;position:relative;inset:auto;display:flex;align-items:center;justify-content:center;align-self:stretch;flex-shrink:0;width:var(--space-40);margin:0;background:transparent;border:none}.root[dir=rtl] .p-select .p-select-clear-icon{order:-1;position:relative;inset:auto;flex-shrink:0;align-self:center;margin-inline-start:0;margin-inline-end:var(--space-4)}.root[dir=rtl] .p-select .p-select-label{order:0;display:flex;align-items:center;flex:1 1 auto;min-width:0;direction:ltr;text-align:end;justify-content:flex-end;width:auto;margin:0;padding-inline-start:var(--space-8);padding-inline-end:var(--space-16)}.root[dir=rtl] .p-select .p-select-label.p-placeholder{text-align:end}.root .p-select .p-select-label{font-family:var(--font-family-arabic-primary);font-size:var(--font-size-md);color:var(--details-value-color);padding:var(--space-15, var(--space-15)) var(--space-14, var(--space-14))}.root .p-select .p-select-label.p-placeholder{color:var(--form-input-placeholder-color);opacity:1}.root .p-select-overlay{border-radius:var(--radius-xl);overflow:hidden}.root .p-select-overlay .p-select-list .p-select-option{transition:background-color .12s ease}.root .p-select-overlay .p-select-header .p-select-filter.p-select-filter{margin-inline-end:unset}\n"] }]
|
|
484
490
|
}], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], helpText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helpText", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], validationMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMode", required: false }] }], validate: [{ type: i0.Input, args: [{ isSignal: true, alias: "validate", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], fieldClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "fieldClassName", required: false }] }], labelClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelClassName", required: false }] }], inputClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputClassName", required: false }] }], panelClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClassName", required: false }] }], borderless: [{ type: i0.Input, args: [{ isSignal: true, alias: "borderless", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], showError: [{ type: i0.Input, args: [{ isSignal: true, alias: "showError", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], containerClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "containerClassName", required: false }] }] } });
|
|
485
491
|
|
|
492
|
+
/** Multi-select form field built on PrimeNG MultiSelect with a built-in required/min/max validation engine and an optional footer for adding new options; `id` and `label` are required. */
|
|
486
493
|
class SceMultiSelectFieldComponent {
|
|
487
494
|
id = input.required(...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
488
495
|
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
@@ -594,6 +601,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
594
601
|
args: [{ selector: 'sce-multi-select-field', standalone: true, imports: [FormsModule, MultiSelect, PrimeTemplate, InputText, ButtonModule, SceFieldComponent, TranslatePipe], encapsulation: ViewEncapsulation.None, host: { class: 'sce-multi-select-field' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"containerClassName()\" [attr.dir]=\"dir()\">\n <sce-field\n [id]=\"id()\"\n [label]=\"label()\"\n [required]=\"required()\"\n [helpText]=\"helpText()\"\n [error]=\"computedError()\"\n [labelClassName]=\"labelClassName()\"\n [fieldClassName]=\"fieldClassName()\"\n >\n <p-multiselect\n [inputId]=\"id()\"\n [options]=\"options()\"\n optionLabel=\"label\"\n optionValue=\"value\"\n optionDisabled=\"disabled\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [filter]=\"filter()\"\n [filterPlaceHolder]=\"filterPlaceholder() ?? ''\"\n [showClear]=\"showClear()\"\n [display]=\"display()\"\n [selectionLimit]=\"maxSelected() ?? null\"\n [selectedItemsLabel]=\"resolvedSelectedItemsLabel()\"\n [ngModel]=\"value()\"\n (ngModelChange)=\"onValueChange($event)\"\n (onBlur)=\"onBlur()\"\n [class.p-invalid]=\"computedError()\"\n [styleClass]=\"inputClasses()\"\n [panelStyleClass]=\"panelClassName()\"\n appendTo=\"body\"\n >\n @if (allowAdd()) {\n <ng-template pTemplate=\"footer\">\n <div class=\"sce-multi-select-field__add-footer\">\n <input\n pInputText\n class=\"sce-multi-select-field__add-input\"\n [ngModel]=\"newOptionValue()\"\n (ngModelChange)=\"onNewOptionInput($event)\"\n [placeholder]=\"addOptionPlaceholder()\"\n (keydown.enter)=\"$event.preventDefault(); handleAddOption()\"\n />\n <button\n pButton\n type=\"button\"\n icon=\"pi pi-plus\"\n class=\"p-button-sm\"\n [attr.aria-label]=\"'common.add' | translate\"\n [disabled]=\"!newOptionValue().trim()\"\n (click)=\"handleAddOption()\"\n ></button>\n </div>\n </ng-template>\n }\n </p-multiselect>\n </sce-field>\n</div>\n", styles: ["@charset \"UTF-8\";.root .p-multiselect{width:100%;min-height:var(--space-56);border-radius:var(--radius-xl);border:1px solid var(--color-neutral-200);background:var(--color-surface);transition:border-color .15s ease}.root .p-multiselect:not(.p-disabled).p-focus{box-shadow:none;border-color:var(--button-background-primary-bg-primary)}.root .p-multiselect.p-multiselect.p-invalid{border-color:var(--text-text-error-primary)}.root .p-multiselect.p-multiselect.p-invalid:not(.p-disabled).p-focus{border-color:var(--text-text-error-primary);box-shadow:none}.root .p-multiselect .p-multiselect-label{font-family:var(--font-family-arabic-primary);font-size:var(--font-size-md);color:var(--details-value-color);padding:var(--space-15, var(--space-15)) var(--space-14, var(--space-14));white-space:normal;display:flex;flex-wrap:wrap;gap:var(--space-8);align-items:center}.root .p-multiselect .p-multiselect-label-container{display:flex;flex:1;overflow:hidden}.root .p-multiselect .p-multiselect-token{max-width:100%;border:0;border-radius:var(--radius-full);background:var(--details-row-bg);font-family:var(--font-family-arabic-primary);color:var(--text-text-primary-900);font-size:var(--font-size-md);font-weight:500;padding:var(--space-4) var(--space-10);flex-direction:row-reverse}.root .p-multiselect .p-multiselect-token-label{max-width:var(--size-220);overflow:hidden;text-overflow:ellipsis}.root .p-multiselect .p-multiselect-token-icon{margin-inline-start:var(--space-8)}.root .p-multiselect .p-multiselect-label.p-placeholder{color:var(--form-input-placeholder-color);opacity:1}.root .p-multiselect-panel{border-radius:var(--radius-xl);overflow:hidden}.root .p-multiselect-panel .p-multiselect-items .p-multiselect-item{transition:background-color .12s ease}.sce-multi-select-field__add-footer{display:flex;gap:var(--space-2);padding:var(--space-3);border-block-start:1px solid var(--text-text-primary-100)}.sce-multi-select-field__add-input{flex:1;font-size:var(--font-size-sm)}\n"] }]
|
|
595
602
|
}], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], helpText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helpText", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], panelClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClassName", required: false }] }], inputClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputClassName", required: false }] }], fieldClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "fieldClassName", required: false }] }], labelClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelClassName", required: false }] }], containerClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "containerClassName", required: false }] }], minSelected: [{ type: i0.Input, args: [{ isSignal: true, alias: "minSelected", required: false }] }], maxSelected: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSelected", required: false }] }], validationMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMode", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], validate: [{ type: i0.Input, args: [{ isSignal: true, alias: "validate", required: false }] }], selectedItemsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItemsLabel", required: false }] }], allowAdd: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowAdd", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], addOption: [{ type: i0.Output, args: ["addOption"] }] } });
|
|
596
603
|
|
|
604
|
+
/** Toggle switch built on PrimeNG ToggleSwitch, with optional active/inactive labels that fall back to translated defaults. */
|
|
597
605
|
class SceSwitchComponent {
|
|
598
606
|
translate = inject(TranslateService);
|
|
599
607
|
checked = input(false, ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
|
|
@@ -614,6 +622,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
614
622
|
|
|
615
623
|
const RATING_MAX = 5;
|
|
616
624
|
const STARS = [1, 2, 3, 4, 5];
|
|
625
|
+
/** Five-star rating input with hover preview, arrow-key adjustment and an optional error message, emitting the selected score. */
|
|
617
626
|
class SceStarRatingInputComponent {
|
|
618
627
|
value = input(0, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
619
628
|
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
@@ -651,6 +660,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
651
660
|
args: [{ host: { class: 'sce-star-rating-input' }, selector: 'sce-star-rating-input', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"starRating\">\n <!-- Focus lives on the child <button> stars (natively focusable); the group delegates keys.\n Making the group itself focusable would add a redundant tab stop. -->\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n <div class=\"starRow\" role=\"radiogroup\" [attr.aria-label]=\"ariaLabel()\" (mouseleave)=\"hoverScore.set(0)\" (keydown)=\"onKeyDown($event)\">\n @for (score of stars; track score) {\n <button\n type=\"button\"\n role=\"radio\"\n [attr.aria-checked]=\"value() === score\"\n [attr.aria-label]=\"score + ' / ' + max\"\n class=\"starButton\"\n [class.starButtonActive]=\"displayScore() >= score\"\n [disabled]=\"disabled()\"\n (mouseenter)=\"hoverScore.set(score)\"\n (focus)=\"hoverScore.set(score)\"\n (blur)=\"hoverScore.set(0)\"\n (click)=\"onStarClick(score)\"\n >\n <span class=\"starGlyph\" aria-hidden=\"true\">\u2605</span>\n </button>\n }\n </div>\n @if (error()) {\n <p class=\"starError\" role=\"alert\">{{ error() }}</p>\n }\n</div>\n", styles: [".sce-star-rating-input{display:contents}\n", ".starRating{display:flex;flex-direction:column;gap:var(--space-2)}.starRow{display:flex;flex-direction:row-reverse;gap:var(--space-1)}.starButton{background:transparent;border:none;cursor:pointer;padding:0;line-height:1;color:var(--color-neutral-300);transition:color .15s}.starButton:disabled{cursor:not-allowed;opacity:.5}.starButtonActive .starGlyph,.starButton.starButtonActive{color:var(--color-warning-400, #f59e0b)}.starGlyph{font-size:var(--font-size-3xl, 2rem)}.starError{color:var(--color-error-600);font-size:var(--font-size-sm);margin:0}\n"] }]
|
|
652
661
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
|
|
653
662
|
|
|
663
|
+
/** Currency amount field wrapped in `sce-field` that sanitizes typed text to a non-negative decimal and emits the parsed number, or `null` when cleared; `id` and `label` are required. */
|
|
654
664
|
class SceCurrencyInputComponent {
|
|
655
665
|
id = input.required(...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
656
666
|
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
@@ -690,6 +700,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
690
700
|
args: [{ selector: 'sce-currency-input', standalone: true, imports: [FormsModule, InputText, SceFieldComponent], encapsulation: ViewEncapsulation.None, host: { class: 'sce-currency-input' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<sce-field [id]=\"id()\" [label]=\"label()\" [required]=\"required()\" [helpText]=\"helpText()\" [error]=\"error()\">\n <div class=\"wrap\" [class.invalid]=\"invalid() || error()\" [class.disabled]=\"disabled()\" [class.readonly]=\"readonly()\">\n <input\n pInputText\n class=\"input\"\n [id]=\"id()\"\n inputmode=\"decimal\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [ngModel]=\"displayValue()\"\n (ngModelChange)=\"onInput($event)\"\n [attr.aria-invalid]=\"invalid() || error() ? true : null\"\n />\n <img class=\"icon\" src=\"/assets/icons/Saudi_Riyal_Symbol 1.svg\" alt=\"\" aria-hidden=\"true\" />\n </div>\n</sce-field>\n", styles: ["@charset \"UTF-8\";.wrap{display:flex;align-items:center;gap:var(--space-8);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl);background:var(--color-surface);padding:0 .85rem;transition:border-color .15s ease,box-shadow .15s ease;min-height:var(--space-44, var(--size-44))}.wrap:focus-within{border-color:var(--form-control-focus-border)}.wrap.invalid{border-color:var(--text-text-error-primary)}.wrap.disabled,.wrap.readonly{background:var(--color-neutral-100);opacity:.85;cursor:not-allowed}.wrap .input,.wrap .input.p-inputtext{flex:1;min-width:0;border:0;border-radius:0;background:transparent;box-shadow:none;height:auto;padding-inline-start:0;padding-inline-end:0;outline:none;font:inherit;color:inherit;width:100%}.wrap .input:enabled:focus,.wrap .input.p-inputtext:enabled:focus{border:0;box-shadow:none;outline:none}.icon{flex-shrink:0;opacity:.75;width:var(--space-18);height:1.15rem;pointer-events:none}\n"] }]
|
|
691
701
|
}], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], helpText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helpText", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
|
|
692
702
|
|
|
703
|
+
/** Unlabelled numeric input with a trailing unit suffix that sanitizes typed text to a non-negative number and emits the sanitized string. */
|
|
693
704
|
class SceUnitInputComponent {
|
|
694
705
|
value = input('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
695
706
|
unit = input('', ...(ngDevMode ? [{ debugName: "unit" }] : /* istanbul ignore next */ []));
|
|
@@ -726,6 +737,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
726
737
|
args: [{ selector: 'sce-unit-input', standalone: true, imports: [FormsModule, InputText], encapsulation: ViewEncapsulation.None, host: { class: 'sce-unit-input' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"wrapperClasses()\">\n <input\n pInputText\n [id]=\"id()\"\n [name]=\"name()\"\n [value]=\"displayValue()\"\n (input)=\"onInput($any($event.target).value)\"\n (focus)=\"onFocus($event)\"\n [attr.inputmode]=\"inputMode()\"\n [attr.min]=\"min() ?? null\"\n [attr.step]=\"step() ?? null\"\n type=\"text\"\n [disabled]=\"disabled()\"\n [readOnly]=\"readOnly()\"\n [attr.aria-invalid]=\"invalid() ? true : null\"\n [attr.aria-label]=\"ariaLabel() || placeholder() || unit()\"\n [placeholder]=\"placeholder()\"\n [class]=\"inputClasses()\"\n />\n <span class=\"unit\" aria-hidden=\"true\">{{ unit() }}</span>\n</div>\n", styles: ["@charset \"UTF-8\";.wrap{display:flex;align-items:center;gap:var(--space-8);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl);background:var(--color-surface);padding:0 .85rem;transition:border-color .15s ease,box-shadow .15s ease;min-height:var(--space-44, var(--size-44))}.wrap:focus-within{border-color:var(--form-control-focus-border)}.wrap.invalid{border-color:var(--text-text-error-primary)}.wrap.disabled{background:var(--color-neutral-100);opacity:.85;cursor:not-allowed}.wrap .input,.wrap .input.p-inputtext{flex:1;min-width:0;border:0;border-radius:0;background:transparent;box-shadow:none;padding-inline-start:0;padding-inline-end:0;outline:none;font:inherit;color:inherit;width:100%}.wrap .input:enabled:focus,.wrap .input.p-inputtext:enabled:focus{border:0;box-shadow:none;outline:none}.unit{flex-shrink:0;color:var(--text-text-secondary-700);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);line-height:1;pointer-events:none}\n"] }]
|
|
727
738
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], unit: [{ type: i0.Input, args: [{ isSignal: true, alias: "unit", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readOnly", required: false }] }], inputMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputMode", required: false }] }], allowDecimal: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowDecimal", required: false }] }], inputClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputClassName", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], focused: [{ type: i0.Output, args: ["focused"] }] } });
|
|
728
739
|
|
|
740
|
+
/** Labelled numeric field with a trailing unit suffix that defaults to the translated square-metre unit; `id` and `label` are required. */
|
|
729
741
|
class SceUnitInputFieldComponent {
|
|
730
742
|
translate = inject(TranslateService);
|
|
731
743
|
id = input.required(...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
@@ -798,6 +810,7 @@ function endOfHijriMonth(anchor) {
|
|
|
798
810
|
d.setDate(d.getDate() - 1);
|
|
799
811
|
return d;
|
|
800
812
|
}
|
|
813
|
+
/** Steps a `Date` forward or back by `delta` Hijri months by walking day-by-day across Umm al-Qura month boundaries. */
|
|
801
814
|
function addHijriMonths(anchor, delta) {
|
|
802
815
|
let next = new Date(anchor);
|
|
803
816
|
const steps = Math.abs(delta);
|
|
@@ -821,6 +834,7 @@ function addHijriMonths(anchor, delta) {
|
|
|
821
834
|
function pad2(n) {
|
|
822
835
|
return String(n).padStart(2, '0');
|
|
823
836
|
}
|
|
837
|
+
/** Formats a `Date` as its Umm al-Qura Hijri `YYYY-MM-DD` string. */
|
|
824
838
|
function toHijriValue(date) {
|
|
825
839
|
const { year, month, day } = getHijriYmd(date);
|
|
826
840
|
return `${year}-${pad2(month)}-${pad2(day)}`;
|
|
@@ -828,10 +842,12 @@ function toHijriValue(date) {
|
|
|
828
842
|
function getGregorianYmd(date) {
|
|
829
843
|
return { year: date.getFullYear(), month: date.getMonth() + 1, day: date.getDate() };
|
|
830
844
|
}
|
|
845
|
+
/** Formats a `Date` as its local-time Gregorian `YYYY-MM-DD` string. */
|
|
831
846
|
function toGregorianValue(date) {
|
|
832
847
|
const { year, month, day } = getGregorianYmd(date);
|
|
833
848
|
return `${year}-${pad2(month)}-${pad2(day)}`;
|
|
834
849
|
}
|
|
850
|
+
/** Parses a `YYYY-MM-DD` string in the given calendar system back to a `Date`, returning `null` if it is malformed or (for Hijri) has no Gregorian match in the scanned window. */
|
|
835
851
|
function parseValueToDate(value, system) {
|
|
836
852
|
const match = /^(\d{4})-(\d{2})-(\d{2})/.exec(value.trim());
|
|
837
853
|
if (!match) {
|
|
@@ -928,6 +944,7 @@ function gregorianMonthNames(locale) {
|
|
|
928
944
|
const base = locale === 'ar' ? 'ar-SA' : 'en-US';
|
|
929
945
|
return Array.from({ length: 12 }, (_, i) => new Intl.DateTimeFormat(base, { month: 'long' }).format(new Date(2024, i, 1)));
|
|
930
946
|
}
|
|
947
|
+
/** Builds the six-week day grid around `anchor` for the given calendar system and locale, along with the anchor month's index and year number. */
|
|
931
948
|
function buildCalendarGrid(anchor, system, locale) {
|
|
932
949
|
const weekdayFormatter = new Intl.DateTimeFormat(locale === 'ar' ? 'ar-SA' : 'en-US', {
|
|
933
950
|
weekday: 'short',
|
|
@@ -1000,10 +1017,12 @@ function formatDateForDisplay(value, system, locale, displayFormat = 'iso', disp
|
|
|
1000
1017
|
return value;
|
|
1001
1018
|
}
|
|
1002
1019
|
}
|
|
1020
|
+
/** Returns the Umm al-Qura Hijri year, month, and day numbers for a `Date`. */
|
|
1003
1021
|
function getHijriYmdFromDate(date) {
|
|
1004
1022
|
return getHijriYmd(date);
|
|
1005
1023
|
}
|
|
1006
1024
|
|
|
1025
|
+
/** Fully-controlled modal calendar used by `sce-date-field`, rendering the day grid plus month and year pickers and emitting every navigation and selection as an output; `locale` and `grid` are required. */
|
|
1007
1026
|
class SceDatePickerModalComponent {
|
|
1008
1027
|
open = input(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
1009
1028
|
locale = input.required(...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
|
|
@@ -1109,6 +1128,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
1109
1128
|
args: [{ host: { class: 'sce-date-picker-modal' }, selector: 'sce-date-picker-modal', standalone: true, imports: [TranslatePipe], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (open()) {\n <div class=\"df-backdrop\" role=\"presentation\" (click)=\"onBackdropClick($event)\">\n <div\n class=\"df-modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.dir]=\"isRtl() ? 'rtl' : 'ltr'\"\n [attr.aria-label]=\"'date.selectDate' | translate\"\n >\n <!-- Title bar -->\n <div class=\"df-titlebar\">\n <span class=\"df-title\">{{ 'date.selectDate' | translate }}</span>\n <button type=\"button\" class=\"df-close-btn\" [attr.aria-label]=\"'common.close' | translate\" (click)=\"cancel.emit()\">✕</button>\n </div>\n\n <!-- Calendar system toggle -->\n @if (showToggle() && !hijriOnly()) {\n <div class=\"df-tabs\" role=\"tablist\">\n <button\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"system() === 'hijri'\"\n class=\"df-tab\"\n [class.df-tab--active]=\"system() === 'hijri'\"\n (click)=\"systemChange.emit('hijri')\"\n >\n {{ 'date.hijri' | translate }}\n </button>\n <button\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"system() === 'gregorian'\"\n class=\"df-tab\"\n [class.df-tab--active]=\"system() === 'gregorian'\"\n (click)=\"systemChange.emit('gregorian')\"\n >\n {{ 'date.gregorian' | translate }}\n </button>\n </div>\n }\n\n <!-- Calendar header -->\n <div class=\"df-cal-header\">\n <button type=\"button\" class=\"df-nav-btn\" [attr.aria-label]=\"'date.previousMonth' | translate\" (click)=\"movePrev.emit()\">\n <i class=\"pi pi-chevron-left\"></i>\n </button>\n <div class=\"df-month-year\">\n <button type=\"button\" class=\"df-month-year-btn\" (click)=\"showMonthPickerChange.emit()\">\n {{ monthLabel() }}\n </button>\n <button type=\"button\" class=\"df-month-year-btn\" (click)=\"showYearPickerChange.emit()\">\n {{ currentYearNumber() }}\n </button>\n </div>\n <button type=\"button\" class=\"df-nav-btn\" [attr.aria-label]=\"'date.nextMonth' | translate\" (click)=\"moveNext.emit()\">\n <i class=\"pi pi-chevron-left\"></i>\n </button>\n </div>\n\n <!-- Month picker -->\n @if (showMonthPicker()) {\n <div class=\"df-month-grid\">\n @for (name of monthNames(); track name; let i = $index) {\n <button\n type=\"button\"\n class=\"df-month-cell\"\n [class.df-month-cell--active]=\"i === currentMonthIndex()\"\n (click)=\"selectMonth.emit(i)\"\n >\n {{ name }}\n </button>\n }\n </div>\n }\n\n <!-- Year picker -->\n @if (showYearPicker()) {\n <div class=\"df-year-picker\">\n <div class=\"df-year-picker-header\">\n <button type=\"button\" class=\"df-nav-btn\" (click)=\"yearPagePrev.emit()\">\n <i class=\"pi pi-chevron-left\"></i>\n </button>\n <span class=\"df-year-range-label\">{{ yearRangeLabel() }}</span>\n <button type=\"button\" class=\"df-nav-btn\" (click)=\"yearPageNext.emit()\">\n <i class=\"pi pi-chevron-left\"></i>\n </button>\n </div>\n <div class=\"df-year-grid\">\n @for (year of yearRange(); track year) {\n <button\n type=\"button\"\n class=\"df-year-cell\"\n [class.df-year-cell--active]=\"year === currentYearNumber()\"\n (click)=\"selectYear.emit(year)\"\n >\n {{ year }}\n </button>\n }\n </div>\n </div>\n }\n\n <!-- Day grid -->\n @if (!showMonthPicker() && !showYearPicker()) {\n <div class=\"df-weekdays\">\n @for (w of grid().weekdays; track w) {\n <div class=\"df-weekday\">{{ w }}</div>\n }\n </div>\n <div class=\"df-days\" (mouseleave)=\"selectionMode() === 'range' ? clearHoverDay.emit() : null\">\n @for (view of dayViews(); track view.day.date.toISOString()) {\n <button\n type=\"button\"\n [disabled]=\"view.disabled\"\n [class]=\"view.classes\"\n (mouseenter)=\"onDayMouseEnter(view.day.value, view.disabled)\"\n (click)=\"onDayClick(view.day.value, view.disabled)\"\n >\n {{ view.day.labelDay }}\n </button>\n }\n </div>\n\n <!-- Time row -->\n <div class=\"df-time-row\">\n <span class=\"df-time-label\">{{ 'date.time' | translate }}</span>\n <span class=\"df-time-value\">11:59 {{ 'date.pm' | translate }}</span>\n </div>\n }\n\n <!-- Footer -->\n <div class=\"df-footer\">\n <button type=\"button\" class=\"df-footer-btn df-footer-btn--confirm\" (click)=\"confirm.emit()\">\n {{ 'common.confirm' | translate }}\n </button>\n <button type=\"button\" class=\"df-footer-btn df-footer-btn--cancel\" (click)=\"cancel.emit()\">\n {{ 'common.cancel' | translate }}\n </button>\n </div>\n </div>\n </div>\n}\n" }]
|
|
1110
1129
|
}], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: true }] }], system: [{ type: i0.Input, args: [{ isSignal: true, alias: "system", required: false }] }], showToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showToggle", required: false }] }], hijriOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "hijriOnly", required: false }] }], selectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionMode", required: false }] }], draftSingle: [{ type: i0.Input, args: [{ isSignal: true, alias: "draftSingle", required: false }] }], draftRange: [{ type: i0.Input, args: [{ isSignal: true, alias: "draftRange", required: false }] }], hoveredDay: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoveredDay", required: false }] }], anchor: [{ type: i0.Input, args: [{ isSignal: true, alias: "anchor", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], canShowToday: [{ type: i0.Input, args: [{ isSignal: true, alias: "canShowToday", required: false }] }], grid: [{ type: i0.Input, args: [{ isSignal: true, alias: "grid", required: true }] }], currentMonthIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentMonthIndex", required: false }] }], currentYearNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentYearNumber", required: false }] }], yearRange: [{ type: i0.Input, args: [{ isSignal: true, alias: "yearRange", required: false }] }], yearPageStart: [{ type: i0.Input, args: [{ isSignal: true, alias: "yearPageStart", required: false }] }], showMonthPicker: [{ type: i0.Input, args: [{ isSignal: true, alias: "showMonthPicker", required: false }] }], showYearPicker: [{ type: i0.Input, args: [{ isSignal: true, alias: "showYearPicker", required: false }] }], systemChange: [{ type: i0.Output, args: ["systemChange"] }], showMonthPickerChange: [{ type: i0.Output, args: ["showMonthPickerChange"] }], showYearPickerChange: [{ type: i0.Output, args: ["showYearPickerChange"] }], movePrev: [{ type: i0.Output, args: ["movePrev"] }], moveNext: [{ type: i0.Output, args: ["moveNext"] }], selectDay: [{ type: i0.Output, args: ["selectDay"] }], hoverDay: [{ type: i0.Output, args: ["hoverDay"] }], clearHoverDay: [{ type: i0.Output, args: ["clearHoverDay"] }], selectMonth: [{ type: i0.Output, args: ["selectMonth"] }], selectYear: [{ type: i0.Output, args: ["selectYear"] }], yearPagePrev: [{ type: i0.Output, args: ["yearPagePrev"] }], yearPageNext: [{ type: i0.Output, args: ["yearPageNext"] }], today: [{ type: i0.Output, args: ["today"] }], cancel: [{ type: i0.Output, args: ["cancel"] }], confirm: [{ type: i0.Output, args: ["confirm"] }], backdropClick: [{ type: i0.Output, args: ["backdropClick"] }] } });
|
|
1111
1130
|
|
|
1131
|
+
/** Date field that pairs a text input with a modal calendar supporting both Hijri and Gregorian systems and single or range selection; it defaults to the Hijri calendar and locks body scroll while the calendar is open. */
|
|
1112
1132
|
class SceDateFieldComponent {
|
|
1113
1133
|
doc = inject(DOCUMENT);
|
|
1114
1134
|
id = input.required(...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
@@ -1367,6 +1387,7 @@ function getPaginationItems(currentPage, totalPages) {
|
|
|
1367
1387
|
items.push(totalPages);
|
|
1368
1388
|
return items;
|
|
1369
1389
|
}
|
|
1390
|
+
/** Page-number paginator with an ellipsis window and a page-size select; it is stateless (`page`, `pageSize`, `totalItems` are required inputs) and derives direction from `locale` unless `dir` is set — note it uses `ViewEncapsulation.None`. */
|
|
1370
1391
|
class ScePaginatorComponent {
|
|
1371
1392
|
page = input.required(...(ngDevMode ? [{ debugName: "page" }] : /* istanbul ignore next */ []));
|
|
1372
1393
|
pageSize = input.required(...(ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []));
|
|
@@ -1405,6 +1426,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
1405
1426
|
args: [{ host: { class: 'sce-paginator' }, selector: 'sce-paginator', standalone: true, imports: [Select, FormsModule, TranslatePipe, DigitPipe], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-paginator__bar\" [attr.dir]=\"effectiveDir()\">\n <div class=\"sce-paginator__nav\">\n <button\n type=\"button\"\n [disabled]=\"currentPage() <= 1\"\n (click)=\"goToPage(currentPage() - 1)\"\n class=\"sce-paginator__btn\"\n [attr.aria-label]=\"'pagination.previousPage' | translate\"\n >\n @if (isRtl()) {\n <img src=\"/assets/icons/caret-right.svg\" width=\"24\" height=\"24\" aria-hidden=\"true\" alt=\"\" />\n } @else {\n <img src=\"/assets/icons/caret-left.svg\" width=\"24\" height=\"24\" aria-hidden=\"true\" alt=\"\" />\n }\n </button>\n\n <!-- track $index: pagination items are positional; 'ellipsis' repeats, so there is no identity -->\n @for (item of items(); track $index) {\n @if (item === 'ellipsis') {\n <span class=\"sce-paginator__ellipsis\">. . .</span>\n } @else {\n <button\n type=\"button\"\n [disabled]=\"item === currentPage()\"\n (click)=\"goToPage(item)\"\n class=\"sce-paginator__page\"\n [class.sce-paginator__page--active]=\"item === currentPage()\"\n >\n {{ item | digit }}\n </button>\n }\n }\n\n <button\n type=\"button\"\n [disabled]=\"currentPage() >= totalPages()\"\n (click)=\"goToPage(currentPage() + 1)\"\n class=\"sce-paginator__btn\"\n [attr.aria-label]=\"'pagination.nextPage' | translate\"\n >\n @if (isRtl()) {\n <img src=\"/assets/icons/caret-left.svg\" width=\"20\" height=\"20\" aria-hidden=\"true\" alt=\"\" />\n } @else {\n <img src=\"/assets/icons/caret-right.svg\" width=\"20\" height=\"20\" aria-hidden=\"true\" alt=\"\" />\n }\n </button>\n </div>\n\n <div class=\"sce-paginator__size\">\n <p class=\"sce-paginator__show-label\">\n {{ showLabel() ?? ('common.pagination.show' | translate) }}\n </p>\n <p-select\n dir=\"ltr\"\n [options]=\"pageSizeSelectOptions()\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"pageSize()\"\n (ngModelChange)=\"onPageSizeSelect($event)\"\n styleClass=\"pageSizeDropdown\"\n panelStyleClass=\"pageSizePanel\"\n appendTo=\"body\"\n />\n </div>\n</div>\n", styles: [".sce-paginator__bar{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:var(--space-12);width:100%;min-height:var(--space-48)}.sce-paginator__nav{display:flex;flex-wrap:wrap;gap:var(--space-6);align-items:center;min-width:0}@media(max-width:576px){.sce-paginator__nav{width:100%;justify-content:center}}@media(min-width:577px){.sce-paginator__nav{gap:var(--space-8)}}.sce-paginator__size{width:8.3125rem;flex-shrink:0;display:flex;justify-content:space-between;align-items:center;gap:var(--space-12)}@media(max-width:576px){.sce-paginator__size{width:100%}}.sce-paginator__btn{display:flex;align-items:center;justify-content:center;width:var(--size-40);height:var(--size-40);border-radius:var(--radius-full);background:var(--pagination-surface);border:none;cursor:pointer;transition:background-color .2s;flex-shrink:0}@media(min-width:577px){.sce-paginator__btn{width:var(--size-44);height:var(--size-44)}}.sce-paginator__btn:hover{background:var(--pagination-surface-hover)}.sce-paginator__btn:disabled{opacity:.5;cursor:not-allowed}.sce-paginator__ellipsis{display:flex;align-items:center;justify-content:center;width:var(--size-40);height:var(--size-40);border-radius:var(--radius-full);background:var(--pagination-surface);color:var(--pagination-text);font-family:var(--font-family-base);font-weight:var(--font-weight-medium);font-size:var(--font-size-sm);letter-spacing:.005em;flex-shrink:0}@media(min-width:577px){.sce-paginator__ellipsis{width:var(--size-44);height:var(--size-44)}}.sce-paginator__page{display:flex;align-items:center;justify-content:center;width:var(--size-40);height:var(--size-40);border-radius:var(--radius-full);background:var(--pagination-surface);color:var(--pagination-text);font-family:var(--font-family-base);font-weight:var(--font-weight-medium);font-size:var(--font-size-sm);letter-spacing:.005em;border:none;cursor:pointer;transition:background-color .2s;flex-shrink:0}@media(min-width:577px){.sce-paginator__page{width:var(--size-44);height:var(--size-44)}}.sce-paginator__page:hover{background:var(--pagination-surface-inactive-hover)}.sce-paginator__page--active{background:var(--pagination-surface-active);color:var(--pagination-text-active);cursor:default}.sce-paginator__page--active:hover{background:var(--pagination-surface-active-hover)}.sce-paginator__show-label{font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-medium);font-size:var(--font-size-base);letter-spacing:0;color:var(--color-neutral-700);margin:0}.pageSizeDropdown{width:var(--space-88, var(--size-88));height:var(--space-48);border-radius:var(--radius-full);border:1px solid var(--control-border);background:var(--dropdown-surface);align-items:center}.pageSizeDropdown .p-select-label{display:flex;align-items:center;justify-content:center;width:100%;padding:0 1rem;margin:0;font-family:var(--font-family-base);font-size:var(--font-size-md);font-weight:var(--font-weight-regular);color:var(--control-text);text-align:center}.pageSizeDropdown .p-select-label.p-inputtext{height:100%;border:0;background:transparent;box-shadow:none}.pageSizeDropdown .p-select-dropdown{width:var(--space-28);color:var(--control-text)}.pageSizeDropdown.p-select:not(.p-disabled).p-focus{box-shadow:none;outline:none;border-color:var(--control-border)}.pageSizePanel .p-select-option{font-family:var(--font-family-base);font-size:var(--font-size-md);justify-content:center}.pageSizePanel .p-select-option.p-select-option-selected,.pageSizePanel .p-select-option.p-focus{background:var(--form-control-option-selected-bg);color:var(--form-control-option-selected-text)}.pageSizePanel .p-select-option:not(.p-select-option-selected):not(.p-disabled):hover{background:var(--form-control-option-hover-bg);color:var(--form-control-option-selected-text)}\n"] }]
|
|
1406
1427
|
}], propDecorators: { page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: true }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: true }] }], totalItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalItems", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }], showLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLabel", required: false }] }], numberFormatter: [{ type: i0.Input, args: [{ isSignal: true, alias: "numberFormatter", required: false }] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], pageSizeChange: [{ type: i0.Output, args: ["pageSizeChange"] }] } });
|
|
1407
1428
|
|
|
1429
|
+
/** Design-system demo harness that wires `sce-paginator` to local page state; not for production pages. */
|
|
1408
1430
|
class ScePaginatorDemoComponent {
|
|
1409
1431
|
totalRecords = input(120, ...(ngDevMode ? [{ debugName: "totalRecords" }] : /* istanbul ignore next */ []));
|
|
1410
1432
|
locale = input('ar', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
|
|
@@ -1425,6 +1447,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
1425
1447
|
args: [{ host: { class: 'sce-paginator-demo' }, selector: 'sce-paginator-demo', standalone: true, imports: [ScePaginatorComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<sce-paginator\n [page]=\"page\"\n [pageSize]=\"pageSize\"\n [totalItems]=\"totalRecords()\"\n [locale]=\"locale()\"\n (pageChange)=\"onPageChange($event)\"\n (pageSizeChange)=\"onPageSizeChange($event)\"\n/>\n", styles: [":host{display:block}.sce-paginator-demo{display:contents}\n"] }]
|
|
1426
1448
|
}], propDecorators: { totalRecords: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalRecords", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }] } });
|
|
1427
1449
|
|
|
1450
|
+
/** Shared PrimeNG-Dialog shell that every sce dialog builds on, providing the sticky header, close button, projected body and footer and the size presets; setting `locked` blocks both Escape and mask dismissal. */
|
|
1428
1451
|
class SceDialogShellComponent {
|
|
1429
1452
|
/** Controls dialog visibility. */
|
|
1430
1453
|
visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
@@ -1507,6 +1530,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
1507
1530
|
args: [{ host: { class: 'sce-dialog-shell' }, selector: 'sce-dialog-shell', standalone: true, imports: [Dialog, TranslatePipe], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<p-dialog\n [visible]=\"visible()\"\n [modal]=\"true\"\n [draggable]=\"false\"\n [resizable]=\"false\"\n [showHeader]=\"false\"\n [dismissableMask]=\"effectiveDismissableMask()\"\n [closeOnEscape]=\"effectiveCloseOnEscape()\"\n [styleClass]=\"rootStyleClass()\"\n [style]=\"style()\"\n contentStyleClass=\"content\"\n appendTo=\"body\"\n (onHide)=\"onHide()\"\n>\n <div [class]=\"shellClass()\" [dir]=\"dir()\">\n <header [class]=\"headerClass()\">\n <div class=\"headerText\">\n <h2 class=\"title\">{{ title() }}</h2>\n @if (subtitle()) {\n <p class=\"subtitle\">{{ subtitle() }}</p>\n }\n </div>\n @if (showCloseButton()) {\n <button\n type=\"button\"\n class=\"closeButton\"\n [disabled]=\"locked()\"\n (click)=\"close.emit()\"\n [attr.aria-label]=\"closeAriaLabel() ?? ('common.close' | translate)\"\n >\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n }\n </header>\n\n @if (hasBody()) {\n <div [class]=\"bodyClass()\">\n <ng-content />\n </div>\n }\n\n @if (hasFooter()) {\n <div class=\"shellFooter\">\n <ng-content select=\"[dialogFooter]\" />\n </div>\n }\n </div>\n</p-dialog>\n", styles: ["@charset \"UTF-8\";.sce-dialog-shell-dialog{width:min(var(--size-560),100vi - var(--size-24));max-width:calc(100vi - var(--size-24));max-height:90vb;border-radius:var(--radius-20);overflow:hidden}.sce-dialog-shell-dialog.size-sm,.sce-dialog-shell-dialog.size-md{width:min(var(--size-560),100vi - var(--size-24));max-width:calc(100vi - var(--size-24))}.sce-dialog-shell-dialog.size-lg{width:min(var(--size-720),100vi - var(--size-24));max-width:calc(100vi - var(--size-24));min-width:min(var(--size-560),100vi - var(--size-24))}.sce-dialog-shell-dialog.size-xl{width:min(var(--size-960),100vi - var(--size-24));max-width:calc(100vi - var(--size-24));min-width:min(var(--size-560),100vi - var(--size-24))}.sce-dialog-shell-dialog .content{padding:0;border-radius:var(--radius-20);max-height:90vb;display:flex;flex-direction:column;overflow:hidden}.sce-dialog-shell-dialog .shell{display:flex;flex-direction:column;min-height:0;flex:1 1 auto;background:var(--color-surface);gap:var(--space-16);padding:var(--space-32)}.sce-dialog-shell-dialog .header{flex:0 0 auto;position:relative;display:flex;align-items:flex-start;gap:var(--space-12);padding:0}.sce-dialog-shell-dialog .headerOnly{padding-block-end:0}.sce-dialog-shell-dialog .headerCenter .header{display:grid;grid-template-columns:1fr;text-align:center;direction:inherit}.sce-dialog-shell-dialog .closeButton{width:var(--space-40);height:var(--space-40);display:inline-flex;align-items:center;justify-content:center;border:0;border-radius:var(--radius-xl);background:var(--app-surface-muted);color:var(--details-title-color);font-size:var(--font-size-22);line-height:1;cursor:pointer;flex:0 0 auto}.sce-dialog-shell-dialog .closeButton .pi{font-size:var(--font-size-base)}.sce-dialog-shell-dialog .closeButton:hover{background:var(--app-surface-hover)}.sce-dialog-shell-dialog .headerCenter .closeButton{position:absolute;inset-inline-end:0;top:0}.sce-dialog-shell-dialog .headerText{display:grid;gap:var(--space-8);min-width:0;flex:1 1 auto}.sce-dialog-shell-dialog .headerCenter .headerText{padding-inline:var(--space-56)}.sce-dialog-shell-dialog .headerCenter .header{min-height:var(--space-72)}.sce-dialog-shell-dialog .title{margin:0;font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-bold);font-size:var(--font-size-2xl-24);line-height:1.4;color:var(--text-text-primary-900);text-align:start}.sce-dialog-shell-dialog .headerCenter .title{text-align:center}.sce-dialog-shell-dialog .subtitle{margin:0;font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-regular);font-size:var(--font-size-lg);line-height:1.5;color:var(--text-text-secondary-700);text-align:start}.sce-dialog-shell-dialog .headerCenter .subtitle{text-align:center}.sce-dialog-shell-dialog .headerSpacer{display:none}.sce-dialog-shell-dialog .body{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;padding:0;display:grid;gap:var(--space-20)}.sce-dialog-shell-dialog .body::-webkit-scrollbar{width:var(--space-8)}.sce-dialog-shell-dialog .body::-webkit-scrollbar-track{background:transparent}.sce-dialog-shell-dialog .body::-webkit-scrollbar-thumb{background:var(--color-neutral-200);border-radius:var(--radius-lg)}.sce-dialog-shell-dialog .body::-webkit-scrollbar-thumb:hover{background:var(--color-neutral-300)}.sce-dialog-shell-dialog .bodyCompact{padding:0}.sce-dialog-shell-dialog .shellFooter{display:contents}.sce-dialog-shell-dialog .footer{position:relative;flex:0 0 auto;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12);padding:0;background:var(--color-surface);width:100%}.sce-dialog-shell-dialog .footer>button{display:block;width:100%;box-sizing:border-box}.sce-dialog-shell-dialog .footerSingle{grid-template-columns:1fr}@media(max-width:768px){.sce-dialog-shell-dialog,.sce-dialog-shell-dialog.size-md,.sce-dialog-shell-dialog.size-lg,.sce-dialog-shell-dialog.size-xl,.sce-dialog-shell-dialog.size-sm{width:calc(100vi - var(--space-16, var(--size-16)));min-width:0;max-width:calc(100vi - var(--size-16));max-height:calc(100vb - var(--size-32))}.sce-dialog-shell-dialog .shell{padding:var(--space-16);gap:var(--space-12)}}\n"] }]
|
|
1508
1531
|
}], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], centerHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "centerHeader", required: false }] }], showCloseButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCloseButton", required: false }] }], locked: [{ type: i0.Input, args: [{ isSignal: true, alias: "locked", required: false }] }], dismissableMask: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissableMask", required: false }] }], closeOnEscape: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnEscape", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }], compactBody: [{ type: i0.Input, args: [{ isSignal: true, alias: "compactBody", required: false }] }], closeAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeAriaLabel", required: false }] }], hasBody: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasBody", required: false }] }], hasFooter: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasFooter", required: false }] }], close: [{ type: i0.Output, args: ["close"] }] } });
|
|
1509
1532
|
|
|
1533
|
+
/** Design-system demo host that shows `sce-dialog-shell` and reports its visibility back through `visibleChange`. */
|
|
1510
1534
|
class SceDialogShellDemoComponent {
|
|
1511
1535
|
visible = input(false, ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
1512
1536
|
visibleChange = output();
|
|
@@ -1533,6 +1557,7 @@ const ICON_BY_VARIANT = {
|
|
|
1533
1557
|
warning: 'pi pi-exclamation-circle',
|
|
1534
1558
|
info: 'pi pi-info-circle',
|
|
1535
1559
|
};
|
|
1560
|
+
/** Confirmation dialog built on `sce-dialog-shell` with per-variant icon and button styling and an optional reason field; supplying `onConfirmHandler` makes it await the async handler and lock the buttons, mask and Escape while pending. */
|
|
1536
1561
|
class SceConfirmDialogComponent {
|
|
1537
1562
|
translate = inject(TranslateService);
|
|
1538
1563
|
visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
@@ -1684,6 +1709,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
1684
1709
|
args: [{ host: { class: 'sce-confirm-dialog' }, selector: 'sce-confirm-dialog', standalone: true, imports: [SceDialogShellComponent, FormsModule], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<sce-dialog-shell\n [visible]=\"visible()\"\n [locale]=\"locale()\"\n [title]=\"title()\"\n [subtitle]=\"subtitleText()\"\n [size]=\"size()\"\n [centerHeader]=\"centerHeader()\"\n [locked]=\"isPending()\"\n [hasBody]=\"hasBodyContent()\"\n (close)=\"onDialogClose()\"\n>\n <!-- Icon -->\n @if (icon() !== undefined) {\n <div class=\"iconWrap\">\n <span class=\"iconCircle {{ iconClass() }}\">\n @if (icon() === 'custom') {\n <ng-content select=\"[confirmIcon]\" />\n } @else {\n <i [class]=\"iconPiClass()\" aria-hidden=\"true\"></i>\n }\n </span>\n </div>\n }\n\n <!-- Custom body slot -->\n @if (hasBodySlot()) {\n <ng-content select=\"[confirmBody]\" />\n }\n\n <!-- Body description -->\n @if (showBodyDescription()) {\n <p class=\"message\">{{ description() }}</p>\n }\n\n <!-- Reason/comment field -->\n @if (field(); as f) {\n <div class=\"fieldGroup\">\n <p class=\"fieldLabel\">\n {{ f.label }}\n @if (fieldRequired()) {\n <span class=\"requiredMark\" aria-hidden=\"true\"> *</span>\n }\n </p>\n @if (multiline()) {\n <textarea\n class=\"p-inputtextarea p-inputtext w-full\"\n [class.p-invalid]=\"fieldHasError()\"\n [placeholder]=\"f.placeholder ?? ''\"\n [value]=\"fieldValue()\"\n [required]=\"fieldRequired()\"\n [attr.aria-required]=\"fieldRequired()\"\n [attr.aria-invalid]=\"fieldHasError()\"\n [attr.maxlength]=\"f.maxLength ?? null\"\n [rows]=\"f.rows ?? 4\"\n (input)=\"onFieldChange($any($event.target).value)\"\n ></textarea>\n } @else {\n <input\n class=\"p-inputtext w-full\"\n [class.p-invalid]=\"fieldHasError()\"\n [placeholder]=\"f.placeholder ?? ''\"\n [value]=\"fieldValue()\"\n [required]=\"fieldRequired()\"\n [attr.aria-required]=\"fieldRequired()\"\n [attr.aria-invalid]=\"fieldHasError()\"\n [attr.maxlength]=\"f.maxLength ?? null\"\n (input)=\"onFieldChange($any($event.target).value)\"\n />\n }\n @if (displayedFieldError()) {\n <p class=\"fieldError\">{{ displayedFieldError() }}</p>\n }\n </div>\n }\n\n <!-- Footer buttons -->\n <div dialogFooter class=\"footer\" [class.footerSingle]=\"hideCancelButton()\">\n <button type=\"button\" [class]=\"confirmBtnClass()\" [disabled]=\"confirmBtnDisabled()\" (click)=\"onConfirm()\">\n {{ resolvedConfirmLabel() }}\n </button>\n @if (!hideCancelButton()) {\n <button type=\"button\" class=\"btn cancel\" [disabled]=\"cancelBtnDisabled()\" (click)=\"onCancel()\">\n {{ resolvedCancelLabel() }}\n </button>\n }\n </div>\n</sce-dialog-shell>\n", styles: ["@charset \"UTF-8\";.sce-dialog-shell-dialog{width:min(var(--size-560),100vi - var(--size-24));max-width:calc(100vi - var(--size-24));max-height:90vb;border-radius:var(--radius-20);overflow:hidden}.sce-dialog-shell-dialog.size-sm,.sce-dialog-shell-dialog.size-md{width:min(var(--size-560),100vi - var(--size-24));max-width:calc(100vi - var(--size-24))}.sce-dialog-shell-dialog.size-lg{width:min(var(--size-720),100vi - var(--size-24));max-width:calc(100vi - var(--size-24));min-width:min(var(--size-560),100vi - var(--size-24))}.sce-dialog-shell-dialog.size-xl{width:min(var(--size-960),100vi - var(--size-24));max-width:calc(100vi - var(--size-24));min-width:min(var(--size-560),100vi - var(--size-24))}.sce-dialog-shell-dialog .content{padding:0;border-radius:var(--radius-20);max-height:90vb;display:flex;flex-direction:column;overflow:hidden}.sce-dialog-shell-dialog .shell{display:flex;flex-direction:column;min-height:0;flex:1 1 auto;background:var(--color-surface);gap:var(--space-16);padding:var(--space-32)}.sce-dialog-shell-dialog .header{flex:0 0 auto;position:relative;display:flex;align-items:flex-start;gap:var(--space-12);padding:0}.sce-dialog-shell-dialog .headerOnly{padding-block-end:0}.sce-dialog-shell-dialog .headerCenter .header{display:grid;grid-template-columns:1fr;text-align:center;direction:inherit}.sce-dialog-shell-dialog .closeButton{width:var(--space-40);height:var(--space-40);display:inline-flex;align-items:center;justify-content:center;border:0;border-radius:var(--radius-xl);background:var(--app-surface-muted);color:var(--details-title-color);font-size:var(--font-size-22);line-height:1;cursor:pointer;flex:0 0 auto}.sce-dialog-shell-dialog .closeButton .pi{font-size:var(--font-size-base)}.sce-dialog-shell-dialog .closeButton:hover{background:var(--app-surface-hover)}.sce-dialog-shell-dialog .headerCenter .closeButton{position:absolute;inset-inline-end:0;top:0}.sce-dialog-shell-dialog .headerText{display:grid;gap:var(--space-8);min-width:0;flex:1 1 auto}.sce-dialog-shell-dialog .headerCenter .headerText{padding-inline:var(--space-56)}.sce-dialog-shell-dialog .headerCenter .header{min-height:var(--space-72)}.sce-dialog-shell-dialog .title{margin:0;font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-bold);font-size:var(--font-size-2xl-24);line-height:1.4;color:var(--text-text-primary-900);text-align:start}.sce-dialog-shell-dialog .headerCenter .title{text-align:center}.sce-dialog-shell-dialog .subtitle{margin:0;font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-regular);font-size:var(--font-size-lg);line-height:1.5;color:var(--text-text-secondary-700);text-align:start}.sce-dialog-shell-dialog .headerCenter .subtitle{text-align:center}.sce-dialog-shell-dialog .headerSpacer{display:none}.sce-dialog-shell-dialog .body{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;padding:0;display:grid;gap:var(--space-20)}.sce-dialog-shell-dialog .body::-webkit-scrollbar{width:var(--space-8)}.sce-dialog-shell-dialog .body::-webkit-scrollbar-track{background:transparent}.sce-dialog-shell-dialog .body::-webkit-scrollbar-thumb{background:var(--color-neutral-200);border-radius:var(--radius-lg)}.sce-dialog-shell-dialog .body::-webkit-scrollbar-thumb:hover{background:var(--color-neutral-300)}.sce-dialog-shell-dialog .bodyCompact{padding:0}.sce-dialog-shell-dialog .shellFooter{display:contents}.sce-dialog-shell-dialog .footer{position:relative;flex:0 0 auto;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12);padding:0;background:var(--color-surface);width:100%}.sce-dialog-shell-dialog .footer>button{display:block;width:100%;box-sizing:border-box}.sce-dialog-shell-dialog .footerSingle{grid-template-columns:1fr}@media(max-width:768px){.sce-dialog-shell-dialog,.sce-dialog-shell-dialog.size-md,.sce-dialog-shell-dialog.size-lg,.sce-dialog-shell-dialog.size-xl,.sce-dialog-shell-dialog.size-sm{width:calc(100vi - var(--space-16, var(--size-16)));min-width:0;max-width:calc(100vi - var(--size-16));max-height:calc(100vb - var(--size-32))}.sce-dialog-shell-dialog .shell{padding:var(--space-16);gap:var(--space-12)}}\n", "@charset \"UTF-8\";.message{margin:0;font-family:var(--font-family-arabic-primary);font-weight:400;font-size:var(--font-size-md);line-height:1.6;text-align:start;color:var(--text-text-secondary-700)}.iconWrap{display:flex;justify-content:center;margin-block-end:var(--space-4)}.iconCircle{width:var(--space-56);height:var(--space-56);border-radius:var(--radius-full);display:inline-flex;align-items:center;justify-content:center;font-size:var(--font-size-26)}.iconPrimary{background:color-mix(in srgb,var(--button-background-primary-bg-primary) 12%,transparent);color:var(--button-background-primary-bg-primary)}.iconDanger{background:var(--color-red-200);color:var(--color-red-700)}.iconSuccess{background:var(--color-kiwi-100);color:var(--color-kiwi-700)}.iconWarning{background:var(--color-yellow-100);color:var(--color-orange-600)}.iconInfo{background:var(--color-blue-100);color:var(--color-blue-700)}.fieldGroup{display:grid;gap:var(--space-8);text-align:start}.fieldLabel{margin:0;font-family:var(--font-family-arabic-primary);font-weight:500;font-size:var(--font-size-sm);color:var(--form-label-muted)}.requiredMark{color:var(--color-danger);margin-inline-start:var(--space-2)}.fieldError{margin:0;color:var(--color-danger);font-size:var(--font-size-sm);font-weight:500}.btn{width:100%;min-height:var(--space-48);border-radius:var(--radius-xl);padding:var(--space-10) var(--space-20);font-family:var(--font-family-arabic-primary);font-weight:700;font-size:var(--font-size-md-15);text-align:center;border:1px solid transparent;cursor:pointer;transition:background .15s ease,border-color .15s ease,color .15s ease,opacity .15s ease}.btn:disabled{opacity:.55;cursor:not-allowed}.cancel{border:1.5px solid var(--color-brand-primary-900);color:var(--color-brand-primary-900);background:var(--background-bg-primary)}.cancel:hover:not(:disabled){background:var(--color-surface-2);border-color:var(--color-brand-primary-900);color:var(--color-brand-primary-900)}.confirmPrimary{background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand)}.confirmPrimary:hover:not(:disabled){background:var(--button-background-primary-bg-hover)}.confirmDanger{background:var(--color-attention-500);color:var(--background-bg-primary);border:none}.confirmDanger:hover:not(:disabled){background:var(--color-attention-600)}.confirmSuccess{background:var(--color-kiwi-700);color:var(--text-text-primaryon-brand)}.confirmWarning{background:var(--color-orange-500);color:var(--text-text-primaryon-brand)}.confirmInfo{background:var(--color-blue-700);color:var(--text-text-primaryon-brand)}\n"] }]
|
|
1685
1710
|
}], ctorParameters: () => [], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], confirmLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmLabel", required: false }] }], cancelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelLabel", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], confirmDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmDisabled", required: false }] }], cancelDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelDisabled", required: false }] }], hideCancelButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideCancelButton", required: false }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], centerHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "centerHeader", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], hasBodySlot: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasBodySlot", required: false }] }], onConfirmHandler: [{ type: i0.Input, args: [{ isSignal: true, alias: "onConfirmHandler", required: false }] }], close: [{ type: i0.Output, args: ["close"] }], cancel: [{ type: i0.Output, args: ["cancel"] }], confirm: [{ type: i0.Output, args: ["confirm"] }] } });
|
|
1686
1711
|
|
|
1712
|
+
/** Design-system demo host that shows `sce-confirm-dialog` and reports its visibility back through `visibleChange`. */
|
|
1687
1713
|
class SceConfirmDialogDemoComponent {
|
|
1688
1714
|
visible = input(false, ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
1689
1715
|
visibleChange = output();
|
|
@@ -1810,6 +1836,7 @@ function defaultStrings(dir) {
|
|
|
1810
1836
|
tooManyFiles: max => `Maximum ${max} files`,
|
|
1811
1837
|
};
|
|
1812
1838
|
}
|
|
1839
|
+
/** Drag-and-drop file picker with client-side accept/size/count validation and image previews; uploading is the consumer's job (it only emits `fileChange`/`filesChange`), it is not a ControlValueAccessor, and it uses `ViewEncapsulation.None`. */
|
|
1813
1840
|
class SceFileUploadZoneComponent {
|
|
1814
1841
|
translate = inject(TranslateService);
|
|
1815
1842
|
// Inputs
|
|
@@ -2050,6 +2077,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
2050
2077
|
args: ['fileInput']
|
|
2051
2078
|
}] } });
|
|
2052
2079
|
|
|
2080
|
+
/** Design-system demo page for `sce-file-upload-zone`, showing its zone and dialog variants under the `dir` passed in. */
|
|
2053
2081
|
class SceFileUploadZoneDemoComponent {
|
|
2054
2082
|
dir = input('rtl', ...(ngDevMode ? [{ debugName: "dir" }] : /* istanbul ignore next */ []));
|
|
2055
2083
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SceFileUploadZoneDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -2129,6 +2157,7 @@ function hashLabel(label) {
|
|
|
2129
2157
|
}
|
|
2130
2158
|
return Math.abs(hash);
|
|
2131
2159
|
}
|
|
2160
|
+
/** Maps a free-text Arabic or English status label to a tone by keyword match, falling back to one of eight stable hash-picked tones. */
|
|
2132
2161
|
function resolveBusinessStatusTone(label) {
|
|
2133
2162
|
const key = normalizeBusinessStatusKey(label ?? '');
|
|
2134
2163
|
if (!key) {
|
|
@@ -2141,6 +2170,7 @@ function resolveBusinessStatusTone(label) {
|
|
|
2141
2170
|
}
|
|
2142
2171
|
return FALLBACK_TONES[hashLabel(key) % FALLBACK_TONES.length];
|
|
2143
2172
|
}
|
|
2173
|
+
/** Resolves a label and its tone together, substituting `fallbackLabel` (an em dash by default) when the label is blank. */
|
|
2144
2174
|
function resolveBusinessStatusPresentation(label, fallbackLabel = '—') {
|
|
2145
2175
|
const resolved = (label ?? '').trim() || fallbackLabel;
|
|
2146
2176
|
return {
|
|
@@ -2148,6 +2178,7 @@ function resolveBusinessStatusPresentation(label, fallbackLabel = '—') {
|
|
|
2148
2178
|
tone: resolveBusinessStatusTone(resolved),
|
|
2149
2179
|
};
|
|
2150
2180
|
}
|
|
2181
|
+
/** Convenience wrapper over `resolveBusinessStatusPresentation` that returns the plain `{ label, tone }` shape table cells bind to. */
|
|
2151
2182
|
function toBusinessStatusTableCell(label, fallbackLabel = '—') {
|
|
2152
2183
|
const presentation = resolveBusinessStatusPresentation(label, fallbackLabel);
|
|
2153
2184
|
return { label: presentation.label, tone: presentation.tone };
|
|
@@ -2189,6 +2220,7 @@ function businessStatusToneClassName(tone) {
|
|
|
2189
2220
|
/**
|
|
2190
2221
|
* React source: Moatamed-Frontend/src/shared-utils/components/tag/tag.tsx
|
|
2191
2222
|
*/
|
|
2223
|
+
/** Status pill rendering `label`; colour comes from `businessTone` when set and otherwise from `variant` (default `pending`), and it uses `ViewEncapsulation.None`. */
|
|
2192
2224
|
class SceTagComponent {
|
|
2193
2225
|
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
2194
2226
|
variant = input('pending', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
@@ -2232,6 +2264,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
2232
2264
|
args: [{ host: { class: 'sce-tag' }, selector: 'sce-tag', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<span class=\"tag\" [class]=\"classes()\">{{ label() }}</span>\n", styles: ["@charset \"UTF-8\";.tag{display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;border-radius:var(--radius-full);border:0;font-weight:600;line-height:1.2;width:fit-content}.sizeSm,.sizeMd{padding-block:var(--space-4);padding-inline:var(--space-12);font-size:var(--font-size-xs)}.sizeLg{padding-block:var(--space-6);padding-inline:var(--space-14, var(--space-14));font-size:var(--font-size-md)}.variantPending{background:var(--color-yellow-100);color:var(--color-yellow-700)}.variantInProgress{background:var(--color-kiwi-100);color:var(--color-kiwi-700)}.variantInfo{background:var(--details-row-bg);color:var(--text-text-secondary-700)}.variantSuccess{background:var(--color-success-100);color:var(--color-success-700)}.variantInactive{background:var(--details-row-bg);color:var(--text-text-secondary-700)}.variantDanger{background:var(--color-red-100);color:var(--color-red-700)}.variantWarning{background:var(--color-yellow-100);color:var(--color-yellow-700)}.variantNeutral{background:var(--color-neutral-100);color:var(--color-neutral-700)}.variantPurple{background:var(--color-violet-100);color:var(--color-violet-800)}.variantAssigned{background:var(--color-blue-100);color:var(--color-blue-700)}.variantReview{background:var(--color-kiwi-100);color:var(--color-kiwi-700)}.variantNew{background:var(--color-info-100);color:var(--color-info-700)}.variantClosed{background:var(--color-neutral-200);color:var(--color-neutral-800)}.toneDraftInitial{background:var(--color-primary-100);color:var(--color-primary-800)}.toneModified{background:var(--color-info-100);color:var(--color-info-700)}.toneCancelled{background:var(--color-error-100);color:var(--color-error-700)}.toneClosed{background:var(--color-neutral-100);color:var(--color-neutral-600)}.toneReturnedEdit{background:var(--color-warning-100);color:var(--color-warning-700)}.toneActive{background:var(--color-success-100);color:var(--color-success-700)}.tonePendingBeneficiary{background:var(--color-warning-100);color:var(--color-warning-700)}.tonePendingApproval{background:var(--color-warning-100);color:var(--color-warning-800)}.toneRequestDraft{background:var(--color-info-100);color:var(--color-info-700)}.toneOpenOffers{background:var(--color-brand-secondary-100);color:var(--color-brand-secondary-800)}.toneExtended{background:var(--color-warning-100);color:var(--color-warning-700)}.toneRequestClosed{background:var(--color-neutral-100);color:var(--text-text-secondary-700)}.toneAwarded{background:var(--color-success-100);color:var(--color-success-800)}.toneRequestNew{background:var(--color-info-100);color:var(--color-info-700)}.toneRejected{background:var(--color-error-100);color:var(--color-attention-600)}.toneApproved{background:var(--color-success-100);color:var(--color-success-700)}.toneInvitationPublic{background:var(--color-primary-100);color:var(--text-text-brand-primary)}.toneInvitationDirect{background:var(--color-violet-100);color:var(--color-violet-800)}.toneFallback1{background:var(--color-info-50, var(--color-info-100));color:var(--color-brand-primary-800)}.toneFallback2{background:var(--color-pink-100);color:var(--color-pink-800)}.toneFallback3{background:var(--color-violet-100);color:var(--color-violet-800)}.toneFallback4{background:var(--color-warning-50, var(--color-warning-100));color:var(--color-warning-800)}.toneFallback5{background:var(--color-success-50, var(--color-success-100));color:var(--color-success-800)}.toneFallback6{background:var(--color-error-50, var(--color-error-100));color:var(--color-error-700)}.toneFallback7{background:var(--color-neutral-50);color:var(--color-violet-700)}.toneFallback8{background:var(--color-info-100);color:var(--color-info-800)}\n"] }]
|
|
2233
2265
|
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], businessTone: [{ type: i0.Input, args: [{ isSignal: true, alias: "businessTone", required: false }] }], toneClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "toneClassName", required: false }] }] } });
|
|
2234
2266
|
|
|
2267
|
+
/** Status tag whose colour tone is inferred from the label text when `tone` is not supplied explicitly. */
|
|
2235
2268
|
class SceBusinessStatusTagComponent {
|
|
2236
2269
|
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
2237
2270
|
tone = input(...(ngDevMode ? [undefined, { debugName: "tone" }] : /* istanbul ignore next */ []));
|
|
@@ -2248,6 +2281,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
2248
2281
|
args: [{ host: { class: 'sce-business-status-tag' }, selector: 'sce-business-status-tag', standalone: true, imports: [SceTagComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<sce-tag [label]=\"label()\" [size]=\"size()\" [className]=\"toneClass()\" />\n", styles: [":host{display:block}.sce-business-status-tag{display:contents}\n"] }]
|
|
2249
2282
|
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
2250
2283
|
|
|
2284
|
+
/** Loading placeholder in one of several shape variants, optionally repeated `count` times with a shortened last line. */
|
|
2251
2285
|
class SceSkeleton {
|
|
2252
2286
|
/** Shape variant of the skeleton */
|
|
2253
2287
|
variant = input('text', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
@@ -2320,6 +2354,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
2320
2354
|
args: [{ host: { class: 'sce-skeleton' }, selector: 'sce-skeleton', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [TranslatePipe], template: "<div\n class=\"skeleton-container\"\n [class.skeleton-container--multi]=\"isMultiLine()\"\n [style]=\"containerStyles()\"\n role=\"status\"\n [attr.aria-label]=\"'ARIA.LOADING_CONTENT' | translate\"\n>\n @for (line of lines(); track line.index) {\n <span\n class=\"skeleton\"\n [class.skeleton--text]=\"variant() === 'text'\"\n [class.skeleton--circular]=\"variant() === 'circular'\"\n [class.skeleton--rectangular]=\"variant() === 'rectangular'\"\n [class.skeleton--rounded]=\"variant() === 'rounded'\"\n [class.skeleton--avatar]=\"variant() === 'avatar'\"\n [class.skeleton--button]=\"variant() === 'button'\"\n [class.skeleton--chip]=\"variant() === 'chip'\"\n [class.skeleton--card]=\"variant() === 'card'\"\n [class.skeleton--image]=\"variant() === 'image'\"\n [class.skeleton--header]=\"variant() === 'header'\"\n [class.skeleton--paragraph]=\"variant() === 'paragraph'\"\n [class.skeleton--divider]=\"variant() === 'divider'\"\n [class.skeleton--badge]=\"variant() === 'badge'\"\n [class.skeleton--input]=\"variant() === 'input'\"\n [class.skeleton--pulse]=\"animation() === 'pulse'\"\n [class.skeleton--wave]=\"animation() === 'wave'\"\n [class.skeleton--no-animation]=\"animation() === 'none'\"\n [class.skeleton--last]=\"line.isLast\"\n [style]=\"skeletonStyles()\"\n aria-hidden=\"true\"\n ></span>\n }\n <span class=\"sr-only\">{{ 'COMMON.LOADING' | translate }}</span>\n</div>\n", styles: [":host{display:block;--skeleton-bg: rgba(31, 42, 55, .08);--skeleton-wave-color-start: transparent;--skeleton-wave-color-mid-light: rgba(255, 255, 255, .35);--skeleton-wave-color-mid: rgba(255, 255, 255, .6);--skeleton-wave-color-mid-light-end: rgba(255, 255, 255, .35);--skeleton-wave-color-end: transparent;--skeleton-pulse-duration: 1.8s;--skeleton-pulse-opacity-min: .4;--skeleton-wave-duration: 2s;--skeleton-radius-xs: var(--radius-xs);--skeleton-radius-sm: var(--radius-md);--skeleton-radius-md: var(--radius-lg);--skeleton-radius-lg: var(--radius-lg);--skeleton-radius-full: 9999px;--skeleton-radius-circle: 50%;--skeleton-text-height: 1em;--skeleton-text-scale-y: .7;--skeleton-circular-size: 48px;--skeleton-rect-height: 120px;--skeleton-avatar-size: 40px;--skeleton-button-width: 120px;--skeleton-button-height: var(--space-40);--skeleton-chip-width: var(--space-72);--skeleton-chip-height: var(--space-28);--skeleton-card-height: 200px;--skeleton-image-height: 180px;--skeleton-header-width: 60%;--skeleton-header-height: 1.5em;--skeleton-paragraph-height: .9em;--skeleton-paragraph-scale-y: .8;--skeleton-divider-height: 1px;--skeleton-badge-width: var(--space-48);--skeleton-badge-height: var(--space-20);--skeleton-input-height: 44px;--skeleton-last-line-width: 65%}:host-context(html[data-theme=dark]){--skeleton-bg: rgba(255, 255, 255, .1);--skeleton-wave-color-mid-light: rgba(255, 255, 255, .06);--skeleton-wave-color-mid: rgba(255, 255, 255, .12);--skeleton-wave-color-mid-light-end: rgba(255, 255, 255, .06)}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.skeleton-container{display:contents}.skeleton-container--multi{display:flex;flex-direction:column}.skeleton{display:block;background-color:var(--skeleton-bg);overflow:hidden;position:relative}.skeleton--text{width:100%;height:var(--skeleton-text-height);border-radius:var(--skeleton-radius-xs);transform-origin:0 55%;transform:scaleY(var(--skeleton-text-scale-y))}.skeleton--circular{width:var(--skeleton-circular-size);height:var(--skeleton-circular-size);border-radius:var(--skeleton-radius-circle);flex-shrink:0}.skeleton--rectangular{width:100%;height:var(--skeleton-rect-height);border-radius:0}.skeleton--rounded{width:100%;height:var(--skeleton-rect-height);border-radius:var(--skeleton-radius-md)}.skeleton--avatar{width:var(--skeleton-avatar-size);height:var(--skeleton-avatar-size);border-radius:var(--skeleton-radius-circle);flex-shrink:0}.skeleton--button{width:var(--skeleton-button-width);height:var(--skeleton-button-height);border-radius:var(--skeleton-radius-sm);flex-shrink:0}.skeleton--chip{display:inline-block;width:var(--skeleton-chip-width);height:var(--skeleton-chip-height);border-radius:var(--skeleton-radius-full);flex-shrink:0}.skeleton--card{width:100%;height:var(--skeleton-card-height);border-radius:var(--skeleton-radius-lg)}.skeleton--image{width:100%;height:var(--skeleton-image-height);border-radius:var(--skeleton-radius-md)}.skeleton--header{width:var(--skeleton-header-width);height:var(--skeleton-header-height);border-radius:var(--skeleton-radius-xs)}.skeleton--paragraph{width:100%;height:var(--skeleton-paragraph-height);border-radius:var(--skeleton-radius-xs);transform-origin:0 55%;transform:scaleY(var(--skeleton-paragraph-scale-y))}.skeleton--divider{width:100%;height:var(--skeleton-divider-height);border-radius:0}.skeleton--badge{display:inline-block;width:var(--skeleton-badge-width);height:var(--skeleton-badge-height);border-radius:var(--skeleton-radius-xs);flex-shrink:0}.skeleton--input{width:100%;height:var(--skeleton-input-height);border-radius:var(--skeleton-radius-sm)}.skeleton--last{width:var(--skeleton-last-line-width)}.skeleton--pulse{animation:skeleton-pulse var(--skeleton-pulse-duration) ease-in-out infinite}.skeleton--wave:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,var(--skeleton-wave-color-start) 0%,var(--skeleton-wave-color-mid-light) 30%,var(--skeleton-wave-color-mid) 50%,var(--skeleton-wave-color-mid-light-end) 70%,var(--skeleton-wave-color-end) 100%);animation:skeleton-wave var(--skeleton-wave-duration) ease-in-out infinite}.skeleton--no-animation{animation:none}.skeleton--no-animation:after{display:none}@keyframes skeleton-pulse{0%{opacity:1}50%{opacity:var(--skeleton-pulse-opacity-min)}to{opacity:1}}@keyframes skeleton-wave{0%{transform:translate(-100%)}50%{transform:translate(100%)}to{transform:translate(100%)}}@media(prefers-reduced-motion:reduce){.skeleton--pulse{animation:none}.skeleton--wave:after{animation:none;display:none}}\n"] }]
|
|
2321
2355
|
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], animation: [{ type: i0.Input, args: [{ isSignal: true, alias: "animation", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], borderRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "borderRadius", required: false }] }], count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], gap: [{ type: i0.Input, args: [{ isSignal: true, alias: "gap", required: false }] }], shrinkLastLine: [{ type: i0.Input, args: [{ isSignal: true, alias: "shrinkLastLine", required: false }] }], aspectRatio: [{ type: i0.Input, args: [{ isSignal: true, alias: "aspectRatio", required: false }] }] } });
|
|
2322
2356
|
|
|
2357
|
+
/** Empty state with an illustration (or a tinted PrimeIcons circle when no `imageSrc` is given), a title and a subtitle, each settable as literal text or a translation key; the `error` tone announces assertively via `role="alert"` while every other tone stays a polite status. */
|
|
2323
2358
|
class SceEmptyStateComponent {
|
|
2324
2359
|
/** Translation key for the title (e.g. COMMON.NO_DATA). Used when title is not provided. */
|
|
2325
2360
|
titleKey = input(...(ngDevMode ? [undefined, { debugName: "titleKey" }] : /* istanbul ignore next */ []));
|
|
@@ -2588,6 +2623,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
2588
2623
|
|
|
2589
2624
|
const IGNORED_ROW_ACTIVATION_TAGS = new Set(['BUTTON', 'A', 'INPUT', 'SELECT', 'TEXTAREA', 'LABEL']);
|
|
2590
2625
|
const IGNORED_ROW_ACTIVATION_ROLES = new Set(['button', 'link', 'switch', 'checkbox', 'menuitem']);
|
|
2626
|
+
/** Data table driven by `columns` and `rows`, with sorting, client- or server-side pagination, status/switch cells, and row actions; its empty body reads differently depending on `error`, `searching`, and `filtered`, and it uses `ViewEncapsulation.None`. */
|
|
2591
2627
|
class SceGenericTableComponent {
|
|
2592
2628
|
messageService = inject(MessageService);
|
|
2593
2629
|
translate = inject(TranslateService);
|
|
@@ -2919,6 +2955,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
2919
2955
|
], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"tableWrapper\">\n <div class=\"tableScroll\">\n <table class=\"table\" [attr.aria-busy]=\"resolvedLoading() ? 'true' : null\">\n <thead>\n <tr>\n @for (col of columnViews(); track col.field) {\n <th [style.text-align]=\"col.align ?? (col.isActionColumn ? 'center' : null)\">\n @if (col.sortable) {\n <button\n type=\"button\"\n class=\"sortHeaderButton\"\n [class.sortHeaderButtonActive]=\"col.isSortActive\"\n [style.justify-content]=\"col.align === 'center' ? 'center' : col.align === 'end' ? 'flex-end' : 'space-between'\"\n [style.gap]=\"col.align === 'center' ? '8px' : null\"\n [style.margin]=\"col.align === 'center' ? '0 auto' : col.isActionColumn ? '0 auto' : null\"\n (click)=\"onSortClick(col)\"\n >\n @if (col.isSortActive) {\n <i\n class=\"pi sortIconActive\"\n [class.pi-arrow-down]=\"sort()?.orderBy === 2\"\n [class.pi-arrow-up]=\"sort()?.orderBy !== 2\"\n aria-hidden=\"true\"\n ></i>\n } @else {\n <img src=\"/assets/icons/sort.svg\" width=\"16\" height=\"16\" class=\"sortIcon\" aria-hidden=\"true\" alt=\"\" />\n }\n <span>{{ col.header }}</span>\n </button>\n } @else {\n {{ col.header }}\n }\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (resolvedLoading()) {\n @for (row of skeletonRows(); track row) {\n <tr class=\"skeletonRow\">\n @for (col of columnViews(); track col.field) {\n <td class=\"skeletonCell\" [style.text-align]=\"col.align ?? (col.isActionColumn ? 'center' : null)\">\n @if (col.isActionColumn) {\n <sce-skeleton variant=\"rounded\" width=\"2rem\" height=\"2rem\" borderRadius=\"var(--radius-lg)\" animation=\"wave\" />\n } @else if (isStatusColumn(col.field)) {\n <sce-skeleton variant=\"chip\" width=\"5.5rem\" height=\"1.5rem\" animation=\"wave\" />\n } @else {\n <sce-skeleton variant=\"text\" [width]=\"col.skeletonWidth\" height=\"0.875rem\" animation=\"wave\" />\n }\n </td>\n }\n </tr>\n }\n } @else if (error() || rows().length === 0) {\n <tr class=\"placeholderRow\">\n <td [attr.colspan]=\"columns().length\" class=\"placeholderCell\">\n <sce-result-state\n [status]=\"bodyStatus()\"\n [titleKey]=\"bodyTitleKey()\"\n [subtitleKey]=\"bodySubtitleKey()\"\n [imageSrc]=\"bodyImage()\"\n [iconSize]=\"bodyIconSize()\"\n [actions]=\"bodyActions()\"\n (retry)=\"errorRetry.emit()\"\n (clearFilters)=\"clearFilters.emit()\"\n (clearSearch)=\"clearSearch.emit()\"\n />\n </td>\n </tr>\n } @else {\n @for (rowView of rowViews(); track rowView.row.id) {\n <tr\n [class.linkedRow]=\"rowView.row.rowHref\"\n [class.clickableRow]=\"!rowView.row.rowHref\"\n [tabindex]=\"!rowView.row.rowHref ? 0 : null\"\n (click)=\"onRowActivate(rowView.row, $any($event))\"\n (keydown.enter)=\"onRowActivate(rowView.row, $any($event))\"\n >\n @for (cellView of rowView.cells; track cellView.col.field; let colIndex = $index) {\n <td\n class=\"dataCell\"\n [class.hasLink]=\"rowView.row.rowHref\"\n [style.text-align]=\"cellView.col.align ?? (cellView.col.isActionColumn ? 'center' : null)\"\n [style.justify-content]=\"cellView.col.align === 'center' ? 'center' : cellView.col.align === 'end' ? 'flex-end' : null\"\n >\n @if (rowView.row.rowHref && !cellView.col.isActionColumn && !cellView.isSwitch) {\n <a [href]=\"rowView.row.rowHref\" class=\"rowCellLink\" data-row-nav-link tabindex=\"-1\" aria-hidden=\"true\"></a>\n }\n @if (cellView.isSwitch) {\n @let switchCell = $any(cellView.value);\n <sce-switch\n [checked]=\"switchCell.checked\"\n [disabled]=\"switchCell.disabled ?? false\"\n [showLabel]=\"true\"\n [activeLabel]=\"switchCell.activeLabel ?? ''\"\n [inactiveLabel]=\"switchCell.inactiveLabel ?? ''\"\n (checkedChange)=\"onSwitchChange(switchCell.rowId, cellView.col.field, $event); ($event)\"\n (click)=\"$event.stopPropagation()\"\n />\n } @else if (isStatusCell(cellView.value)) {\n @if (cellView.value.tone !== undefined || cellView.value.variant === undefined) {\n <sce-business-status-tag [label]=\"cellView.value.label\" [tone]=\"cellView.value.tone\" size=\"sm\" />\n } @else {\n <sce-tag [label]=\"cellView.value.label\" [variant]=\"cellView.value.variant!\" size=\"sm\" />\n }\n } @else if (cellView.col.isActionColumn) {\n @if (rowView.hasRowActions) {\n <div class=\"rowActionsCell\">\n @if (rowView.canEdit) {\n <button\n type=\"button\"\n class=\"rowActionBtn rowActionBtnEdit\"\n (click)=\"$event.stopPropagation(); editClick.emit(rowView.row)\"\n [attr.aria-label]=\"'table.edit' | translate\"\n >\n <i class=\"pi pi-pencil\" aria-hidden=\"true\"></i>\n </button>\n }\n @if (rowView.canDelete) {\n <button\n type=\"button\"\n class=\"rowActionBtn rowActionBtnDelete\"\n (click)=\"$event.stopPropagation(); deleteClick.emit(rowView.row)\"\n [attr.aria-label]=\"'table.delete' | translate\"\n >\n <i class=\"pi pi-trash\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n } @else {\n <i\n class=\"pi actionChevron\"\n [class.pi-chevron-left]=\"locale() === 'ar'\"\n [class.pi-chevron-right]=\"locale() === 'en'\"\n aria-hidden=\"true\"\n ></i>\n }\n } @else if (colIndex === 0 && rowView.row.rowHref) {\n @if (cellView.copyText) {\n <span class=\"copyCell\">\n <a [href]=\"rowView.row.rowHref\" class=\"rowPrimaryLink\" data-row-nav-link>\n <span class=\"copyCellValue\">{{ cellView.text }}</span>\n </a>\n <button\n type=\"button\"\n class=\"copyBtn\"\n [class.copyBtnCopied]=\"copiedCellKey() === rowView.row.id + '-' + cellView.col.field\"\n data-row-click-ignore\n [attr.aria-label]=\"'table.copy.ariaLabel' | translate\"\n (click)=\"$event.stopPropagation(); copyToClipboard(cellView.copyText!, rowView.row.id + '-' + cellView.col.field)\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\" />\n <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\" />\n </svg>\n </button>\n </span>\n } @else {\n <a [href]=\"rowView.row.rowHref\" class=\"rowPrimaryLink\" data-row-nav-link>\n {{ cellView.text }}\n </a>\n }\n } @else {\n @if (cellView.copyText) {\n <span class=\"copyCell\">\n <span class=\"copyCellValue\">{{ cellView.text }}</span>\n <button\n type=\"button\"\n class=\"copyBtn\"\n [class.copyBtnCopied]=\"copiedCellKey() === rowView.row.id + '-' + cellView.col.field\"\n data-row-click-ignore\n [attr.aria-label]=\"'table.copy.ariaLabel' | translate\"\n (click)=\"$event.stopPropagation(); copyToClipboard(cellView.copyText!, rowView.row.id + '-' + cellView.col.field)\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\" />\n <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\" />\n </svg>\n </button>\n </span>\n } @else {\n {{ cellView.text }}\n }\n }\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n\n @if (paginationEnabled() && resolvedLoading()) {\n <div class=\"paginationWrap paginationWrap--skeleton\" aria-hidden=\"true\">\n <sce-skeleton variant=\"text\" width=\"8rem\" height=\"2.25rem\" animation=\"wave\" />\n <sce-skeleton variant=\"text\" width=\"12rem\" height=\"2.25rem\" animation=\"wave\" />\n </div>\n } @else if (paginationEnabled()) {\n <div class=\"paginationWrap\">\n <sce-paginator\n [page]=\"resolvedPage()\"\n [pageSize]=\"resolvedPageSize()\"\n [totalItems]=\"totalItems()\"\n [locale]=\"locale()\"\n [pageSizeOptions]=\"pagination()?.pageSizeOptions ?? [4, 8, 12, 16]\"\n [showLabel]=\"pagination()?.showLabel\"\n (pageChange)=\"onPaginatorPageChange($event)\"\n (pageSizeChange)=\"onPaginatorPageSizeChange($event)\"\n />\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";.tableWrapper{background:var(--app-surface);border-radius:var(--space-16);display:flex;flex-direction:column;overflow:hidden}.paginationWrap{margin-block-start:var(--space-16)}.tableScroll{overflow-x:auto;overflow-y:hidden;min-width:0;-webkit-overflow-scrolling:touch;scrollbar-width:thin;scrollbar-color:var(--color-neutral-300) var(--color-neutral-100)}.tableScroll::-webkit-scrollbar{height:var(--space-10)}.tableScroll::-webkit-scrollbar-track{background:var(--color-neutral-100);border-radius:var(--radius-10)}.tableScroll::-webkit-scrollbar-thumb{background-color:var(--color-neutral-300);border-radius:var(--radius-10)}html[dir=rtl] .tableScroll{direction:rtl}.tableFooter{flex-shrink:0;margin-block-start:var(--space-16);padding-inline:var(--space-16);padding-block-end:var(--space-16);width:100%;box-sizing:border-box}.paginationWrap--skeleton{display:flex;align-items:center;justify-content:space-between;gap:var(--space-12);padding-inline:var(--space-16);min-height:var(--space-44)}.table tbody tr.skeletonRow{background:transparent;border-block-end:1px solid var(--card-border-subtle);pointer-events:none;min-height:4.5rem}.table tbody tr.skeletonRow:hover{background:transparent}.table tbody td.skeletonCell{vertical-align:middle;padding:var(--space-24) 2rem}.table tbody td.skeletonCell:last-child{display:table-cell}.table tbody td.skeletonCell sce-skeleton{display:block;max-width:100%}.loadingState{min-height:var(--size-280);display:flex;align-items:center;justify-content:center;padding:var(--space-24)}.emptyState{min-height:var(--size-280);display:flex;align-items:center;justify-content:center;flex-direction:column;gap:var(--space-12);text-align:center;padding:var(--space-24)}.emptyTitle{margin:0;font-family:var(--font-family-text);font-weight:600;font-size:var(--typo-size-text-lg);color:var(--text-text-display)}.emptySubtitle{margin:0;font-family:var(--font-family-text);font-weight:400;font-size:var(--typo-size-text-md);color:var(--text-text-secondary-paragraph)}.table{width:100%;min-width:max-content;border-collapse:collapse}.table thead{background:var(--color-neutral-100)}.table thead th{padding:var(--space-20) 1.75rem;text-align:start;color:var(--form-field-text-placeholder);font-weight:600;font-size:var(--font-size-xs);white-space:nowrap}.sortHeaderButton{border:0;background:transparent;display:inline-flex;align-items:center;gap:var(--space-6);color:inherit;font:inherit;cursor:pointer;padding:0;width:100%;justify-content:space-between;flex-direction:row-reverse}.sortHeaderButtonActive{color:var(--text-text-brand-primary)}.sortIcon{opacity:.7;transition:opacity .2s ease}.sortIconActive{opacity:1;font-size:var(--font-size-md);color:var(--text-text-brand-primary)}.table tbody tr{border-block-end:1px solid var(--card-border-subtle);transition:background-color .3s ease}.table tbody tr:hover{background:var(--table-row-hover)}.clickableRow{cursor:pointer}.linkedRow{position:relative;cursor:pointer}.dataCell .copyCell{position:relative;z-index:2;display:flex;align-items:center;width:100%;min-height:100%;gap:var(--space-6)}.dataCell .copyCell .rowPrimaryLink{flex:1;min-width:0}.dataCell .copyBtn{position:relative;z-index:3}.rowCellLink{position:absolute;inset:0;z-index:1}.rowPrimaryLink{position:relative;z-index:2;display:inline-flex;align-items:center;max-width:100%;color:inherit;font:inherit;font-weight:inherit;text-decoration:none}.rowPrimaryLink:hover{color:var(--text-text-brand-primary);text-decoration:underline}.cellContent{position:relative;z-index:2;pointer-events:none}.cellContent,.cellContent *{pointer-events:none}.cellContent :is(button,a,input,select,textarea,[role=switch],[data-row-click-ignore]){pointer-events:auto}.table tbody td{padding:var(--space-24) 2rem;color:var(--color-text-heading-700);font-size:var(--font-size-md);text-align:start;font-weight:500}.table tbody td:last-child{display:flex;align-items:center;justify-content:flex-start}.table tbody td.dataCell:last-child{display:table-cell}.copyCell{display:inline-flex;align-items:center;gap:var(--space-6);max-width:100%;min-width:0}.copyCellValue{min-width:0}.copyBtn{display:inline-flex;align-items:center;justify-content:center;width:var(--space-24);height:var(--space-24);flex-shrink:0;border:0;border-radius:var(--space-6);background:transparent;color:var(--form-field-text-placeholder);cursor:pointer;opacity:0;transition:opacity .15s ease,color .15s ease,background-color .15s ease}.cellContent .copyCell{position:relative;z-index:2}.copyCell:hover .copyBtn,.copyCell:focus-within .copyBtn,.dataCell:hover .copyBtn{opacity:1}.copyBtn:hover{color:var(--text-text-brand-primary);background:var(--surface-overlay-soft)}.copyBtnCopied{opacity:1;color:var(--text-text-brand-primary)}@media(hover:none){.copyBtn{opacity:1}}.table tbody tr.placeholderRow{background:transparent;border-block-end:0}.table tbody tr.placeholderRow:hover{background:transparent}.table tbody .placeholderRow td.placeholderCell,.table tbody .placeholderRow td.placeholderCell:last-child{display:table-cell;padding:0;text-align:center}.dataCell{position:relative}.rowCellLink{position:absolute;inset:0;z-index:1;opacity:0;cursor:pointer}.dataCell.hasLink{position:relative}.actionChevron{font-size:var(--font-size-md);color:var(--text-text-secondary-600);transition:transform .2s ease,color .2s ease}.clickableRow:hover .actionChevron,.linkedRow:hover .actionChevron{color:var(--text-text-brand-primary, var(--color-brand-primary-600));transform:scale(1.1)}.rowActionsCell{display:flex;align-items:center;justify-content:center;gap:var(--space-2, .5rem)}.rowActionBtn{display:inline-flex;align-items:center;justify-content:center;width:var(--space-32);height:var(--space-32);border-radius:var(--radius-md, .5rem);border:1px solid transparent;background:transparent;cursor:pointer;transition:background .15s ease,color .15s ease;color:var(--text-text-secondary-600)}.rowActionBtn:hover{background:var(--color-neutral-100, var(--color-neutral-100));color:var(--text-text-primary-900)}.rowActionBtn.rowActionBtnDelete{color:var(--text-text-error-primary, var(--color-attention-600))}.rowActionBtn.rowActionBtnDelete:hover{background:var(--color-error-50, var(--color-error-50));color:var(--color-error-600, var(--color-error-600))}\n"] }]
|
|
2920
2956
|
}], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: false }] }], loadingDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingDelay", required: false }] }], sort: [{ type: i0.Input, args: [{ isSignal: true, alias: "sort", required: false }] }], pagination: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagination", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], errorStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorStatus", required: false }] }], filtered: [{ type: i0.Input, args: [{ isSignal: true, alias: "filtered", required: false }] }], searching: [{ type: i0.Input, args: [{ isSignal: true, alias: "searching", required: false }] }], errorRetry: [{ type: i0.Output, args: ["errorRetry"] }], clearFilters: [{ type: i0.Output, args: ["clearFilters"] }], clearSearch: [{ type: i0.Output, args: ["clearSearch"] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], pageSizeChange: [{ type: i0.Output, args: ["pageSizeChange"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], switchChange: [{ type: i0.Output, args: ["switchChange"] }], editClick: [{ type: i0.Output, args: ["editClick"] }], deleteClick: [{ type: i0.Output, args: ["deleteClick"] }] } });
|
|
2921
2957
|
|
|
2958
|
+
/** Design-system demo harness for `sce-generic-table` with three hard-coded rows; its columns and rows re-translate whenever `LanguageService.locale()` changes. */
|
|
2922
2959
|
class SceGenericTableDemoComponent {
|
|
2923
2960
|
translate = inject(TranslateService);
|
|
2924
2961
|
language = inject(LanguageService);
|
|
@@ -2964,6 +3001,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
2964
3001
|
|
|
2965
3002
|
/** Simple in-memory SVG cache shared across all SceIcon instances. */
|
|
2966
3003
|
const svgCache = new Map();
|
|
3004
|
+
/** Inline SVG icon that fetches the named asset over HTTP, sanitizes it and caches it in a module-level cache shared by all instances. */
|
|
2967
3005
|
class SceIcon {
|
|
2968
3006
|
http = inject(HttpClient);
|
|
2969
3007
|
sanitizer = inject(DomSanitizer);
|
|
@@ -3025,6 +3063,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3025
3063
|
args: [{ selector: 'sce-icon', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-icon', '[style.width.px]': 'widthPx()', '[style.height.px]': 'heightPx()' }, template: "@if (iconSrc()) {\n <span class=\"sce-icon\" [class]=\"'sce-icon ' + (name() || '')\" [innerHTML]=\"svgContent()\"></span>\n}\n", styles: [":host{display:block;display:inline-flex;align-items:center;justify-content:center;width:100%;height:100%}.sce-icon{display:flex;width:100%;height:100%;align-items:center;justify-content:center}.sce-icon ::ng-deep svg{flex-grow:1;width:100%;height:100%;color:inherit}\n"] }]
|
|
3026
3064
|
}], ctorParameters: () => [], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }] } });
|
|
3027
3065
|
|
|
3066
|
+
/** Verified/unverified badge icon derived from an engineering office's service-provider status. */
|
|
3028
3067
|
class SceEngineeringOfficeVerificationBadgeComponent {
|
|
3029
3068
|
status = input(...(ngDevMode ? [undefined, { debugName: "status" }] : /* istanbul ignore next */ []));
|
|
3030
3069
|
size = input(24, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
@@ -3077,6 +3116,7 @@ function isOfficeBrandPhotoSrc(src) {
|
|
|
3077
3116
|
function officeImageNeedsUnoptimized(src) {
|
|
3078
3117
|
return (src.startsWith('/images/') || src.startsWith('/api/cms/media') || src.startsWith('blob:') || src.startsWith('data:'));
|
|
3079
3118
|
}
|
|
3119
|
+
/** Circular office logo that renders uploaded photos with `object-fit: cover` and bundled SVGs with `contain`, falling back to the default office icon when the source is empty or fails to load. */
|
|
3080
3120
|
class SceOfficeBrandLogoComponent {
|
|
3081
3121
|
/** Logo source. http(s)/CMS/blob/data render as photo; anything else as bundled icon. */
|
|
3082
3122
|
src = input('', ...(ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []));
|
|
@@ -3106,6 +3146,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3106
3146
|
/**
|
|
3107
3147
|
* React source: feedback/inline-api-error.tsx
|
|
3108
3148
|
*/
|
|
3149
|
+
/** Inline error banner for an already-resolved `message`, showing a retry button only when `retryable` is opted into (it defaults to false so a failed save cannot re-trigger a load). */
|
|
3109
3150
|
class SceInlineApiErrorComponent {
|
|
3110
3151
|
message = input.required(...(ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []));
|
|
3111
3152
|
className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
@@ -3170,6 +3211,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3170
3211
|
/**
|
|
3171
3212
|
* React source: Moatamed-Frontend/src/shared-utils/components/notifications/notification-type-badge.tsx
|
|
3172
3213
|
*/
|
|
3214
|
+
/** Small pill showing a notification's kind: renders the already-translated `label` styled by `variant` (default `info`), with extra classes from `className`; uses `ViewEncapsulation.None`. */
|
|
3173
3215
|
class SceNotificationTypeBadgeComponent {
|
|
3174
3216
|
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
3175
3217
|
variant = input('info', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
@@ -3235,6 +3277,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3235
3277
|
}, template: "@if (value(); as text) {\n <bdi class=\"sce-bidi-isolate__run\" [class.sce-bidi-isolate__run--tabular]=\"tabular()\" [attr.dir]=\"dir()\">{{ text }}</bdi>\n} @else {\n <bdi class=\"sce-bidi-isolate__run\" [class.sce-bidi-isolate__run--tabular]=\"tabular()\" [attr.dir]=\"dir()\"><ng-content /></bdi>\n}\n", styles: ["@charset \"UTF-8\";:host{display:inline}.sce-bidi-isolate__run{unicode-bidi:isolate}.sce-bidi-isolate__run--tabular{font-variant-numeric:tabular-nums lining-nums}\n"] }]
|
|
3236
3278
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], tabular: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabular", required: false }] }] } });
|
|
3237
3279
|
|
|
3280
|
+
/** Read-only label/value card used throughout profile and review screens, with default, highlight and editable variants. */
|
|
3238
3281
|
class SceInfoFieldCardComponent {
|
|
3239
3282
|
label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
|
|
3240
3283
|
value = input(...(ngDevMode ? [undefined, { debugName: "value" }] : /* istanbul ignore next */ []));
|
|
@@ -3260,6 +3303,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3260
3303
|
args: [{ host: { class: 'sce-info-field-card' }, selector: 'sce-info-field-card', standalone: true, imports: [SceBidiIsolate], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"cardClasses()\">\n @if (label() != null) {\n <p class=\"label\" [class]=\"labelClassName() ?? ''\">{{ label() }}</p>\n }\n @if (value() != null) {\n <p class=\"value\" [class]=\"valueClassName() ?? ''\">\n <!--\n Isolated because this card is the sink for licence, VAT, IBAN, CR, national-ID, phone,\n and email values, which are Latin runs sitting inside an Arabic-direction card. `dir=\"auto\"`\n leaves Arabic values untouched, so isolation here is unconditionally safe.\n -->\n <sce-bidi-isolate [value]=\"value()\" />\n </p>\n }\n <ng-content />\n</div>\n", styles: ["@charset \"UTF-8\";.card{display:flex;flex-direction:column;gap:var(--space-8);min-width:0;min-height:var(--space-72);padding:var(--space-16);border-radius:var(--space-12);background:var(--app-surface-hover);box-sizing:border-box}.cardHighlight{background:var(--color-base-white)}.cardEditable{background:var(--color-surface);border:1px solid var(--color-neutral-200);cursor:text}.cardCompact{min-height:auto;padding:var(--space-10) var(--space-12);gap:var(--space-4);border-radius:var(--space-8)}.label{margin:0;font-family:var(--font-family-arabic-primary);font-weight:var(--details-label-weight);font-size:var(--details-label-size);color:var(--details-label-color);text-align:start}.cardHighlight .label{color:var(--color-warning-600)}.cardCompact .label{font-weight:500;font-size:var(--font-size-xs);color:var(--text-text-secondary-700)}.cardHighlight.cardCompact .label{color:var(--color-warning-600)}.value{margin:0;font-family:var(--font-family-arabic-primary);font-weight:var(--details-value-weight);font-size:var(--details-value-size);color:var(--details-value-color);text-align:start;overflow-wrap:break-word}.cardCompact .value{font-weight:600;font-size:var(--font-size-sm);color:var(--text-text-primary-900)}.grid{display:grid;width:100%;box-sizing:border-box;gap:var(--space-20);grid-template-columns:repeat(2,minmax(0,1fr))}.gridGapSm{gap:var(--space-12)}.columns1{grid-template-columns:1fr}.columns3{grid-template-columns:repeat(3,minmax(0,1fr))}.columns4{grid-template-columns:repeat(4,minmax(0,1fr))}sce-info-field-card:has(.fullWidth){grid-column:1/-1}.fullWidth{grid-column:1/-1}@media(max-width:640px){.grid:not(.columns1){grid-template-columns:1fr}.card{padding:var(--space-14)}.label,.value{text-align:start;overflow-wrap:anywhere}}@media(max-width:992px){.grid.columns3,.grid.columns4{grid-template-columns:1fr}}\n"] }]
|
|
3261
3304
|
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], 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 }] }], labelClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelClassName", required: false }] }], valueClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueClassName", required: false }] }] } });
|
|
3262
3305
|
|
|
3306
|
+
/** Layout wrapper that arranges projected info-field cards into a one- to four-column grid. */
|
|
3263
3307
|
class SceInfoFieldsGridComponent {
|
|
3264
3308
|
columns = input(2, ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
|
|
3265
3309
|
gap = input('default', ...(ngDevMode ? [{ debugName: "gap" }] : /* istanbul ignore next */ []));
|
|
@@ -3370,6 +3414,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3370
3414
|
args: [{ host: { class: 'sce-public-legal-prose' }, selector: 'sce-public-legal-prose', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div #root [class]=\"rootClass()\" [attr.dir]=\"rootDir()\" [innerHTML]=\"sanitizedHtml()\"></div>\n", styles: [".sce-public-legal-prose{display:contents}\n"] }]
|
|
3371
3415
|
}], ctorParameters: () => [], propDecorators: { html: [{ type: i0.Input, args: [{ isSignal: true, alias: "html", required: true }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], root: [{ type: i0.ViewChild, args: ['root', { isSignal: true }] }] } });
|
|
3372
3416
|
|
|
3417
|
+
/** Table row-action affordance rendering the chevron icon with `alt` as its accessible text; uses `ViewEncapsulation.None`, so its styles are global. */
|
|
3373
3418
|
class SceRowActionIconComponent {
|
|
3374
3419
|
alt = input('', ...(ngDevMode ? [{ debugName: "alt" }] : /* istanbul ignore next */ []));
|
|
3375
3420
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SceRowActionIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -3381,6 +3426,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3381
3426
|
}], propDecorators: { alt: [{ type: i0.Input, args: [{ isSignal: true, alias: "alt", required: false }] }] } });
|
|
3382
3427
|
|
|
3383
3428
|
const DEFAULT_CLIENT_AVATAR = '/assets/images/Avatar.png';
|
|
3429
|
+
/** Avatar/role icon for a dashboard account; the supplied `photoUrl` is only used for individual client accounts, everything else falls back to the role icon. */
|
|
3384
3430
|
class SceDashboardAccountRoleIconComponent {
|
|
3385
3431
|
role = input('client', ...(ngDevMode ? [{ debugName: "role" }] : /* istanbul ignore next */ []));
|
|
3386
3432
|
accountKind = input(...(ngDevMode ? [undefined, { debugName: "accountKind" }] : /* istanbul ignore next */ []));
|
|
@@ -3407,6 +3453,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3407
3453
|
args: [{ host: { class: 'sce-dashboard-account-role-icon' }, selector: 'sce-dashboard-account-role-icon', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "@switch (role()) {\n @case ('manager') {\n <span class=\"iconContainerManager\">\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M12 15a7 7 0 1 0 0-14 7 7 0 0 0 0 14z\" />\n <path d=\"m19.4 15-1.2 5.4a2 2 0 0 1-2 1.6H7.8a2 2 0 0 1-2-1.6L4.6 15\" />\n </svg>\n </span>\n }\n @case ('entity') {\n <span class=\"iconContainerEntity\">\n <svg\n width=\"28\"\n height=\"28\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M6 22V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v18Z\" />\n <path d=\"M6 12H4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2\" />\n <path d=\"M18 9h2a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-2\" />\n <path d=\"M10 6h4\" />\n <path d=\"M10 10h4\" />\n <path d=\"M10 14h4\" />\n <path d=\"M10 18h4\" />\n </svg>\n </span>\n }\n @case ('office') {\n <span class=\"iconContainerOffice\">\n <img src=\"/assets/images/Avatar-1.png\" alt=\"\" class=\"officeAvatarImage\" />\n </span>\n }\n @default {\n @if (showClientPhoto()) {\n <img [src]=\"photoUrl() ?? defaultAvatar\" [alt]=\"alt()\" class=\"accountIconImage\" [width]=\"width()\" [height]=\"height()\" />\n } @else {\n <span class=\"iconContainerClient\">\n <svg\n width=\"28\"\n height=\"28\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2\" />\n <circle cx=\"12\" cy=\"7\" r=\"4\" />\n </svg>\n </span>\n }\n }\n}\n", styles: ["sce-dashboard-account-role-icon{display:inline-flex;align-items:center;justify-content:center}.accountIconImage{width:auto;height:auto;border-radius:var(--radius-full);object-fit:cover}.iconContainerManager,.iconContainerEntity,.iconContainerOffice{display:flex;align-items:center;justify-content:center;width:var(--space-40);height:var(--space-40);border-radius:var(--radius-full)}.iconContainerManager{background:var(--surface-accent-brand);color:var(--background-bg-primary)}.iconContainerEntity{background:var(--color-info-100);color:var(--text-text-primary-900)}.iconContainerOffice{background:var(--surface-muted);overflow:hidden}.iconContainerClient{display:flex;align-items:center;justify-content:center;width:var(--space-40);height:var(--space-40);border-radius:var(--radius-full);background:var(--surface-muted);color:var(--text-text-secondary-700)}.officeAvatarImage{width:100%;height:100%;object-fit:cover}\n"] }]
|
|
3408
3454
|
}], propDecorators: { role: [{ type: i0.Input, args: [{ isSignal: true, alias: "role", required: false }] }], accountKind: [{ type: i0.Input, args: [{ isSignal: true, alias: "accountKind", required: false }] }], alt: [{ type: i0.Input, args: [{ isSignal: true, alias: "alt", required: false }] }], photoUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "photoUrl", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }] } });
|
|
3409
3455
|
|
|
3456
|
+
/** Panel rendering a list of label/value review fields as table rows, skipping any item marked `hidden`. */
|
|
3410
3457
|
class SceReviewFieldTablePanelComponent {
|
|
3411
3458
|
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
3412
3459
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SceReviewFieldTablePanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -3506,6 +3553,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3506
3553
|
args: [{ host: { class: 'sce-engineering-office-card' }, selector: 'sce-engineering-office-card', standalone: true, imports: [RouterLink, SceEngineeringOfficeVerificationBadgeComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (office().href) {\n <a [routerLink]=\"office().href\" [class]=\"wrapperClass()\">\n <div [class]=\"viewMode() === 'list' ? 'mediaList' : 'media'\">\n @if (showCoverSkeleton()) {\n <div class=\"mediaSkeleton\" aria-hidden=\"true\"></div>\n }\n @if (office().imageSrc || office().heroObjectUrl) {\n <img\n [src]=\"office().imageSrc || office().heroObjectUrl\"\n [alt]=\"office().imageAlt\"\n class=\"mediaImg\"\n [class.mediaImgLoaded]=\"coverLoaded()\"\n [class.mediaImgLoading]=\"!coverLoaded()\"\n (load)=\"onCoverLoad()\"\n />\n }\n @if (bookmarkLabel()) {\n <button\n type=\"button\"\n class=\"bookmark\"\n [class.bookmarkActive]=\"bookmarked()\"\n [attr.aria-label]=\"bookmarkLabel()\"\n [attr.aria-pressed]=\"bookmarked()\"\n (click)=\"onBookmarkClick($event)\"\n >\n <img class=\"bookmarkIcon\" src=\"/assets/icons/bookmark-add-02.svg\" alt=\"\" aria-hidden=\"true\" />\n </button>\n }\n <div class=\"logo\" aria-hidden=\"true\">\n <div class=\"logoInner\">\n @if (showLogoSkeleton()) {\n <div class=\"logoPlaceholderSkeleton\" aria-hidden=\"true\"></div>\n }\n @if (office().logoSrc || office().logoObjectUrl) {\n <img\n [src]=\"office().logoSrc || office().logoObjectUrl\"\n alt=\"\"\n class=\"logoPhoto\"\n [class.logoPhotoLoaded]=\"logoLoaded()\"\n [class.logoPhotoLoading]=\"!logoLoaded()\"\n (load)=\"onLogoLoad()\"\n />\n }\n </div>\n </div>\n </div>\n\n <div class=\"body\">\n <div class=\"nameRow\">\n <div class=\"name\">{{ office().name }}</div>\n @if (office().verified) {\n <sce-engineering-office-verification-badge [status]=\"VerifiedStatus\" [size]=\"16\" className=\"verifiedIcon\" />\n }\n </div>\n\n <div class=\"tags\" tabindex=\"0\">\n @for (tag of office().tags; track tag) {\n <span class=\"tag\">{{ tag }}</span>\n }\n @if (office().extraTagsCount > 0) {\n <span class=\"tag\">{{ office().extraTagsCount }} {{ otherLabel() }}</span>\n }\n </div>\n\n <div class=\"meta\">\n <div class=\"metaItem\">\n <span class=\"metaLabel\">{{ ratingLabel() }}</span>\n <span class=\"metaValue\">\n <img class=\"metaIcon\" src=\"/assets/icons/star-rating.svg\" alt=\"\" aria-hidden=\"true\" />\n <span>{{ office().ratingValue }}</span>\n <span class=\"ratingCount\">{{ office().ratingCount }}</span>\n </span>\n </div>\n <div class=\"metaItem\">\n <span class=\"metaLabel\">{{ locationLabel() }}</span>\n <span class=\"metaValue\">\n <img class=\"metaIcon\" src=\"/assets/icons/location.svg\" alt=\"\" aria-hidden=\"true\" />\n <span>{{ office().location }}</span>\n </span>\n </div>\n </div>\n </div>\n </a>\n} @else {\n <article [class]=\"wrapperClass()\">\n <div [class]=\"viewMode() === 'list' ? 'mediaList' : 'media'\">\n @if (showCoverSkeleton()) {\n <div class=\"mediaSkeleton\" aria-hidden=\"true\"></div>\n }\n @if (office().imageSrc || office().heroObjectUrl) {\n <img\n [src]=\"office().imageSrc || office().heroObjectUrl\"\n [alt]=\"office().imageAlt\"\n class=\"mediaImg\"\n [class.mediaImgLoaded]=\"coverLoaded()\"\n [class.mediaImgLoading]=\"!coverLoaded()\"\n (load)=\"onCoverLoad()\"\n />\n }\n @if (bookmarkLabel()) {\n <button\n type=\"button\"\n class=\"bookmark\"\n [class.bookmarkActive]=\"bookmarked()\"\n [attr.aria-label]=\"bookmarkLabel()\"\n [attr.aria-pressed]=\"bookmarked()\"\n (click)=\"onBookmarkClick($event)\"\n >\n <img class=\"bookmarkIcon\" src=\"/assets/icons/bookmark-add-02.svg\" alt=\"\" aria-hidden=\"true\" />\n </button>\n }\n <div class=\"logo\" aria-hidden=\"true\">\n <div class=\"logoInner\">\n @if (showLogoSkeleton()) {\n <div class=\"logoPlaceholderSkeleton\" aria-hidden=\"true\"></div>\n }\n @if (office().logoSrc || office().logoObjectUrl) {\n <img\n [src]=\"office().logoSrc || office().logoObjectUrl\"\n alt=\"\"\n class=\"logoPhoto\"\n [class.logoPhotoLoaded]=\"logoLoaded()\"\n [class.logoPhotoLoading]=\"!logoLoaded()\"\n (load)=\"onLogoLoad()\"\n />\n }\n </div>\n </div>\n </div>\n\n <div class=\"body\">\n <div class=\"nameRow\">\n <div class=\"name\">{{ office().name }}</div>\n @if (office().verified) {\n <sce-engineering-office-verification-badge [status]=\"VerifiedStatus\" [size]=\"16\" className=\"verifiedIcon\" />\n }\n </div>\n\n <div class=\"tags\" tabindex=\"0\">\n @for (tag of office().tags; track tag) {\n <span class=\"tag\">{{ tag }}</span>\n }\n @if (office().extraTagsCount > 0) {\n <span class=\"tag\">{{ office().extraTagsCount }} {{ otherLabel() }}</span>\n }\n </div>\n\n <div class=\"meta\">\n <div class=\"metaItem\">\n <span class=\"metaLabel\">{{ ratingLabel() }}</span>\n <span class=\"metaValue\">\n <img class=\"metaIcon\" src=\"/assets/icons/star-rating.svg\" alt=\"\" aria-hidden=\"true\" />\n <span>{{ office().ratingValue }}</span>\n <span class=\"ratingCount\">{{ office().ratingCount }}</span>\n </span>\n </div>\n <div class=\"metaItem\">\n <span class=\"metaLabel\">{{ locationLabel() }}</span>\n <span class=\"metaValue\">\n <img class=\"metaIcon\" src=\"/assets/icons/location.svg\" alt=\"\" aria-hidden=\"true\" />\n <span>{{ office().location }}</span>\n </span>\n </div>\n </div>\n </div>\n </article>\n}\n", styles: ["@charset \"UTF-8\";sce-engineering-office-card-skeleton,sce-engineering-office-card{display:block}sce-engineering-office-card-skeleton .card,sce-engineering-office-card .card{width:100%;min-height:var(--size-320);border-radius:var(--radius-brand-sm);padding:var(--space-18);background:var(--surface-primary);border:1px solid var(--border-subtle);box-shadow:var(--shadow-card-soft-subtle);text-decoration:none;color:inherit;display:grid;gap:var(--space-8)}sce-engineering-office-card-skeleton .cardList,sce-engineering-office-card .cardList{grid-template-columns:180px minmax(0,1fr);grid-template-areas:\"media content\";align-items:center;min-height:auto;direction:rtl}sce-engineering-office-card-skeleton .cardList[dir=ltr],sce-engineering-office-card .cardList[dir=ltr]{direction:ltr}sce-engineering-office-card-skeleton .media,sce-engineering-office-card .media{position:relative;width:100%;max-width:100%;min-width:0;height:10.5rem;border-radius:var(--radius-brand-sm);overflow:hidden;isolation:isolate;background:var(--surface-overlay-soft)}sce-engineering-office-card-skeleton .mediaList,sce-engineering-office-card .mediaList{grid-area:media;position:relative;width:100%;height:100%;border-radius:var(--radius-brand-sm);overflow:hidden;isolation:isolate;background:var(--surface-overlay-soft)}sce-engineering-office-card-skeleton .mediaImg,sce-engineering-office-card .mediaImg{width:100%;height:100%;object-fit:cover;object-position:center;transition:opacity .35s ease}sce-engineering-office-card-skeleton .mediaImgLoading,sce-engineering-office-card .mediaImgLoading{opacity:0}sce-engineering-office-card-skeleton .mediaImgLoaded,sce-engineering-office-card .mediaImgLoaded{opacity:1}sce-engineering-office-card-skeleton .mediaSkeleton,sce-engineering-office-card-skeleton .logoSkeleton,sce-engineering-office-card-skeleton .lineSkeleton,sce-engineering-office-card-skeleton .tagSkeleton,sce-engineering-office-card .mediaSkeleton,sce-engineering-office-card .logoSkeleton,sce-engineering-office-card .lineSkeleton,sce-engineering-office-card .tagSkeleton{position:relative;overflow:hidden;background:var(--surface-overlay-soft)}sce-engineering-office-card-skeleton .mediaSkeleton,sce-engineering-office-card .mediaSkeleton{position:absolute;inset:0;z-index:1}sce-engineering-office-card-skeleton .mediaSkeleton:after,sce-engineering-office-card-skeleton .logoSkeleton:after,sce-engineering-office-card-skeleton .lineSkeleton:after,sce-engineering-office-card-skeleton .tagSkeleton:after,sce-engineering-office-card .mediaSkeleton:after,sce-engineering-office-card .logoSkeleton:after,sce-engineering-office-card .lineSkeleton:after,sce-engineering-office-card .tagSkeleton:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.55) 45%,transparent 100%);animation:office-card-shimmer 1.35s ease-in-out infinite}sce-engineering-office-card-skeleton .logoSkeleton,sce-engineering-office-card .logoSkeleton{position:absolute;bottom:.9rem;inset-inline-start:.9rem;width:65.3198776245px;height:65.3198776245px;border-radius:var(--radius-full);z-index:2}sce-engineering-office-card-skeleton .cardSkeleton,sce-engineering-office-card .cardSkeleton{pointer-events:none}sce-engineering-office-card-skeleton .lineSkeleton[data-size=title],sce-engineering-office-card .lineSkeleton[data-size=title]{width:72%;height:1.35rem;border-radius:var(--space-8)}sce-engineering-office-card-skeleton .lineSkeleton[data-size=meta],sce-engineering-office-card .lineSkeleton[data-size=meta]{width:55%;height:var(--space-16);border-radius:.4rem}sce-engineering-office-card-skeleton .tagsSkeleton,sce-engineering-office-card .tagsSkeleton{display:flex;gap:var(--space-8)}sce-engineering-office-card-skeleton .tagSkeleton,sce-engineering-office-card .tagSkeleton{width:var(--space-88, var(--size-88));height:1.625rem;border-radius:var(--radius-full)}sce-engineering-office-card-skeleton .metaSkeleton,sce-engineering-office-card .metaSkeleton{margin-block-start:.4rem;padding-block-start:var(--space-12);border-block-start:1px dashed var(--border-subtle);display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12)}@keyframes office-card-shimmer{to{transform:translate(100%)}}sce-engineering-office-card-skeleton .bookmark,sce-engineering-office-card .bookmark{position:absolute;top:.9rem;inset-inline-end:.9rem;width:var(--space-44, var(--size-44));height:var(--space-44, var(--size-44));border-radius:var(--radius-sm);border:0;background:var(--surface-overlay-white-alpha-36);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;z-index:2}sce-engineering-office-card-skeleton .bookmarkIcon,sce-engineering-office-card .bookmarkIcon{width:var(--space-20);height:var(--space-20)}sce-engineering-office-card-skeleton .logo,sce-engineering-office-card .logo{position:absolute;bottom:.9rem;inset-inline-start:.9rem;width:65.3198776245px;height:65.3198776245px;border-radius:var(--radius-full);background:var(--surface-primary);border:2px solid var(--border-chip-light);box-shadow:var(--shadow-card-soft-subtle);overflow:hidden;z-index:2}sce-engineering-office-card-skeleton .logoInner,sce-engineering-office-card .logoInner{position:relative;width:100%;height:100%;display:flex;align-items:center;justify-content:center}sce-engineering-office-card-skeleton .logoPhoto,sce-engineering-office-card .logoPhoto{object-fit:cover;object-position:center;transition:opacity .35s ease;height:100%}sce-engineering-office-card-skeleton .logoPhotoLoading,sce-engineering-office-card .logoPhotoLoading{opacity:0}sce-engineering-office-card-skeleton .logoPhotoLoaded,sce-engineering-office-card .logoPhotoLoaded{opacity:1}sce-engineering-office-card-skeleton .logoPlaceholderSkeleton,sce-engineering-office-card .logoPlaceholderSkeleton{position:absolute;inset:0;border-radius:var(--radius-full);overflow:hidden;background:var(--surface-overlay-soft);z-index:1}sce-engineering-office-card-skeleton .logoPlaceholderSkeleton:after,sce-engineering-office-card .logoPlaceholderSkeleton:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.55) 45%,transparent 100%);animation:office-card-shimmer 1.35s ease-in-out infinite}sce-engineering-office-card-skeleton .logoIcon,sce-engineering-office-card .logoIcon{width:58%;height:58%;object-fit:contain;display:block}sce-engineering-office-card-skeleton .body,sce-engineering-office-card .body{padding-block-start:var(--space-12);display:grid;gap:var(--space-8)}sce-engineering-office-card-skeleton .cardList .body,sce-engineering-office-card .cardList .body{grid-area:content;padding-block-start:0}sce-engineering-office-card-skeleton .nameRow,sce-engineering-office-card .nameRow{display:flex;align-items:center;justify-content:flex-start;gap:var(--space-8);margin-block-end:var(--space-6)}sce-engineering-office-card-skeleton .name,sce-engineering-office-card .name{font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-lg);font-weight:var(--font-weight-bold);color:var(--text-primary-emphasis);text-align:start;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}sce-engineering-office-card-skeleton .verifiedIcon,sce-engineering-office-card .verifiedIcon{width:var(--space-20);height:var(--space-20)}sce-engineering-office-card-skeleton .tags,sce-engineering-office-card .tags{display:flex;flex-wrap:nowrap;gap:var(--space-8);justify-content:flex-start;align-items:center;overflow-x:auto;scrollbar-width:none;margin-block-end:var(--space-6)}sce-engineering-office-card-skeleton .tag,sce-engineering-office-card .tag{width:fit-content;height:var(--space-26, var(--size-26));padding:var(--space-4) var(--space-12);border-radius:var(--radius-2xl, var(--radius-2xl));background:var(--color-neutral-100);font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-xs);font-weight:var(--font-weight-medium);color:var(--text-primary-soft);display:inline-flex;align-items:center;white-space:nowrap}sce-engineering-office-card-skeleton .meta,sce-engineering-office-card .meta{margin-block-start:.4rem;padding-block-start:var(--space-12);border-block-start:1px dashed var(--border-subtle);display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12)}sce-engineering-office-card-skeleton .metaItem,sce-engineering-office-card .metaItem{display:grid;gap:.4rem;justify-items:flex-start;text-align:start;min-width:0}sce-engineering-office-card-skeleton .metaLabel,sce-engineering-office-card .metaLabel{font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-md);font-weight:var(--font-weight-medium);color:var(--text-primary-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}sce-engineering-office-card-skeleton .metaValue,sce-engineering-office-card .metaValue{display:flex;align-items:flex-start;gap:var(--space-8);font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);color:var(--text-primary-soft);line-height:1.4;min-width:0}sce-engineering-office-card-skeleton .metaValue>span:not(.ratingCount),sce-engineering-office-card .metaValue>span:not(.ratingCount){display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;overflow-wrap:break-word;flex:1}sce-engineering-office-card-skeleton .ratingCount,sce-engineering-office-card .ratingCount{font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-md);font-weight:var(--font-weight-medium);color:var(--text-primary-faint);flex-shrink:0;margin-inline-start:-.25rem}sce-engineering-office-card-skeleton .metaIcon,sce-engineering-office-card .metaIcon{width:1.35rem;height:1.35rem;flex-shrink:0;margin-block-start:.15rem}@media(max-width:640px){sce-engineering-office-card-skeleton .card,sce-engineering-office-card .card{min-height:var(--size-320);padding:var(--space-16)}sce-engineering-office-card-skeleton .logo,sce-engineering-office-card .logo{width:var(--space-64);height:var(--space-64)}sce-engineering-office-card-skeleton .logoIcon,sce-engineering-office-card .logoIcon{width:1.8rem;height:1.8rem}sce-engineering-office-card-skeleton .name,sce-engineering-office-card .name{font-size:1.6rem}}\n"] }]
|
|
3507
3554
|
}], propDecorators: { office: [{ type: i0.Input, args: [{ isSignal: true, alias: "office", required: true }] }], viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], bookmarkLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "bookmarkLabel", required: false }] }], bookmarked: [{ type: i0.Input, args: [{ isSignal: true, alias: "bookmarked", required: false }] }], ratingLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ratingLabel", required: false }] }], locationLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "locationLabel", required: false }] }], otherLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "otherLabel", required: false }] }], bookmarkClick: [{ type: i0.Output, args: ["bookmarkClick"] }] } });
|
|
3508
3555
|
|
|
3556
|
+
/** Loading placeholder for the engineering office card, mirroring its grid or list layout via `viewMode`. */
|
|
3509
3557
|
class SceEngineeringOfficeCardSkeletonComponent {
|
|
3510
3558
|
viewMode = input('grid', ...(ngDevMode ? [{ debugName: "viewMode" }] : /* istanbul ignore next */ []));
|
|
3511
3559
|
wrapperClass = computed(() => this.viewMode() === 'list' ? 'card cardList cardSkeleton' : 'card cardSkeleton', ...(ngDevMode ? [{ debugName: "wrapperClass" }] : /* istanbul ignore next */ []));
|
|
@@ -3518,6 +3566,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3518
3566
|
args: [{ host: { class: 'sce-engineering-office-card-skeleton' }, selector: 'sce-engineering-office-card-skeleton', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, imports: [SceSkeleton], template: "<article [class]=\"wrapperClass()\" aria-hidden=\"true\">\n <div [class]=\"mediaClass()\">\n <div class=\"mediaSkeleton\">\n <sce-skeleton variant=\"rectangular\" width=\"100%\" height=\"100%\" borderRadius=\"0\" />\n </div>\n <div class=\"logoSkeleton\">\n <sce-skeleton variant=\"circular\" width=\"100%\" height=\"100%\" />\n </div>\n </div>\n <div class=\"body\">\n <sce-skeleton variant=\"header\" width=\"72%\" height=\"1.35rem\" />\n <div class=\"tagsSkeleton\">\n <sce-skeleton variant=\"chip\" width=\"5.5rem\" height=\"1.625rem\" />\n <sce-skeleton variant=\"chip\" width=\"5.5rem\" height=\"1.625rem\" />\n </div>\n <div class=\"metaSkeleton\">\n <sce-skeleton variant=\"text\" width=\"80%\" height=\"1rem\" />\n <sce-skeleton variant=\"text\" width=\"80%\" height=\"1rem\" />\n </div>\n </div>\n</article>\n", styles: ["@charset \"UTF-8\";sce-engineering-office-card-skeleton,sce-engineering-office-card{display:block}sce-engineering-office-card-skeleton .card,sce-engineering-office-card .card{width:100%;min-height:var(--size-320);border-radius:var(--radius-brand-sm);padding:var(--space-18);background:var(--surface-primary);border:1px solid var(--border-subtle);box-shadow:var(--shadow-card-soft-subtle);text-decoration:none;color:inherit;display:grid;gap:var(--space-8)}sce-engineering-office-card-skeleton .cardList,sce-engineering-office-card .cardList{grid-template-columns:180px minmax(0,1fr);grid-template-areas:\"media content\";align-items:center;min-height:auto;direction:rtl}sce-engineering-office-card-skeleton .cardList[dir=ltr],sce-engineering-office-card .cardList[dir=ltr]{direction:ltr}sce-engineering-office-card-skeleton .media,sce-engineering-office-card .media{position:relative;width:100%;max-width:100%;min-width:0;height:10.5rem;border-radius:var(--radius-brand-sm);overflow:hidden;isolation:isolate;background:var(--surface-overlay-soft)}sce-engineering-office-card-skeleton .mediaList,sce-engineering-office-card .mediaList{grid-area:media;position:relative;width:100%;height:100%;border-radius:var(--radius-brand-sm);overflow:hidden;isolation:isolate;background:var(--surface-overlay-soft)}sce-engineering-office-card-skeleton .mediaImg,sce-engineering-office-card .mediaImg{width:100%;height:100%;object-fit:cover;object-position:center;transition:opacity .35s ease}sce-engineering-office-card-skeleton .mediaImgLoading,sce-engineering-office-card .mediaImgLoading{opacity:0}sce-engineering-office-card-skeleton .mediaImgLoaded,sce-engineering-office-card .mediaImgLoaded{opacity:1}sce-engineering-office-card-skeleton .mediaSkeleton,sce-engineering-office-card-skeleton .logoSkeleton,sce-engineering-office-card-skeleton .lineSkeleton,sce-engineering-office-card-skeleton .tagSkeleton,sce-engineering-office-card .mediaSkeleton,sce-engineering-office-card .logoSkeleton,sce-engineering-office-card .lineSkeleton,sce-engineering-office-card .tagSkeleton{position:relative;overflow:hidden;background:var(--surface-overlay-soft)}sce-engineering-office-card-skeleton .mediaSkeleton,sce-engineering-office-card .mediaSkeleton{position:absolute;inset:0;z-index:1}sce-engineering-office-card-skeleton .mediaSkeleton:after,sce-engineering-office-card-skeleton .logoSkeleton:after,sce-engineering-office-card-skeleton .lineSkeleton:after,sce-engineering-office-card-skeleton .tagSkeleton:after,sce-engineering-office-card .mediaSkeleton:after,sce-engineering-office-card .logoSkeleton:after,sce-engineering-office-card .lineSkeleton:after,sce-engineering-office-card .tagSkeleton:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.55) 45%,transparent 100%);animation:office-card-shimmer 1.35s ease-in-out infinite}sce-engineering-office-card-skeleton .logoSkeleton,sce-engineering-office-card .logoSkeleton{position:absolute;bottom:.9rem;inset-inline-start:.9rem;width:65.3198776245px;height:65.3198776245px;border-radius:var(--radius-full);z-index:2}sce-engineering-office-card-skeleton .cardSkeleton,sce-engineering-office-card .cardSkeleton{pointer-events:none}sce-engineering-office-card-skeleton .lineSkeleton[data-size=title],sce-engineering-office-card .lineSkeleton[data-size=title]{width:72%;height:1.35rem;border-radius:var(--space-8)}sce-engineering-office-card-skeleton .lineSkeleton[data-size=meta],sce-engineering-office-card .lineSkeleton[data-size=meta]{width:55%;height:var(--space-16);border-radius:.4rem}sce-engineering-office-card-skeleton .tagsSkeleton,sce-engineering-office-card .tagsSkeleton{display:flex;gap:var(--space-8)}sce-engineering-office-card-skeleton .tagSkeleton,sce-engineering-office-card .tagSkeleton{width:var(--space-88, var(--size-88));height:1.625rem;border-radius:var(--radius-full)}sce-engineering-office-card-skeleton .metaSkeleton,sce-engineering-office-card .metaSkeleton{margin-block-start:.4rem;padding-block-start:var(--space-12);border-block-start:1px dashed var(--border-subtle);display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12)}@keyframes office-card-shimmer{to{transform:translate(100%)}}sce-engineering-office-card-skeleton .bookmark,sce-engineering-office-card .bookmark{position:absolute;top:.9rem;inset-inline-end:.9rem;width:var(--space-44, var(--size-44));height:var(--space-44, var(--size-44));border-radius:var(--radius-sm);border:0;background:var(--surface-overlay-white-alpha-36);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;z-index:2}sce-engineering-office-card-skeleton .bookmarkIcon,sce-engineering-office-card .bookmarkIcon{width:var(--space-20);height:var(--space-20)}sce-engineering-office-card-skeleton .logo,sce-engineering-office-card .logo{position:absolute;bottom:.9rem;inset-inline-start:.9rem;width:65.3198776245px;height:65.3198776245px;border-radius:var(--radius-full);background:var(--surface-primary);border:2px solid var(--border-chip-light);box-shadow:var(--shadow-card-soft-subtle);overflow:hidden;z-index:2}sce-engineering-office-card-skeleton .logoInner,sce-engineering-office-card .logoInner{position:relative;width:100%;height:100%;display:flex;align-items:center;justify-content:center}sce-engineering-office-card-skeleton .logoPhoto,sce-engineering-office-card .logoPhoto{object-fit:cover;object-position:center;transition:opacity .35s ease;height:100%}sce-engineering-office-card-skeleton .logoPhotoLoading,sce-engineering-office-card .logoPhotoLoading{opacity:0}sce-engineering-office-card-skeleton .logoPhotoLoaded,sce-engineering-office-card .logoPhotoLoaded{opacity:1}sce-engineering-office-card-skeleton .logoPlaceholderSkeleton,sce-engineering-office-card .logoPlaceholderSkeleton{position:absolute;inset:0;border-radius:var(--radius-full);overflow:hidden;background:var(--surface-overlay-soft);z-index:1}sce-engineering-office-card-skeleton .logoPlaceholderSkeleton:after,sce-engineering-office-card .logoPlaceholderSkeleton:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.55) 45%,transparent 100%);animation:office-card-shimmer 1.35s ease-in-out infinite}sce-engineering-office-card-skeleton .logoIcon,sce-engineering-office-card .logoIcon{width:58%;height:58%;object-fit:contain;display:block}sce-engineering-office-card-skeleton .body,sce-engineering-office-card .body{padding-block-start:var(--space-12);display:grid;gap:var(--space-8)}sce-engineering-office-card-skeleton .cardList .body,sce-engineering-office-card .cardList .body{grid-area:content;padding-block-start:0}sce-engineering-office-card-skeleton .nameRow,sce-engineering-office-card .nameRow{display:flex;align-items:center;justify-content:flex-start;gap:var(--space-8);margin-block-end:var(--space-6)}sce-engineering-office-card-skeleton .name,sce-engineering-office-card .name{font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-lg);font-weight:var(--font-weight-bold);color:var(--text-primary-emphasis);text-align:start;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}sce-engineering-office-card-skeleton .verifiedIcon,sce-engineering-office-card .verifiedIcon{width:var(--space-20);height:var(--space-20)}sce-engineering-office-card-skeleton .tags,sce-engineering-office-card .tags{display:flex;flex-wrap:nowrap;gap:var(--space-8);justify-content:flex-start;align-items:center;overflow-x:auto;scrollbar-width:none;margin-block-end:var(--space-6)}sce-engineering-office-card-skeleton .tag,sce-engineering-office-card .tag{width:fit-content;height:var(--space-26, var(--size-26));padding:var(--space-4) var(--space-12);border-radius:var(--radius-2xl, var(--radius-2xl));background:var(--color-neutral-100);font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-xs);font-weight:var(--font-weight-medium);color:var(--text-primary-soft);display:inline-flex;align-items:center;white-space:nowrap}sce-engineering-office-card-skeleton .meta,sce-engineering-office-card .meta{margin-block-start:.4rem;padding-block-start:var(--space-12);border-block-start:1px dashed var(--border-subtle);display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12)}sce-engineering-office-card-skeleton .metaItem,sce-engineering-office-card .metaItem{display:grid;gap:.4rem;justify-items:flex-start;text-align:start;min-width:0}sce-engineering-office-card-skeleton .metaLabel,sce-engineering-office-card .metaLabel{font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-md);font-weight:var(--font-weight-medium);color:var(--text-primary-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}sce-engineering-office-card-skeleton .metaValue,sce-engineering-office-card .metaValue{display:flex;align-items:flex-start;gap:var(--space-8);font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);color:var(--text-primary-soft);line-height:1.4;min-width:0}sce-engineering-office-card-skeleton .metaValue>span:not(.ratingCount),sce-engineering-office-card .metaValue>span:not(.ratingCount){display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;overflow-wrap:break-word;flex:1}sce-engineering-office-card-skeleton .ratingCount,sce-engineering-office-card .ratingCount{font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-md);font-weight:var(--font-weight-medium);color:var(--text-primary-faint);flex-shrink:0;margin-inline-start:-.25rem}sce-engineering-office-card-skeleton .metaIcon,sce-engineering-office-card .metaIcon{width:1.35rem;height:1.35rem;flex-shrink:0;margin-block-start:.15rem}@media(max-width:640px){sce-engineering-office-card-skeleton .card,sce-engineering-office-card .card{min-height:var(--size-320);padding:var(--space-16)}sce-engineering-office-card-skeleton .logo,sce-engineering-office-card .logo{width:var(--space-64);height:var(--space-64)}sce-engineering-office-card-skeleton .logoIcon,sce-engineering-office-card .logoIcon{width:1.8rem;height:1.8rem}sce-engineering-office-card-skeleton .name,sce-engineering-office-card .name{font-size:1.6rem}}\n"] }]
|
|
3519
3567
|
}], propDecorators: { viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }] } });
|
|
3520
3568
|
|
|
3569
|
+
/** Single office metric tile rendering a title, subtitle and optional icon in an accent or soft variant. */
|
|
3521
3570
|
class SceOfficeMetricCardComponent {
|
|
3522
3571
|
item = input.required(...(ngDevMode ? [{ debugName: "item" }] : /* istanbul ignore next */ []));
|
|
3523
3572
|
variant = input('accent', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
@@ -3528,6 +3577,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3528
3577
|
type: Component,
|
|
3529
3578
|
args: [{ host: { class: 'sce-office-metric-card' }, selector: 'sce-office-metric-card', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<article class=\"metricCard\">\n <div class=\"metricIconWrap\" [class.metricIconAccent]=\"variant() === 'accent'\" [class.metricIconSoft]=\"variant() === 'soft'\">\n @if (item().icon) {\n <img [src]=\"item().icon\" width=\"28\" height=\"28\" alt=\"\" aria-hidden=\"true\" class=\"metricIconImg\" />\n }\n </div>\n <div class=\"metricBody\">\n <p class=\"metricTitle\">{{ item().title }}</p>\n <p class=\"metricSubtitle\">{{ item().subtitle }}</p>\n </div>\n</article>\n", styles: ["sce-office-metric-card{display:block;min-width:0;flex:1}.metricCard{display:flex;min-width:0;flex:1;align-items:center;gap:var(--space-12);border-radius:var(--space-12);border:1px solid var(--pagination-surface-hover, var(--color-neutral-200));background:var(--public-surface, var(--background-bg-primary));padding:var(--space-16)}.metricIconWrap{display:flex;height:53.58px;width:53.58px;flex-shrink:0;align-items:center;justify-content:center;border-radius:15.31px}.metricIconAccent{background:var(--surface-accent-brand)}.metricIconAccent .metricIconImg{filter:brightness(0) invert(1)}.metricIconSoft{background:var(--color-info-100)}.metricBody{display:flex;min-width:0;flex:1;flex-direction:column;gap:var(--space-4);text-align:start}.metricTitle{font-size:var(--font-size-lg);font-weight:600;color:var(--text-text-secondary-700);margin:0}.metricSubtitle{font-size:var(--font-size-lg);font-weight:400;color:var(--text-text-primary-900);margin:0}.metricCardsRow{display:grid;width:100%;gap:var(--space-16);grid-template-columns:repeat(2,1fr)}.metricCardsRow3{grid-template-columns:repeat(3,1fr)}@media(max-width:640px){.metricCardsRow,.metricCardsRow3{grid-template-columns:1fr}}\n"] }]
|
|
3530
3579
|
}], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }] } });
|
|
3580
|
+
/** Row of office metric tiles laid out in two or three columns, sharing one variant across all items. */
|
|
3531
3581
|
class SceOfficeMetricCardsRowComponent {
|
|
3532
3582
|
items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
3533
3583
|
variant = input('accent', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
@@ -3540,6 +3590,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3540
3590
|
args: [{ host: { class: 'sce-office-metric-cards-row' }, selector: 'sce-office-metric-cards-row', standalone: true, imports: [SceOfficeMetricCardComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"metricCardsRow\" [class.metricCardsRow3]=\"columns() === 3\">\n @for (item of items(); track item.subtitle) {\n <sce-office-metric-card [item]=\"item\" [variant]=\"variant()\" />\n }\n</div>\n", styles: ["sce-office-metric-card{display:block;min-width:0;flex:1}.metricCard{display:flex;min-width:0;flex:1;align-items:center;gap:var(--space-12);border-radius:var(--space-12);border:1px solid var(--pagination-surface-hover, var(--color-neutral-200));background:var(--public-surface, var(--background-bg-primary));padding:var(--space-16)}.metricIconWrap{display:flex;height:53.58px;width:53.58px;flex-shrink:0;align-items:center;justify-content:center;border-radius:15.31px}.metricIconAccent{background:var(--surface-accent-brand)}.metricIconAccent .metricIconImg{filter:brightness(0) invert(1)}.metricIconSoft{background:var(--color-info-100)}.metricBody{display:flex;min-width:0;flex:1;flex-direction:column;gap:var(--space-4);text-align:start}.metricTitle{font-size:var(--font-size-lg);font-weight:600;color:var(--text-text-secondary-700);margin:0}.metricSubtitle{font-size:var(--font-size-lg);font-weight:400;color:var(--text-text-primary-900);margin:0}.metricCardsRow{display:grid;width:100%;gap:var(--space-16);grid-template-columns:repeat(2,1fr)}.metricCardsRow3{grid-template-columns:repeat(3,1fr)}@media(max-width:640px){.metricCardsRow,.metricCardsRow3{grid-template-columns:1fr}}\n"] }]
|
|
3541
3591
|
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }] } });
|
|
3542
3592
|
|
|
3593
|
+
/** Loading placeholder matching `sce-info-fields-grid`: `count` info-field cards (default 6) with an optional section-title bar. */
|
|
3543
3594
|
class SceInfoFieldsSkeletonComponent {
|
|
3544
3595
|
/** Number of info-field cards to render */
|
|
3545
3596
|
count = input(6, ...(ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []));
|
|
@@ -3556,6 +3607,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3556
3607
|
args: [{ host: { class: 'sce-info-fields-skeleton' }, selector: 'sce-info-fields-skeleton', standalone: true, imports: [SceSkeleton], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-info-fields-skeleton\" [class.sce-info-fields-skeleton--gap-md]=\"gap() === 'md'\" role=\"status\" aria-busy=\"true\">\n @if (showSectionTitle()) {\n <sce-skeleton variant=\"header\" width=\"12rem\" height=\"1.25rem\" animation=\"wave\" />\n }\n\n <div class=\"sce-info-fields-skeleton__grid\">\n @for (i of slots(); track i) {\n <div class=\"sce-info-fields-skeleton__card\">\n <sce-skeleton variant=\"text\" width=\"42%\" height=\"0.75rem\" animation=\"wave\" />\n <sce-skeleton variant=\"text\" width=\"72%\" height=\"1rem\" animation=\"wave\" />\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%}.sce-info-fields-skeleton{display:grid;gap:var(--space-12);width:100%}.sce-info-fields-skeleton--gap-md{gap:var(--space-20)}.sce-info-fields-skeleton__grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12);width:100%}.sce-info-fields-skeleton--gap-md .sce-info-fields-skeleton__grid{gap:var(--space-20)}.sce-info-fields-skeleton__card{display:flex;flex-direction:column;gap:var(--space-8);min-height:var(--space-72);padding:var(--space-16);border-radius:var(--radius-lg);background:var(--app-surface-hover);box-sizing:border-box}@media(max-width:640px){.sce-info-fields-skeleton__grid{grid-template-columns:1fr}}\n"] }]
|
|
3557
3608
|
}], propDecorators: { count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], gap: [{ type: i0.Input, args: [{ isSignal: true, alias: "gap", required: false }] }], showSectionTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSectionTitle", required: false }] }] } });
|
|
3558
3609
|
|
|
3610
|
+
/** Loading placeholder for a form: `count` label-plus-input pairs (default 6) laid out in one or two `columns`. */
|
|
3559
3611
|
class SceFormFieldsSkeletonComponent {
|
|
3560
3612
|
count = input(6, ...(ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []));
|
|
3561
3613
|
columns = input(2, ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
|
|
@@ -3568,6 +3620,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3568
3620
|
args: [{ host: { class: 'sce-form-fields-skeleton' }, selector: 'sce-form-fields-skeleton', standalone: true, imports: [SceSkeleton], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-form-fields-skeleton\" [class.sce-form-fields-skeleton--cols-1]=\"columns() === 1\" role=\"status\" aria-busy=\"true\">\n @for (i of slots(); track i) {\n <sce-skeleton variant=\"input\" animation=\"wave\" />\n }\n</div>\n", styles: [":host{display:block;width:100%}.sce-form-fields-skeleton{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-16);width:100%}.sce-form-fields-skeleton--cols-1{grid-template-columns:1fr}@media(max-width:768px){.sce-form-fields-skeleton{grid-template-columns:1fr}}\n"] }]
|
|
3569
3621
|
}], propDecorators: { count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }] } });
|
|
3570
3622
|
|
|
3623
|
+
/** Loading placeholder for a notification list: `count` rows (default 5), with `compact` tightening the padding for dropdown menus. */
|
|
3571
3624
|
class SceNotificationListSkeletonComponent {
|
|
3572
3625
|
count = input(5, ...(ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []));
|
|
3573
3626
|
/** Compact padding for dropdown menus */
|
|
@@ -3581,6 +3634,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3581
3634
|
args: [{ host: { class: 'sce-notification-list-skeleton' }, selector: 'sce-notification-list-skeleton', standalone: true, imports: [SceSkeleton], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-notification-list-skeleton\" [class.sce-notification-list-skeleton--compact]=\"compact()\" role=\"status\" aria-busy=\"true\">\n @for (i of slots(); track i) {\n <article class=\"sce-notification-list-skeleton__item\">\n <div class=\"sce-notification-list-skeleton__top\">\n <div class=\"sce-notification-list-skeleton__meta\">\n <sce-skeleton variant=\"circular\" width=\"0.5rem\" height=\"0.5rem\" animation=\"wave\" />\n <sce-skeleton variant=\"text\" width=\"7rem\" height=\"0.875rem\" animation=\"wave\" />\n <sce-skeleton variant=\"chip\" width=\"4.5rem\" height=\"1.25rem\" animation=\"wave\" />\n </div>\n <sce-skeleton variant=\"text\" width=\"5rem\" height=\"0.75rem\" animation=\"wave\" />\n </div>\n <sce-skeleton variant=\"text\" width=\"100%\" height=\"0.875rem\" animation=\"wave\" />\n <sce-skeleton variant=\"text\" width=\"88%\" height=\"0.875rem\" animation=\"wave\" />\n </article>\n }\n</div>\n", styles: [":host{display:block;width:100%}.sce-notification-list-skeleton{display:grid;gap:var(--space-12);width:100%}.sce-notification-list-skeleton--compact{gap:var(--space-8)}.sce-notification-list-skeleton__item{display:grid;gap:var(--space-8);padding:var(--space-16);border:1px solid var(--color-neutral-200);border-radius:var(--radius-lg);background:var(--surface-primary);box-sizing:border-box;min-height:var(--space-96)}.sce-notification-list-skeleton--compact .sce-notification-list-skeleton__item{padding:var(--space-12);min-height:var(--space-72)}.sce-notification-list-skeleton__top{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-12)}.sce-notification-list-skeleton__meta{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-8);min-width:0;flex:1}\n"] }]
|
|
3582
3635
|
}], propDecorators: { count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }] } });
|
|
3583
3636
|
|
|
3637
|
+
/** Loading placeholder for a profile page: a hero banner of `heroHeight` (default `230px`) above `fieldCount` info-field placeholders. */
|
|
3584
3638
|
class SceProfileHeroSkeletonComponent {
|
|
3585
3639
|
heroHeight = input('230px', ...(ngDevMode ? [{ debugName: "heroHeight" }] : /* istanbul ignore next */ []));
|
|
3586
3640
|
fieldCount = input(4, ...(ngDevMode ? [{ debugName: "fieldCount" }] : /* istanbul ignore next */ []));
|
|
@@ -3592,6 +3646,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3592
3646
|
args: [{ host: { class: 'sce-profile-hero-skeleton' }, selector: 'sce-profile-hero-skeleton', standalone: true, imports: [SceSkeleton, SceInfoFieldsSkeletonComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<section class=\"sce-profile-hero-skeleton\" role=\"status\" aria-busy=\"true\">\n <sce-skeleton variant=\"rectangular\" [height]=\"heroHeight()\" animation=\"wave\" borderRadius=\"0\" aria-hidden=\"true\" />\n <div class=\"sce-profile-hero-skeleton__body\">\n <sce-skeleton variant=\"header\" animation=\"wave\" width=\"45%\" />\n <sce-skeleton variant=\"text\" animation=\"wave\" width=\"30%\" />\n <sce-info-fields-skeleton [count]=\"fieldCount()\" />\n </div>\n</section>\n", styles: [":host{display:block;width:100%}.sce-profile-hero-skeleton{display:grid;gap:var(--space-16);width:100%}.sce-profile-hero-skeleton__body{display:grid;gap:var(--space-12);padding-inline:var(--space-24);padding-block-end:var(--space-24)}\n"] }]
|
|
3593
3647
|
}], propDecorators: { heroHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "heroHeight", required: false }] }], fieldCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "fieldCount", required: false }] }] } });
|
|
3594
3648
|
|
|
3649
|
+
/** Loading placeholder for a data table (`columns` x `rows`, default 5x5), cycling a fixed set of column widths and treating the last column as a status pill; `wrapInCard` defaults to true. */
|
|
3595
3650
|
class SceTableSkeletonComponent {
|
|
3596
3651
|
columns = input(5, ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
|
|
3597
3652
|
rows = input(5, ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
|
|
@@ -3659,6 +3714,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3659
3714
|
args: [{ host: { class: 'sce-featured-office-card-skeleton' }, selector: 'sce-featured-office-card-skeleton', standalone: true, imports: [SceSkeleton], changeDetection: ChangeDetectionStrategy.OnPush, template: "<article class=\"sce-featured-office-card-skeleton\" role=\"status\" aria-busy=\"true\">\n <div class=\"sce-featured-office-card-skeleton__lead\">\n <sce-skeleton variant=\"rounded\" width=\"4rem\" height=\"4rem\" borderRadius=\"var(--radius-lg)\" animation=\"wave\" />\n <div class=\"sce-featured-office-card-skeleton__meta\">\n <sce-skeleton variant=\"header\" width=\"12rem\" height=\"1rem\" animation=\"wave\" />\n <sce-skeleton variant=\"text\" width=\"16rem\" height=\"0.875rem\" animation=\"wave\" />\n </div>\n </div>\n <div class=\"sce-featured-office-card-skeleton__tags\">\n <sce-skeleton variant=\"chip\" width=\"4.5rem\" height=\"1.5rem\" animation=\"wave\" />\n <sce-skeleton variant=\"chip\" width=\"5rem\" height=\"1.5rem\" animation=\"wave\" />\n <sce-skeleton variant=\"chip\" width=\"4rem\" height=\"1.5rem\" animation=\"wave\" />\n </div>\n <sce-skeleton variant=\"button\" width=\"6.5rem\" height=\"2rem\" borderRadius=\"999px\" animation=\"wave\" />\n</article>\n", styles: [":host{display:block;width:100%}.sce-featured-office-card-skeleton{display:flex;align-items:center;justify-content:space-between;gap:var(--space-24);background:var(--surface-primary);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:var(--space-16) var(--space-24);box-sizing:border-box;pointer-events:none;min-width:0}.sce-featured-office-card-skeleton__lead{display:flex;align-items:center;gap:var(--space-16);flex:1;min-width:0}.sce-featured-office-card-skeleton__meta{display:flex;flex-direction:column;gap:var(--space-24);min-width:0;flex:1}.sce-featured-office-card-skeleton__tags{display:flex;flex-wrap:wrap;gap:var(--space-8);justify-content:center}@media(max-width:768px){.sce-featured-office-card-skeleton{flex-direction:column;align-items:stretch}.sce-featured-office-card-skeleton__tags{justify-content:flex-start}}\n"] }]
|
|
3660
3715
|
}] });
|
|
3661
3716
|
|
|
3717
|
+
/** Fixed loading placeholder for the service-detail page; takes no inputs. */
|
|
3662
3718
|
class SceServiceDetailSkeletonComponent {
|
|
3663
3719
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SceServiceDetailSkeletonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3664
3720
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SceServiceDetailSkeletonComponent, isStandalone: true, selector: "sce-service-detail-skeleton", host: { classAttribute: "sce-service-detail-skeleton" }, ngImport: i0, template: "<div class=\"sce-service-detail-skeleton\" role=\"status\" aria-busy=\"true\">\n <div class=\"sce-service-detail-skeleton__main\">\n <sce-skeleton variant=\"header\" animation=\"wave\" width=\"50%\" />\n <sce-skeleton variant=\"paragraph\" animation=\"wave\" [count]=\"4\" />\n </div>\n <div class=\"sce-service-detail-skeleton__sidebar\">\n <sce-skeleton variant=\"header\" animation=\"wave\" width=\"60%\" />\n @for (i of [1, 2, 3, 4, 5]; track i) {\n <sce-skeleton variant=\"text\" animation=\"wave\" />\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%}.sce-service-detail-skeleton{display:grid;grid-template-columns:minmax(0,1fr) minmax(280px,360px);gap:var(--space-24);width:100%}.sce-service-detail-skeleton__main,.sce-service-detail-skeleton__sidebar{display:grid;gap:var(--space-16);background:var(--surface-primary);border:1px solid var(--color-primary-100);border-radius:var(--radius-lg);padding:var(--space-24);box-sizing:border-box}@media(max-width:992px){.sce-service-detail-skeleton{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "component", type: SceSkeleton, selector: "sce-skeleton", inputs: ["variant", "animation", "width", "height", "borderRadius", "count", "gap", "shrinkLastLine", "aspectRatio"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
@@ -3668,6 +3724,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3668
3724
|
args: [{ host: { class: 'sce-service-detail-skeleton' }, selector: 'sce-service-detail-skeleton', standalone: true, imports: [SceSkeleton], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-service-detail-skeleton\" role=\"status\" aria-busy=\"true\">\n <div class=\"sce-service-detail-skeleton__main\">\n <sce-skeleton variant=\"header\" animation=\"wave\" width=\"50%\" />\n <sce-skeleton variant=\"paragraph\" animation=\"wave\" [count]=\"4\" />\n </div>\n <div class=\"sce-service-detail-skeleton__sidebar\">\n <sce-skeleton variant=\"header\" animation=\"wave\" width=\"60%\" />\n @for (i of [1, 2, 3, 4, 5]; track i) {\n <sce-skeleton variant=\"text\" animation=\"wave\" />\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%}.sce-service-detail-skeleton{display:grid;grid-template-columns:minmax(0,1fr) minmax(280px,360px);gap:var(--space-24);width:100%}.sce-service-detail-skeleton__main,.sce-service-detail-skeleton__sidebar{display:grid;gap:var(--space-16);background:var(--surface-primary);border:1px solid var(--color-primary-100);border-radius:var(--radius-lg);padding:var(--space-24);box-sizing:border-box}@media(max-width:992px){.sce-service-detail-skeleton{grid-template-columns:1fr}}\n"] }]
|
|
3669
3725
|
}] });
|
|
3670
3726
|
|
|
3727
|
+
/** Loading placeholder for the office-details panel — `count` repeated blocks (minimum 1); uses `ViewEncapsulation.None` and shares its styles with the office-projects skeleton. */
|
|
3671
3728
|
class SceOfficeDetailsSkeletonComponent {
|
|
3672
3729
|
count = input(2, ...(ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []));
|
|
3673
3730
|
countArray = computed(() => Array.from({ length: Math.max(1, this.count()) }, (_, i) => i), ...(ngDevMode ? [{ debugName: "countArray" }] : /* istanbul ignore next */ []));
|
|
@@ -3678,6 +3735,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3678
3735
|
type: Component,
|
|
3679
3736
|
args: [{ host: { class: 'sce-office-details-skeleton' }, selector: 'sce-office-details-skeleton', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"projectsSkeletonStack\">\n @for (i of countArray(); track i) {\n <div class=\"panelSkeleton shimmerPanel projectPanelSkeleton\">\n <div class=\"shimmerBlock panelTitleSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n <div class=\"shimmerBlock projectHeroSkeleton\"></div>\n <div class=\"projectThumbsSkeletonRow\">\n <div class=\"shimmerBlock projectThumbSkeleton\"></div>\n <div class=\"shimmerBlock projectThumbSkeleton\"></div>\n <div class=\"shimmerBlock projectThumbSkeleton\"></div>\n </div>\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";sce-office-details-skeleton,sce-office-projects-skeleton{display:block}\n", "@charset \"UTF-8\";.shimmerBlock,.shimmerPanel{position:relative;overflow:hidden;background:#ffffff2e;border-radius:var(--space-8)}.shimmerPanel{background:var(--public-surface, var(--background-bg-primary));border-radius:var(--space-16);padding:var(--space-16) var(--space-20)}.shimmerBlock:after,.shimmerPanel:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.42) 45%,transparent 100%);animation:office-detail-shimmer 1.35s ease-in-out infinite}.shimmerPanel:after{background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.65) 45%,transparent 100%)}@keyframes office-detail-shimmer{to{transform:translate(100%)}}.contentSkeletonLayout{display:flex;width:100%;max-width:var(--size-1220);flex-direction:column;gap:var(--space-24);padding-inline:var(--space-16)}.contentSkeletonColumn{display:flex;flex:1;flex-direction:column;gap:var(--space-24)}.panelSkeleton{display:grid;gap:var(--space-12)}.panelTitleSkeleton{width:8rem;height:1.35rem}.panelLineSkeleton{width:100%;height:var(--space-16)}.panelLineSkeleton:last-child{width:82%}.metricSkeletonRow{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-16);margin-block-start:var(--space-8)}.metricSkeleton{height:var(--space-88, var(--size-88));border-radius:var(--space-16)}.mapPanelSkeleton{min-height:var(--size-280)}.mapSkeleton{width:100%;height:var(--size-220);border-radius:var(--space-16);margin-block-start:var(--space-8)}.projectsSkeletonStack{flex-direction:column;gap:var(--space-24)}.projectPanelSkeleton{width:100%}.projectHeroSkeleton{width:100%;height:var(--size-220);border-radius:var(--space-16);margin-block-start:var(--space-8)}.projectThumbsSkeletonRow{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-16);margin-block-start:var(--space-16)}.projectThumbSkeleton{width:100%;aspect-ratio:379/213;border-radius:var(--space-16)}@media(min-width:1024px){.contentSkeletonLayout{flex-direction:row;align-items:flex-start;padding-inline:0}.mapPanelSkeleton{width:min(596.5px,42%);flex-shrink:0}}\n"] }]
|
|
3680
3737
|
}], propDecorators: { count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }] } });
|
|
3738
|
+
/** Office-projects loading placeholder; reuses the office-details skeleton template but carries no styles of its own, so it inherits them from an office-details skeleton rendered elsewhere on the page (`ViewEncapsulation.None`). */
|
|
3681
3739
|
class SceOfficeProjectsSkeletonComponent {
|
|
3682
3740
|
count = input(2, ...(ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []));
|
|
3683
3741
|
countArray = computed(() => Array.from({ length: Math.max(1, this.count()) }, (_, i) => i), ...(ngDevMode ? [{ debugName: "countArray" }] : /* istanbul ignore next */ []));
|
|
@@ -3912,6 +3970,7 @@ var osmOfficesMap_component = /*#__PURE__*/Object.freeze({
|
|
|
3912
3970
|
SceOsmOfficesMapComponent: SceOsmOfficesMapComponent
|
|
3913
3971
|
});
|
|
3914
3972
|
|
|
3973
|
+
/** Renders the small leading `<img>` icon inside a filter control, sized 20x20 by default and omitted entirely when `iconSrc` is unset. */
|
|
3915
3974
|
class SceFilterFieldIconComponent {
|
|
3916
3975
|
iconSrc = input(...(ngDevMode ? [undefined, { debugName: "iconSrc" }] : /* istanbul ignore next */ []));
|
|
3917
3976
|
iconAlt = input('', ...(ngDevMode ? [{ debugName: "iconAlt" }] : /* istanbul ignore next */ []));
|
|
@@ -3926,6 +3985,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3926
3985
|
args: [{ host: { class: 'sce-filter-field-icon' }, selector: 'sce-filter-field-icon', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (iconSrc()) {\n <img [src]=\"iconSrc()\" [alt]=\"iconAlt()\" [width]=\"width()\" [height]=\"height()\" [class]=\"className()\" />\n}\n", styles: [":host{display:block}.sce-filter-field-icon{display:contents}\n"] }]
|
|
3927
3986
|
}], propDecorators: { iconSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconSrc", required: false }] }], iconAlt: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconAlt", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }] } });
|
|
3928
3987
|
|
|
3988
|
+
/** Filter-bar select built on PrimeNG `Select` with an optional leading icon, clear button, and type-ahead `filter`; controlled when `value` is bound and self-managing when it is left `undefined`, and uses `ViewEncapsulation.None`. */
|
|
3929
3989
|
class SceFilterDropdownComponent {
|
|
3930
3990
|
id = input('', ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
3931
3991
|
locale = input('ar', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
|
|
@@ -3960,6 +4020,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3960
4020
|
args: [{ host: { class: 'sce-filter-dropdown' }, selector: 'sce-filter-dropdown', standalone: true, imports: [Select, FormsModule, SceFilterFieldIconComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"rootClass()\" [attr.data-locale]=\"locale()\" [dir]=\"dir()\">\n <sce-filter-field-icon [iconSrc]=\"iconSrc()\" [iconAlt]=\"iconAlt()\" [width]=\"20\" [height]=\"20\" className=\"icon\" />\n <p-select\n [showClear]=\"showClear()\"\n [inputId]=\"id()\"\n [ngModel]=\"currentValue()\"\n (ngModelChange)=\"onSelectionChange({ value: $event })\"\n [options]=\"options()\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"placeholder()\"\n styleClass=\"dropdown\"\n [filter]=\"filter()\"\n appendTo=\"body\"\n />\n</div>\n", styles: ["@charset \"UTF-8\";.root{position:relative;width:100%}.icon{position:absolute;top:50%;transform:translateY(-50%);inset-inline-start:var(--space-12);z-index:2;pointer-events:none}.dropdown{width:100%;height:auto;border-radius:var(--radius-xl);border:1px solid var(--color-neutral-300);display:flex;align-items:center}.dropdown .p-select-label{display:flex;align-items:center;align-self:stretch;flex:1 1 auto;min-width:0;margin:0;padding-block:0;padding-inline-start:var(--space-40);padding-inline-end:var(--space-8);font-family:var(--font-family-arabic-primary);font-weight:500;font-size:var(--font-size-xs);line-height:normal;text-align:start}.dropdown .p-select-label.p-inputtext{height:auto;min-height:100%;border:0;background:transparent;box-shadow:none}.dropdown .p-select-label.p-placeholder{color:var(--color-neutral-500);font-weight:500}.dropdown .p-select-label:not(.p-placeholder){color:var(--text-text-primary-900)}.dropdown .p-select-clear-icon{position:static;inset:unset;inset-inline-start:unset;inset-inline-end:unset;margin:0;flex-shrink:0;align-self:center;color:var(--color-neutral-500);font-weight:500}.dropdown .p-select-dropdown{display:flex;align-items:center;justify-content:center;align-self:stretch;width:var(--space-40);flex-shrink:0;color:var(--color-neutral-500);font-weight:500}.root[dir=rtl] .icon{inset-inline-end:auto;inset-inline-start:var(--space-12)}\n"] }]
|
|
3961
4021
|
}], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], iconSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconSrc", required: false }] }], iconAlt: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconAlt", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
|
|
3962
4022
|
|
|
4023
|
+
/** Filter-bar single-date picker with a leading icon and a clear button; controlled when `value` is bound and self-managing when it is left `undefined`, and uses `ViewEncapsulation.None`. */
|
|
3963
4024
|
class SceFilterCalendarComponent {
|
|
3964
4025
|
locale = input('ar', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
|
|
3965
4026
|
placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
@@ -3999,6 +4060,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
3999
4060
|
}], propDecorators: { locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], iconSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconSrc", required: false }] }], iconAlt: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconAlt", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
|
|
4000
4061
|
|
|
4001
4062
|
const EMPTY_RANGE = { from: null, to: null };
|
|
4063
|
+
/** Filter-bar date-range picker with a leading icon and a clear button; works controlled when `value` is bound and falls back to its own internal state when it is left `undefined`, and uses `ViewEncapsulation.None`. */
|
|
4002
4064
|
class SceFilterCalendarRangeComponent {
|
|
4003
4065
|
locale = input('ar', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
|
|
4004
4066
|
placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
@@ -4088,6 +4150,7 @@ function clearField(field) {
|
|
|
4088
4150
|
break;
|
|
4089
4151
|
}
|
|
4090
4152
|
}
|
|
4153
|
+
/** Renders a dashboard table's filter row from a declarative `fields` array and exposes `hasActiveSearch`/`hasActiveFilters` plus `clearSearch()`/`clearFilters()` for a page to drive via a template reference; uses `ViewEncapsulation.None`. */
|
|
4091
4154
|
class SceDashboardTableFiltersComponent {
|
|
4092
4155
|
locale = input('ar', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
|
|
4093
4156
|
idPrefix = input('', ...(ngDevMode ? [{ debugName: "idPrefix" }] : /* istanbul ignore next */ []));
|
|
@@ -4140,6 +4203,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
4140
4203
|
], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"filters\" [dir]=\"dir()\" [attr.data-locale]=\"locale()\">\n @for (field of fields(); track field.id) {\n @switch (field.kind) {\n @case ('search') {\n <div class=\"field\">\n <input class=\"input\" [placeholder]=\"field.placeholder\" [value]=\"field.value\" (input)=\"onSearchInput($any(field), $event)\" />\n @if (field.iconSrc) {\n <sce-filter-field-icon\n [iconSrc]=\"field.iconSrc\"\n [iconAlt]=\"field.iconAlt ?? ''\"\n [width]=\"20\"\n [height]=\"20\"\n className=\"trailingImageIcon\"\n />\n } @else {\n <i class=\"pi pi-search trailingIcon\" aria-hidden=\"true\"></i>\n }\n </div>\n }\n @case ('text') {\n <div class=\"field\">\n <input\n class=\"input\"\n [placeholder]=\"field.placeholder\"\n [value]=\"field.value\"\n [attr.maxlength]=\"field.maxLength ?? null\"\n [attr.inputmode]=\"field.inputMode ?? null\"\n (input)=\"onTextInput($any(field), $event)\"\n />\n <sce-filter-field-icon\n [iconSrc]=\"field.iconSrc\"\n [iconAlt]=\"field.iconAlt ?? ''\"\n [width]=\"20\"\n [height]=\"20\"\n className=\"trailingImageIcon\"\n />\n </div>\n }\n @case ('select') {\n <div class=\"field\">\n <sce-filter-dropdown\n [id]=\"idPrefix() + '-' + field.id\"\n [locale]=\"locale()\"\n className=\"control\"\n [iconSrc]=\"field.iconSrc\"\n [iconAlt]=\"field.iconAlt ?? ''\"\n [options]=\"field.options\"\n [placeholder]=\"field.placeholder\"\n [value]=\"field.value\"\n [showClear]=\"field.showClear ?? false\"\n [filter]=\"field.filter ?? false\"\n (valueChange)=\"field.onChange($event)\"\n />\n </div>\n }\n @case ('date') {\n <div class=\"field\">\n <sce-filter-calendar\n [locale]=\"locale()\"\n className=\"control\"\n [iconSrc]=\"field.iconSrc\"\n [iconAlt]=\"field.iconAlt ?? ''\"\n [placeholder]=\"field.placeholder\"\n [id]=\"idPrefix() + '-' + field.id\"\n [value]=\"field.value\"\n (valueChange)=\"field.onChange($event)\"\n />\n </div>\n }\n @case ('dateRange') {\n <div class=\"field\">\n <sce-filter-calendar-range\n [locale]=\"locale()\"\n className=\"control\"\n [iconSrc]=\"field.iconSrc\"\n [iconAlt]=\"field.iconAlt ?? ''\"\n [placeholder]=\"field.placeholder\"\n [id]=\"idPrefix() + '-' + field.id\"\n [value]=\"field.value\"\n (valueChange)=\"field.onChange($event)\"\n />\n </div>\n }\n }\n }\n</div>\n", styles: ["@charset \"UTF-8\";.filters{display:grid;grid-template-columns:minmax(0,2fr) repeat(3,minmax(0,1fr));gap:var(--space-12);margin-block-end:var(--space-16)}.field{position:relative}.trailingIcon{position:absolute;inset-inline-start:var(--space-12);top:50%;transform:translateY(-50%);z-index:2;color:var(--color-neutral-500);pointer-events:none;font-weight:500;font-size:var(--font-size-xs)}.trailingImageIcon{position:absolute;inset-inline-start:var(--space-12);top:50%;transform:translateY(-50%);z-index:2;pointer-events:none}.input{width:100%;height:var(--space-48);border-radius:var(--radius-xl);border:1px solid var(--color-neutral-300);padding-block:0;padding-inline-start:var(--space-40);padding-inline-end:var(--space-14);font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-medium);font-size:var(--font-size-xs);line-height:var(--space-48);color:var(--text-text-primary-900);text-align:start}.input::placeholder{color:var(--color-neutral-500);font-family:inherit;font-weight:500;font-size:var(--font-size-xs);opacity:1}.control{width:100%}.field .p-dropdown{display:flex;align-items:center;height:var(--space-48)}.field .p-dropdown-label{display:flex;align-items:center;align-self:stretch;flex:1 1 auto;min-width:0;margin:0;padding-block:0;font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-medium);font-size:var(--font-size-xs);line-height:normal;text-align:start}.field .p-dropdown-label.p-inputtext{height:auto;min-height:100%;border:0;background:transparent;box-shadow:none}.field .p-dropdown-label.p-placeholder{color:var(--color-neutral-500);font-weight:500}.field .p-dropdown-label:not(.p-placeholder){color:var(--text-text-primary-900)}.field .p-dropdown-clear-icon{position:static;inset:unset;inset-inline-start:unset;inset-inline-end:unset;margin:0;flex-shrink:0;align-self:center}.field .p-dropdown-trigger{display:flex;align-items:center;justify-content:center;align-self:stretch;flex-shrink:0}.field .p-inputtext:not(.p-dropdown-label){margin:0;padding-block:0;font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-medium);font-size:var(--font-size-xs);line-height:var(--space-48);color:var(--text-text-primary-900)}.field .p-inputtext:not(.p-dropdown-label)::placeholder{color:var(--color-neutral-500);font-family:inherit;font-weight:500;font-size:inherit;opacity:1}.filters[data-locale=ar] .input{padding-inline-start:var(--space-40);padding-inline-end:var(--space-12)}@media(max-width:1200px){.filters{grid-template-columns:repeat(1,minmax(0,1fr))}}@media(max-width:768px){.filters{grid-template-columns:1fr}}\n"] }]
|
|
4141
4204
|
}], propDecorators: { locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], idPrefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "idPrefix", required: false }] }], fields: [{ type: i0.Input, args: [{ isSignal: true, alias: "fields", required: false }] }] } });
|
|
4142
4205
|
|
|
4206
|
+
/** Filter bar for the public services and offices listings, rendering a search box plus category, target, extra and sort dropdowns and emitting the resolved filter state via `filtersChange`. */
|
|
4143
4207
|
class SceServicesTopFiltersComponent {
|
|
4144
4208
|
language = inject(LanguageService);
|
|
4145
4209
|
translate = inject(TranslateService);
|
|
@@ -4304,6 +4368,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
4304
4368
|
args: [{ host: { class: 'sce-services-top-filters' }, selector: 'sce-services-top-filters', standalone: true, imports: [NgTemplateOutlet, FormsModule, TranslatePipe, Select, InputText, Button], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--\n The three dropdown columns are identical apart from their label, icon, options, selected value\n and change handler, so they share one template rendered three times. ng-container adds no\n element, so each column stays a direct child of .services-top-filters-row.\n-->\n<ng-template #filterColumn let-field=\"field\" let-labelKey=\"labelKey\" let-icon=\"icon\" let-options=\"options\" let-selected=\"selected\">\n <div class=\"services-top-filter-col\">\n <p class=\"services-top-filter-label\">{{ labelKey | translate }}</p>\n <div class=\"sce-services-top-filters__control\">\n <img [src]=\"icon\" class=\"services-filter-value-icon\" alt=\"\" aria-hidden=\"true\" />\n <p-select\n [options]=\"options\"\n optionLabel=\"label\"\n dataKey=\"value\"\n [ngModel]=\"selected\"\n (ngModelChange)=\"onFilterChange(field, $event)\"\n [filter]=\"true\"\n [filterPlaceholder]=\"filterPlaceholderKey() | translate\"\n [emptyFilterMessage]=\"emptyFilterMessageKey() | translate\"\n styleClass=\"services-filter-dropdown\"\n panelStyleClass=\"services-filter-dropdown-panel\"\n [attr.dir]=\"dir()\"\n appendTo=\"body\"\n >\n <ng-template #selectedItem let-option>\n @if (option) {\n <span class=\"services-filter-value-item\">\n <span class=\"services-filter-value-text\">{{ option.label }}</span>\n </span>\n }\n </ng-template>\n <ng-template #item let-option>\n <div class=\"services-filter-option-item\">\n <span class=\"services-filter-option-icon-wrap\">\n <img [src]=\"option.icon\" class=\"services-filter-option-icon\" alt=\"\" aria-hidden=\"true\" />\n </span>\n <div class=\"services-filter-option-text\">\n <span class=\"services-filter-option-title\">{{ option.label }}</span>\n <span class=\"services-filter-option-subtitle\">{{ option.subtitle | translate }}</span>\n </div>\n </div>\n </ng-template>\n </p-select>\n </div>\n </div>\n</ng-template>\n\n<div class=\"relative z-20\">\n <div [class]=\"wrapClass()\" [attr.dir]=\"dir()\">\n <div class=\"services-top-filters-badge\">\n <span class=\"sce-services-top-filters__badge-text\">\n {{ badgeKey() | translate }}\n </span>\n </div>\n\n <div class=\"services-top-filters-card\">\n <div class=\"services-top-filters-row\">\n <ng-container\n *ngTemplateOutlet=\"\n filterColumn;\n context: {\n field: 'category',\n labelKey: categoryLabelKey(),\n icon: categoryIcon(),\n options: categoryOptions(),\n selected: selectedCategory(),\n }\n \"\n />\n\n <ng-container\n *ngTemplateOutlet=\"\n filterColumn;\n context: {\n field: 'target',\n labelKey: targetLabelKey(),\n icon: targetIcon(),\n options: targetOptions(),\n selected: selectedTarget(),\n }\n \"\n />\n\n @if (extraOptions().length > 0) {\n <ng-container\n *ngTemplateOutlet=\"\n filterColumn;\n context: {\n field: 'extra',\n labelKey: extraLabelKey(),\n icon: extraIcon(),\n options: extraFilterOptions(),\n selected: selectedExtra(),\n }\n \"\n />\n }\n\n <div class=\"services-top-filter-col services-top-filter-col-search\">\n <p class=\"services-top-filter-label\">{{ searchLabelKey() | translate }}</p>\n <div class=\"services-filter-search-row\">\n <input\n pInputText\n type=\"search\"\n class=\"services-filter-input\"\n [placeholder]=\"searchPlaceholderKey() | translate\"\n [attr.aria-label]=\"searchAriaKey() | translate\"\n [(ngModel)]=\"localQ\"\n (keydown.enter)=\"submitSearch()\"\n />\n <p-button\n type=\"button\"\n styleClass=\"services-search-icon-btn\"\n (onClick)=\"submitSearch()\"\n [ariaLabel]=\"searchAriaKey() | translate\"\n >\n <img src=\"/assets/icons/search-01-spaced.svg\" alt=\"\" aria-hidden=\"true\" class=\"sce-services-top-filters__search-icon\" />\n </p-button>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".sce-services-top-filters__control{display:flex;align-items:center;gap:var(--space-8)}.sce-services-top-filters__badge-text{font-family:var(--font-family-arabic-primary);font-size:var(--font-size-lg);font-weight:var(--font-weight-bold);color:var(--search-badge-text)}.sce-services-top-filters__search-icon{width:var(--space-24);height:var(--space-24)}\n"] }]
|
|
4305
4369
|
}], propDecorators: { q: [{ type: i0.Input, args: [{ isSignal: true, alias: "q", required: false }] }], category: [{ type: i0.Input, args: [{ isSignal: true, alias: "category", required: false }] }], target: [{ type: i0.Input, args: [{ isSignal: true, alias: "target", required: false }] }], sort: [{ type: i0.Input, args: [{ isSignal: true, alias: "sort", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], categories: [{ type: i0.Input, args: [{ isSignal: true, alias: "categories", required: false }] }], targets: [{ type: i0.Input, args: [{ isSignal: true, alias: "targets", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], extra: [{ type: i0.Input, args: [{ isSignal: true, alias: "extra", required: false }] }], extraOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "extraOptions", required: false }] }], extraParamName: [{ type: i0.Input, args: [{ isSignal: true, alias: "extraParamName", required: false }] }], filtersChange: [{ type: i0.Output, args: ["filtersChange"] }] } });
|
|
4306
4370
|
|
|
4371
|
+
/** Landing-page navigation bar that renders the required `items` as router links with route prefetching and active-route highlighting. */
|
|
4307
4372
|
class SceLandingNavComponent {
|
|
4308
4373
|
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
4309
4374
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SceLandingNavComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -4389,6 +4454,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
4389
4454
|
args: [{ host: { class: 'sce-landing-mobile-menu' }, selector: 'sce-landing-mobile-menu', standalone: true, imports: [RouterLink, TranslatePipe, RoutePrefetchDirective, SceRouteActiveDirective], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<button\n type=\"button\"\n class=\"sce-mobile-menu__trigger\"\n [attr.aria-label]=\"'nav.openMenu' | translate\"\n aria-haspopup=\"dialog\"\n [attr.aria-expanded]=\"isOpen()\"\n (click)=\"open()\"\n>\n <svg class=\"sce-mobile-menu__trigger-icon\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M3 6h18M3 12h18M3 18h18\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n</button>\n\n<ng-template #menuOverlay>\n <!-- Click-outside-to-close overlay (role=\"presentation\" \u2014 not an interactive control).\n Keyboard: the component binds a document Escape listener and renders a labelled close button. -->\n <div class=\"sce-mobile-menu__overlay\" role=\"presentation\" [attr.data-locale]=\"locale()\" (click)=\"close()\">\n <!-- stopPropagation keeps a click INSIDE the panel from closing the menu. It is not an\n interactive control, so a key handler here would be meaningless; Escape closes it. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\n <aside\n class=\"sce-mobile-menu__panel\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"'nav.menu' | translate\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"sce-mobile-menu__panel-header\">\n <span class=\"sce-mobile-menu__panel-title\">{{ 'nav.menu' | translate }}</span>\n <button type=\"button\" class=\"sce-mobile-menu__close-btn\" [attr.aria-label]=\"'nav.closeMenu' | translate\" (click)=\"close()\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M6 6l12 12M18 6L6 18\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" />\n </svg>\n </button>\n </div>\n\n <nav class=\"sce-mobile-menu__nav\" [attr.aria-label]=\"'aria.primaryNavigation' | translate\">\n @for (item of items(); track item.href) {\n <a\n [routerLink]=\"item.href\"\n sceRouteActive=\"sce-mobile-menu__nav-link--active\"\n [sceRouteActiveOptions]=\"{ exact: true }\"\n class=\"sce-mobile-menu__nav-link\"\n sceRoutePrefetch\n (click)=\"close()\"\n >\n {{ item.label }}\n </a>\n }\n </nav>\n </aside>\n </div>\n</ng-template>\n", styles: ["@charset \"UTF-8\";sce-landing-mobile-menu{display:inline-flex;align-items:center}.sce-mobile-menu__trigger{display:inline-flex;align-items:center;justify-content:center;width:var(--space-40);height:var(--space-40);padding:0;border:1px solid var(--landing-header-theme-border, var(--border-subtle, var(--color-border)));border-radius:var(--radius-lg);background:var(--landing-header-theme-bg, transparent);color:var(--header-fg, var(--color-fg));cursor:pointer;flex-shrink:0}.sce-mobile-menu__trigger:hover{background:var(--landing-header-theme-bg-hover, var(--surface-section-soft, rgba(0, 0, 0, .04)))}.sce-mobile-menu__trigger:focus-visible{outline:2px solid var(--color-brand-secondary-400);outline-offset:2px}.sce-mobile-menu__trigger-icon{width:var(--space-24);height:var(--space-24);color:inherit}@media(max-width:640px){.sce-mobile-menu__trigger{width:var(--space-32);height:var(--space-32)}.sce-mobile-menu__trigger-icon{width:1.15rem;height:1.15rem}}@media(max-width:400px){.sce-mobile-menu__trigger{width:var(--space-28);height:var(--space-28)}.sce-mobile-menu__trigger-icon{width:var(--space-16);height:var(--space-16)}}.sce-mobile-menu__overlay{position:fixed;inset:0;z-index:1200;display:block;margin:0;padding:0;border:0;background:var(--color-overlay-strong, rgba(0, 0, 0, .5));animation:sce-lmm-overlay-in .16s ease-out}.sce-mobile-menu__panel{position:fixed;inset-block:0;inset-inline-start:0;inset-inline-end:auto;width:min(var(--space-320, 20rem),82vi);max-width:var(--space-320, 20rem);height:100dvb;max-height:100dvb;display:flex;flex-direction:column;gap:var(--space-8);padding:var(--space-16);box-sizing:border-box;background:var(--color-surface, var(--color-bg, var(--background-bg-primary)));color:var(--color-fg);border-inline-end:1px solid var(--color-border);box-shadow:var(--shadow-overlay-lg, 0 12px 40px rgba(0, 0, 0, .25));animation:sce-lmm-panel-in .2s ease-out;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain}.sce-mobile-menu__panel-header{display:flex;align-items:center;justify-content:space-between;padding-block-end:var(--space-12);margin-block-end:var(--space-4);border-block-end:1px solid var(--color-border)}.sce-mobile-menu__panel-title{font-size:var(--font-size-md);font-weight:var(--font-weight-semibold);color:var(--color-fg)}.sce-mobile-menu__close-btn{display:inline-flex;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;padding:0;border:0;border-radius:var(--radius-lg);background:transparent;color:var(--color-fg);cursor:pointer}.sce-mobile-menu__close-btn:hover{background:var(--surface-section-soft, rgba(0, 0, 0, .06))}.sce-mobile-menu__close-btn:focus-visible{outline:2px solid var(--color-brand-secondary-400);outline-offset:2px}.sce-mobile-menu__nav{display:flex;flex-direction:column;gap:var(--space-4)}.sce-mobile-menu__nav-link{display:block;padding:var(--space-12) .75rem;border-radius:var(--radius-lg);text-decoration:none;font-size:var(--font-size-md);font-weight:var(--font-weight-semibold);color:var(--color-fg);opacity:var(--opacity-85)}.sce-mobile-menu__nav-link:hover{opacity:1;background:var(--surface-section-soft, rgba(0, 0, 0, .04))}.sce-mobile-menu__nav-link--active{opacity:1;color:var(--color-brand-secondary-600);background:var(--surface-section-soft, rgba(0, 0, 0, .04))}.sce-mobile-menu__nav-link:focus-visible{outline:2px solid var(--color-brand-secondary-400);outline-offset:2px;opacity:1}@keyframes sce-lmm-overlay-in{0%{opacity:0}to{opacity:1}}@keyframes sce-lmm-panel-in{0%{transform:translate(calc(var(--dir) * -100%))}to{transform:translate(0)}}\n"] }]
|
|
4390
4455
|
}], ctorParameters: () => [], propDecorators: { overlayTpl: [{ type: i0.ViewChild, args: ['menuOverlay', { isSignal: true }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }] } });
|
|
4391
4456
|
|
|
4457
|
+
/** Button that switches the app between Arabic and English through LanguageService, labelled with the language it will switch to rather than the current one. */
|
|
4392
4458
|
class SceLangToggleComponent {
|
|
4393
4459
|
language = inject(LanguageService);
|
|
4394
4460
|
translate = inject(TranslateService);
|
|
@@ -4411,6 +4477,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
4411
4477
|
args: [{ host: { class: 'sce-lang-toggle' }, selector: 'sce-lang-toggle', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<button type=\"button\" class=\"langToggle\" [class.langToggle--lab]=\"lightContext()\" [attr.aria-label]=\"ariaLabel()\" (click)=\"toggle()\">\n {{ nextLabel() }}\n</button>\n", styles: ["@charset \"UTF-8\";.langToggle{border:0;background:transparent;padding:0;cursor:pointer;font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-md);font-weight:700;font-style:normal;line-height:1.4;color:var(--header-fg)}.langToggle--lab{color:var(--text-text-primary-900)}@media(max-width:640px){.langToggle{font-size:var(--font-size-sm)}}\n"] }]
|
|
4412
4478
|
}], propDecorators: { lightContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "lightContext", required: false }] }] } });
|
|
4413
4479
|
|
|
4480
|
+
/** Light/dark theme switcher backed by ThemeService, with labels falling back to translated defaults. */
|
|
4414
4481
|
class SceThemeSwitcherComponent {
|
|
4415
4482
|
themeService = inject(ThemeService);
|
|
4416
4483
|
translate = inject(TranslateService);
|
|
@@ -4459,6 +4526,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
4459
4526
|
args: [{ host: { class: 'sce-theme-toggle-button' }, selector: 'sce-theme-toggle-button', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<button type=\"button\" class=\"sce-theme-toggle\" [attr.aria-label]=\"ariaLabel()\" [title]=\"ariaLabel()\" (click)=\"toggle()\">\n <i class=\"pi\" [class.pi-moon]=\"theme() === 'light'\" [class.pi-sun]=\"theme() === 'dark'\" aria-hidden=\"true\"></i>\n</button>\n", styles: ["sce-theme-toggle-button{display:inline-flex}sce-theme-toggle-button .sce-theme-toggle{flex-shrink:0;width:var(--space-40);height:var(--space-40);border-radius:var(--radius-pill);border:1px solid var(--account-switcher-menu-theme-border, var(--border-subtle));background:var(--account-switcher-menu-theme-bg, var(--surface-primary));color:var(--account-switcher-menu-theme-color, var(--text-text-primary-900));display:inline-flex;align-items:center;justify-content:center;cursor:pointer;font-size:var(--font-size-lg-18);line-height:1;padding:0;transition:background .15s ease,border-color .15s ease}sce-theme-toggle-button .sce-theme-toggle:hover{background:var(--account-switcher-menu-theme-bg-hover, var(--surface-section-soft));border-color:var(--account-switcher-menu-theme-border-hover, var(--control-border))}\n"] }]
|
|
4460
4527
|
}] });
|
|
4461
4528
|
|
|
4529
|
+
/** Thin wrapper over `sce-confirm-dialog` for approve/reject actions, offering a convenience reason-textarea API (`showReasonInput` and friends) alongside the legacy `field` config, which wins when both are supplied. */
|
|
4462
4530
|
class SceActionDialogComponent {
|
|
4463
4531
|
visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
4464
4532
|
locale = input('ar', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
|
|
@@ -4540,6 +4608,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
4540
4608
|
}], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: true }] }], confirmLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmLabel", required: true }] }], cancelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelLabel", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], confirmDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmDisabled", required: false }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: false }] }], showReasonInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "showReasonInput", required: false }] }], reasonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "reasonLabel", required: false }] }], reasonPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "reasonPlaceholder", required: false }] }], reasonValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "reasonValue", required: false }] }], reasonRequired: [{ type: i0.Input, args: [{ isSignal: true, alias: "reasonRequired", required: false }] }], reasonError: [{ type: i0.Input, args: [{ isSignal: true, alias: "reasonError", required: false }] }], close: [{ type: i0.Output, args: ["close"] }], cancel: [{ type: i0.Output, args: ["cancel"] }], confirm: [{ type: i0.Output, args: ["confirm"] }], reasonChange: [{ type: i0.Output, args: ["reasonChange"] }], fieldChange: [{ type: i0.Output, args: ["fieldChange"] }] } });
|
|
4541
4609
|
|
|
4542
4610
|
let nextFormDialogId = 0;
|
|
4611
|
+
/** Dialog shell for forms, with submit/cancel footer buttons, an optional secondary action and an error banner; the footer submit button lives outside the projected `<form>` and is wired to it by a generated id, so submission goes through the native form submit event. */
|
|
4543
4612
|
class SceFormDialogComponent {
|
|
4544
4613
|
translate = inject(TranslateService);
|
|
4545
4614
|
visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
@@ -4605,6 +4674,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
4605
4674
|
args: [{ host: { class: 'sce-form-dialog' }, selector: 'sce-form-dialog', standalone: true, imports: [SceDialogShellComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<sce-dialog-shell\n [visible]=\"visible()\"\n [locale]=\"locale()\"\n [title]=\"title()\"\n [subtitle]=\"subtitle()\"\n [size]=\"size()\"\n [locked]=\"isSubmitting()\"\n [dismissableMask]=\"dismissableMask() ?? !isSubmitting()\"\n (close)=\"onClose()\"\n>\n <form [id]=\"formId\" class=\"form\" (submit)=\"onSubmit($event)\" novalidate>\n <div class=\"bodySections\">\n @if (errorMessage()) {\n <p class=\"errorBanner\">{{ errorMessage() }}</p>\n }\n <ng-content />\n </div>\n </form>\n\n <div dialogFooter [class]=\"secondaryAction() ? 'footerActions' : 'footerActionsPair'\">\n @if (secondaryAction(); as secondary) {\n @if (secondaryActionPosition() === 'first') {\n <button type=\"button\" class=\"btn cancel\" [disabled]=\"isSubmitting() || secondary.disabled\" (click)=\"onSecondaryAction()\">\n {{ secondary.label }}\n </button>\n }\n @if (secondaryActionPosition() === 'last') {\n <button type=\"submit\" [attr.form]=\"formId\" [class]=\"submitBtnClass()\" [disabled]=\"isSubmitting()\">\n {{ resolvedSubmitLabel() }}\n </button>\n }\n <button type=\"button\" class=\"btn cancel\" [disabled]=\"isSubmitting()\" (click)=\"onClose()\">\n {{ resolvedCancelLabel() }}\n </button>\n @if (secondaryActionPosition() === 'last') {\n <button type=\"button\" class=\"btn cancel\" [disabled]=\"isSubmitting() || secondary.disabled\" (click)=\"onSecondaryAction()\">\n {{ secondary.label }}\n </button>\n } @else {\n <button type=\"submit\" [attr.form]=\"formId\" [class]=\"submitBtnClass()\" [disabled]=\"isSubmitting()\">\n {{ resolvedSubmitLabel() }}\n </button>\n }\n } @else {\n <button type=\"button\" class=\"btn cancel\" [disabled]=\"isSubmitting()\" (click)=\"onClose()\">\n {{ resolvedCancelLabel() }}\n </button>\n <button type=\"submit\" [attr.form]=\"formId\" [class]=\"submitBtnClass()\" [disabled]=\"isSubmitting()\">\n {{ resolvedSubmitLabel() }}\n </button>\n }\n </div>\n</sce-dialog-shell>\n", styles: ["@charset \"UTF-8\";.form{display:contents}.bodySections{display:grid;gap:var(--space-20)}.section{display:grid;gap:var(--space-12)}.sectionTitle{margin:0;color:var(--details-label-color);font-size:var(--details-label-size);font-weight:var(--font-weight-semibold)}.row{display:grid;grid-template-columns:1fr;gap:var(--space-12)}@media(min-width:520px){.row{grid-template-columns:repeat(2,minmax(0,1fr))}}.errorBanner{margin:0;padding:var(--space-10) var(--space-14);border-radius:var(--radius-10);border:1px solid var(--color-red-200);background:var(--color-red-100);color:var(--color-red-800);font-size:var(--font-size-sm);font-weight:500}.btn{width:100%;min-height:var(--space-48);border-radius:var(--radius-10);padding:var(--space-10) var(--space-20);font-family:var(--font-family-arabic-primary);font-weight:600;font-size:var(--font-size-md-15);text-align:center;border:1px solid transparent;cursor:pointer;transition:background .15s ease,border-color .15s ease,color .15s ease,opacity .15s ease}.btn:disabled{opacity:.55;cursor:not-allowed}.cancel{border-color:var(--background-bg-brand-solid);color:var(--text-text-brand-primary);background:var(--color-surface)}.cancel:hover:not(:disabled){background:var(--app-surface-hover);border-color:var(--background-bg-brand-solid)}.submitPrimary{background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand)}.submitPrimary:hover:not(:disabled){background:var(--button-background-primary-bg-hover)}.submitDanger{background:var(--button-background-destructive-bg-primary);color:var(--text-text-primaryon-brand)}.submitDanger:hover:not(:disabled){background:var(--button-background-destructive-bg-hover)}.submitSuccess{background:var(--color-kiwi-700);color:var(--text-text-primaryon-brand)}.sce-form-dialog .footerActions,.sce-form-dialog .footerActionsPair{grid-column:1/-1;display:grid;gap:var(--space-12);width:100%}.sce-form-dialog .footerActions{grid-template-columns:repeat(3,minmax(0,1fr))}.sce-form-dialog .footerActionsPair{grid-template-columns:repeat(2,minmax(0,1fr))}.sce-form-dialog .footerActions .btn,.sce-form-dialog .footerActionsPair .btn{display:block;width:100%;min-height:var(--space-48);box-sizing:border-box}\n"] }]
|
|
4606
4675
|
}], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], submitLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitLabel", required: false }] }], cancelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelLabel", required: false }] }], isSubmitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSubmitting", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], dismissableMask: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissableMask", required: false }] }], secondaryAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "secondaryAction", required: false }] }], secondaryActionPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "secondaryActionPosition", required: false }] }], close: [{ type: i0.Output, args: ["close"] }], submitForm: [{ type: i0.Output, args: ["submitForm"] }], submitValues: [{ type: i0.Output, args: ["submitValues"] }], secondaryActionClick: [{ type: i0.Output, args: ["secondaryActionClick"] }] } });
|
|
4607
4676
|
|
|
4677
|
+
/** Optionally-titled section wrapper for grouping projected fields inside `sce-form-dialog`, laid out in one or two columns. */
|
|
4608
4678
|
class SceFormDialogSectionComponent {
|
|
4609
4679
|
title = input(...(ngDevMode ? [undefined, { debugName: "title" }] : /* istanbul ignore next */ []));
|
|
4610
4680
|
twoColumn = input(false, ...(ngDevMode ? [{ debugName: "twoColumn" }] : /* istanbul ignore next */ []));
|
|
@@ -4616,6 +4686,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
4616
4686
|
args: [{ host: { class: 'sce-form-dialog-section' }, selector: 'sce-form-dialog-section', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<section class=\"section\">\n @if (title()) {\n <h3 class=\"sectionTitle\">{{ title() }}</h3>\n }\n <div [class]=\"twoColumn() ? 'row' : 'section'\">\n <ng-content />\n </div>\n</section>\n", styles: [":host{display:block}.sce-form-dialog-section{display:contents}\n"] }]
|
|
4617
4687
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], twoColumn: [{ type: i0.Input, args: [{ isSignal: true, alias: "twoColumn", required: false }] }] } });
|
|
4618
4688
|
|
|
4689
|
+
/** Single-expand accordion that renders a list of title/content items, toggling one open panel at a time. */
|
|
4619
4690
|
class SceAccordionComponent {
|
|
4620
4691
|
items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
4621
4692
|
className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
@@ -4634,6 +4705,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
4634
4705
|
args: [{ host: { class: 'sce-accordion' }, selector: 'sce-accordion', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"accordion\" [class]=\"className()\">\n @for (item of items(); track item.id) {\n <div class=\"accordion__item\" [class]=\"itemClassName()\">\n <button type=\"button\" (click)=\"toggle(item.id)\" class=\"accordion__header\" [class]=\"headerClassName()\">\n <span class=\"accordion__title\">{{ item.title }}</span>\n <span class=\"accordion__icon\">\n {{ openId() === item.id ? '\u2212' : '+' }}\n </span>\n </button>\n @if (openId() === item.id) {\n <div class=\"accordion__content\" [class]=\"contentClassName()\">\n <p class=\"accordion__text\">{{ item.content }}</p>\n </div>\n }\n </div>\n }\n</div>\n", styles: [".accordion{display:flex;flex-direction:column;gap:var(--space-12)}.accordion__item{border-radius:var(--space-16);overflow:hidden;background:var(--color-surface)}.accordion__header{width:100%;padding:var(--space-16) var(--space-24);display:flex;align-items:center;justify-content:space-between;background:transparent;border:0;cursor:pointer;font-family:inherit;text-align:inherit;transition:background-color .2s ease}.accordion__header:hover{background-color:#00000005}.accordion__title{color:var(--text-text-primary-900);font-weight:var(--font-weight-semibold);font-size:var(--font-size-lg)}.accordion__icon{font-size:var(--space-20);line-height:1;color:var(--text-text-primary-900);display:inline-flex;align-items:center;justify-content:center;transition:transform .2s ease}.accordion__content{padding:var(--space-16) var(--space-24);background:var(--color-surface)}.accordion__text{color:var(--text-text-secondary-700);font-size:var(--font-size-md, .875rem);line-height:1.5;margin:0}\n"] }]
|
|
4635
4706
|
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], itemClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemClassName", required: false }] }], headerClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerClassName", required: false }] }], contentClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentClassName", required: false }] }] } });
|
|
4636
4707
|
|
|
4708
|
+
/** Horizontal wizard progress indicator with three `variant`s (numbered `steps`, a `progress` bar, or `pills`), optional per-step error markers, and click-to-navigate gated by `clickable` (off by default) plus an `isStepClickable` predicate; uses `ViewEncapsulation.None`. */
|
|
4637
4709
|
class SceHorizontalWizardStepperComponent {
|
|
4638
4710
|
translate = inject(TranslateService);
|
|
4639
4711
|
steps = input.required(...(ngDevMode ? [{ debugName: "steps" }] : /* istanbul ignore next */ []));
|
|
@@ -4725,6 +4797,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
4725
4797
|
args: [{ host: { class: 'sce-horizontal-wizard-stepper' }, selector: 'sce-horizontal-wizard-stepper', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "@if (variant() === 'steps') {\n <div class=\"mobileRoot\">\n <div class=\"mobileHeader\">\n <h2 class=\"mobileHeaderTitle\">{{ activeStep().title }}</h2>\n <p class=\"mobileHeaderSubtitle\">\n {{ 'stepper.fillRequiredData' | translate }}\n </p>\n <span class=\"mobileProgress\">\n {{ 'stepper.stepProgress' | translate: { current: currentStep(), total: steps().length } }}\n </span>\n </div>\n\n <div class=\"horizontalTrack\" role=\"list\" [attr.aria-label]=\"'stepper.formSteps' | translate\">\n <div [class]=\"'horizontalStepsRow ' + rowDirClass()\">\n @for (step of stepViews(); track step.id; let i = $index; let first = $first; let last = $last) {\n <div class=\"horizontalStepItem\" role=\"listitem\">\n <div class=\"horizontalStepTrack\">\n @if (!first) {\n <div\n [class]=\"'horizontalLine horizontalLineBefore' + (currentStep() > steps()[i - 1].id ? ' horizontalLineCompleted' : '')\"\n aria-hidden=\"true\"\n ></div>\n } @else {\n <span class=\"horizontalLineSpacer\" aria-hidden=\"true\"></span>\n }\n\n @if (errorSet().has(step.id) && showErrors()) {\n <button\n type=\"button\"\n [class]=\"step.circleClass\"\n (click)=\"showError.emit(step.id)\"\n [attr.aria-label]=\"showErrorLabel() + ': ' + step.title\"\n [attr.aria-invalid]=\"true\"\n [title]=\"showErrorLabel()\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path\n d=\"M12 8v4m0 4h.01M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n } @else if (step.isClickable) {\n <button\n type=\"button\"\n [class]=\"step.circleClass + ' horizontalCircleButton'\"\n (click)=\"stepClick.emit(step.id)\"\n [attr.aria-current]=\"currentStep() === step.id ? 'step' : null\"\n [attr.aria-label]=\"step.title\"\n [attr.aria-invalid]=\"errorSet().has(step.id) ? true : null\"\n >\n {{ step.stepContent }}\n </button>\n } @else {\n <div [class]=\"step.circleClass\">\n {{ step.stepContent }}\n </div>\n }\n\n @if (!last) {\n <div\n [class]=\"'horizontalLine horizontalLineAfter' + (currentStep() > step.id ? ' horizontalLineCompleted' : '')\"\n aria-hidden=\"true\"\n ></div>\n } @else {\n <span class=\"horizontalLineSpacer\" aria-hidden=\"true\"></span>\n }\n </div>\n\n @if (step.isClickable) {\n <button\n type=\"button\"\n [attr.data-step-id]=\"step.id\"\n class=\"horizontalStepButton horizontalStepClickable\"\n (click)=\"stepClick.emit(step.id)\"\n [attr.aria-current]=\"currentStep() === step.id ? 'step' : null\"\n [attr.aria-label]=\"step.title\"\n [attr.aria-invalid]=\"errorSet().has(step.id) ? true : null\"\n >\n <span [class]=\"step.labelClass\">{{ step.title }}</span>\n </button>\n } @else {\n <div\n [attr.data-step-id]=\"step.id\"\n class=\"horizontalStepButton\"\n [attr.aria-current]=\"currentStep() === step.id ? 'step' : null\"\n [attr.aria-invalid]=\"errorSet().has(step.id) ? true : null\"\n >\n <span [class]=\"step.labelClass\">{{ step.title }}</span>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n} @else if (isProgressVariant()) {\n <div\n class=\"stepper-progress\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"progressPercent()\"\n [attr.aria-label]=\"progressPercent() + '%'\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n >\n <div class=\"stepper-progress__header\">\n <span class=\"stepper-progress__label\">{{ activeStep().title }}</span>\n <span class=\"stepper-progress__percent\">{{ progressPercent() }}%</span>\n </div>\n <div class=\"stepper-progress__track\">\n <div class=\"stepper-progress__fill\" [style.width.%]=\"progressPercent()\"></div>\n </div>\n <span class=\"stepper-progress__step-count\">\n {{ 'stepper.stepProgress' | translate: { current: currentStep(), total: steps().length } }}\n </span>\n </div>\n} @else if (isPillsVariant()) {\n <div class=\"stepper-pills\" role=\"list\" [attr.aria-label]=\"'stepper.formSteps' | translate\">\n @for (step of stepViews(); track step.id) {\n <button\n type=\"button\"\n class=\"stepper-pills__pill\"\n [class.stepper-pills__pill--active]=\"currentStep() === step.id\"\n [class.stepper-pills__pill--completed]=\"step.isCompleted\"\n [class.stepper-pills__pill--error]=\"errorSet().has(step.id)\"\n [disabled]=\"!step.isClickable\"\n (click)=\"stepClick.emit(step.id)\"\n role=\"listitem\"\n [attr.aria-current]=\"currentStep() === step.id ? 'step' : null\"\n >\n @if (step.isCompleted && !errorSet().has(step.id)) {\n <span class=\"stepper-pills__check\" aria-hidden=\"true\">\u2713</span>\n }\n {{ step.title }}\n </button>\n }\n </div>\n}\n", styles: ["@charset \"UTF-8\";.mobileRoot{width:100%;min-width:0;box-sizing:border-box;border-radius:var(--space-16);background:var(--color-surface);padding:var(--space-16)}@media(min-width:1024px){.mobileRoot{display:none}}.mobileHeader{margin-block-end:var(--space-12)}.mobileHeaderTitle{margin:0;font-family:var(--font-family-arabic-primary);font-size:var(--font-size-lg);font-weight:700;color:var(--text-text-display)}.mobileHeaderSubtitle{margin:.35rem 0 0;font-family:var(--font-family-arabic-primary);font-size:var(--font-size-sm);color:var(--text-text-secondary-600)}.mobileProgress{display:inline-block;margin-block-start:.35rem;font-family:var(--font-family-arabic-primary);font-size:var(--font-size-xs);font-weight:600;color:var(--text-text-secondary-600)}.horizontalTrack{width:100%;min-width:0}.horizontalStepsRow{display:flex;width:100%;align-items:flex-start;direction:rtl}.horizontalRowLtr{direction:ltr}.horizontalStepItem{flex:1 1 0;min-width:0;display:flex;flex-direction:column;align-items:center}.horizontalStepTrack{display:flex;width:100%;align-items:center;min-height:var(--space-32)}.horizontalLine{flex:1 1 auto;min-width:0;height:var(--space-2);align-self:center;background:var(--color-neutral-300);z-index:0}.horizontalLineBefore{margin-inline-end:-1rem}.horizontalLineAfter{margin-inline-start:-1rem}.horizontalLineCompleted{background:var(--color-success-600)}.horizontalLineSpacer{flex:1 1 auto;min-width:0;height:var(--space-2);visibility:hidden}.horizontalCircleButton,.circleErrorAction{padding:0;border-width:var(--space-2);border-style:solid;cursor:pointer;font:inherit}.horizontalCircleButton:focus-visible,.circleErrorAction:focus-visible{outline:2px solid var(--color-success-600);outline-offset:2px}.circleErrorAction:focus-visible{outline-color:var(--color-red-700)}.circleErrorAction:hover{background:var(--color-red-300)}.horizontalStepButton{display:flex;width:100%;min-width:0;flex-direction:column;align-items:center;margin-block-start:var(--space-8);padding:.125rem .2rem;border:0;background:transparent;text-align:center;cursor:default;border-radius:var(--space-8);transition:background .15s ease}.horizontalStepClickable{cursor:pointer}.horizontalStepClickable:hover{background:var(--color-neutral-100)}.horizontalStepButton:focus-visible{outline:2px solid var(--color-success-600);outline-offset:2px}.horizontalLabel{display:-webkit-box;width:100%;margin:0;font-family:var(--font-family-arabic-primary);font-size:var(--space-10);font-weight:600;line-height:1.25;color:var(--color-neutral-400);-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;text-align:center}.horizontalLabelActive{color:var(--text-text-primary-900)}.horizontalLabelError{color:var(--color-red-700)}.circle{position:relative;z-index:1;display:flex;height:var(--space-32);width:var(--space-32);flex:0 0 2rem;flex-shrink:0;box-sizing:border-box;align-items:center;justify-content:center;border-radius:var(--radius-full);border:2px solid var(--color-neutral-300);background:var(--color-surface);font-size:var(--font-size-md);font-weight:600;color:var(--color-neutral-400)}.circleActive{border-color:var(--color-success-600);background:var(--color-surface);color:var(--text-text-primary-900)}.circleCompleted{border-color:var(--color-success-600);background:var(--color-success-600);color:var(--color-base-white)}.circleError{border-color:var(--color-red-600);background:var(--color-red-200);color:var(--color-red-700)}@media(max-width:380px){.horizontalTrack{overflow-x:auto;-webkit-overflow-scrolling:touch;padding-block-end:var(--space-4)}.horizontalStepsRow{min-width:22rem}}.stepper-progress{width:100%;padding:var(--space-md);box-sizing:border-box}.stepper-progress__header{display:flex;align-items:center;justify-content:space-between;margin-block-end:var(--space-sm)}.stepper-progress__label{font-family:var(--font-family-arabic-primary);font-size:var(--font-size-sm, .875rem);font-weight:600;color:var(--text-text-primary-900)}.stepper-progress__percent{font-family:var(--font-family-arabic-primary);font-size:var(--font-size-sm, .875rem);font-weight:700;color:var(--color-success-600)}.stepper-progress__track{width:100%;height:var(--space-8);border-radius:var(--radius-full);background:var(--color-neutral-200);overflow:hidden}.stepper-progress__fill{height:100%;border-radius:var(--radius-full);background:var(--color-success-600);transition:width .3s ease}.stepper-progress__step-count{display:block;margin-block-start:var(--space-xs);font-family:var(--font-family-arabic-primary);font-size:var(--font-size-xs, .75rem);font-weight:600;color:var(--text-text-secondary-600)}.stepper-pills{display:flex;flex-wrap:wrap;gap:var(--space-sm);width:100%;padding:var(--space-md) 0}.stepper-pills__pill{display:inline-flex;align-items:center;gap:var(--space-xs);padding:var(--space-sm) var(--space-lg);border:2px solid var(--color-neutral-300);border-radius:var(--radius-full);background:var(--color-surface);font-family:var(--font-family-arabic-primary);font-size:var(--font-size-sm, .875rem);font-weight:600;color:var(--color-neutral-500);cursor:pointer;transition:background .15s,border-color .15s,color .15s}.stepper-pills__pill:disabled{cursor:default}.stepper-pills__pill:not(:disabled):hover{background:var(--color-neutral-100)}.stepper-pills__pill:focus-visible{outline:2px solid var(--color-success-600);outline-offset:2px}.stepper-pills__pill--active{border-color:var(--color-success-600);background:var(--color-surface);color:var(--text-text-primary-900)}.stepper-pills__pill--completed{border-color:var(--color-success-600);background:var(--color-success-600);color:var(--color-base-white)}.stepper-pills__pill--error{border-color:var(--color-red-600);background:var(--color-red-200);color:var(--color-red-700)}.stepper-pills__check{font-size:var(--font-size-xs, .75rem)}\n"] }]
|
|
4726
4798
|
}], propDecorators: { steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: true }] }], currentStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentStep", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], errorStepIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorStepIds", required: false }] }], isStepClickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "isStepClickable", required: false }] }], clickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clickable", required: false }] }], showErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "showErrors", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], stepClick: [{ type: i0.Output, args: ["stepClick"] }], showError: [{ type: i0.Output, args: ["showError"] }] } });
|
|
4727
4799
|
|
|
4800
|
+
/** Vertical wizard stepper sharing `StepItem` with the horizontal one; unlike that component `clickable` defaults to true, and `errorStepIds` marks steps whose `showError` link is emitted on click. */
|
|
4728
4801
|
class SceVerticalStepperComponent {
|
|
4729
4802
|
translate = inject(TranslateService);
|
|
4730
4803
|
steps = input.required(...(ngDevMode ? [{ debugName: "steps" }] : /* istanbul ignore next */ []));
|
|
@@ -4833,6 +4906,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
4833
4906
|
}], propDecorators: { steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: true }] }], currentStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentStep", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], errorStepIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorStepIds", required: false }] }], isStepClickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "isStepClickable", required: false }] }], clickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clickable", required: false }] }], stepClick: [{ type: i0.Output, args: ["stepClick"] }], showError: [{ type: i0.Output, args: ["showError"] }] } });
|
|
4834
4907
|
|
|
4835
4908
|
const SIZE_PX$2 = { sm: 28, md: 42, lg: 56 };
|
|
4909
|
+
/** Branded loading indicator that animates the app logo at a small/medium/large size preset, rendered inline or as a fullscreen overlay. */
|
|
4836
4910
|
class SceBrandLoaderComponent {
|
|
4837
4911
|
translate = inject(TranslateService);
|
|
4838
4912
|
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
@@ -4852,6 +4926,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
4852
4926
|
|
|
4853
4927
|
const SIZE_PX$1 = { sm: 24, md: 40, lg: 64 };
|
|
4854
4928
|
const THICKNESS_PX = { sm: 2.5, md: 3.5, lg: 5 };
|
|
4929
|
+
/** Spinning ring loading indicator drawn with a radial-gradient mask at a size preset, rendered inline or as a fullscreen overlay. */
|
|
4855
4930
|
class SceRingLoaderComponent {
|
|
4856
4931
|
translate = inject(TranslateService);
|
|
4857
4932
|
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
@@ -4925,6 +5000,7 @@ function buildGearPath(geo, cx = 32, cy = 32) {
|
|
|
4925
5000
|
}
|
|
4926
5001
|
const PRIMARY_PATH = buildGearPath(PRIMARY_GEAR);
|
|
4927
5002
|
const SECONDARY_PATH = buildGearPath(SECONDARY_GEAR);
|
|
5003
|
+
/** Loading indicator that renders two meshed, counter-rotating SVG gears whose paths are generated at module load, sized by preset and shown inline or as a fullscreen overlay. */
|
|
4928
5004
|
class SceGearsLoaderComponent {
|
|
4929
5005
|
translate = inject(TranslateService);
|
|
4930
5006
|
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
@@ -4948,6 +5024,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
4948
5024
|
args: [{ host: { class: 'sce-gears-loader' }, selector: 'sce-gears-loader', standalone: true, imports: [NgTemplateOutlet], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template #spinnerTpl>\n <span dir=\"ltr\" class=\"sce-gears-loader__spinner\" [style.width.px]=\"containerWidth()\" [style.height.px]=\"primaryPx()\">\n <svg\n viewBox=\"0 0 64 64\"\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"sce-gears-loader__gear sce-gears-loader__gear--primary\"\n [style.width.px]=\"primaryPx()\"\n [style.height.px]=\"primaryPx()\"\n aria-hidden=\"true\"\n >\n <path [attr.d]=\"primaryPath\" fill=\"currentColor\" fill-rule=\"evenodd\" clip-rule=\"evenodd\" />\n </svg>\n <svg\n viewBox=\"0 0 64 64\"\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"sce-gears-loader__gear sce-gears-loader__gear--secondary\"\n [style.width.px]=\"secondaryPx()\"\n [style.height.px]=\"secondaryPx()\"\n [style.left.px]=\"secondaryLeft()\"\n [style.top.px]=\"secondaryTop()\"\n aria-hidden=\"true\"\n >\n <path [attr.d]=\"secondaryPath\" fill=\"currentColor\" fill-rule=\"evenodd\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n</ng-template>\n\n@if (variant() === 'fullscreen') {\n <div class=\"sce-gears-loader__overlay\" role=\"status\" aria-live=\"polite\" [attr.aria-label]=\"label()\">\n <ng-container *ngTemplateOutlet=\"spinnerTpl\" />\n @if (hintText()) {\n <div class=\"sce-gears-loader__hint\">{{ hintText() }}</div>\n }\n </div>\n} @else {\n <span class=\"sce-gears-loader__inline\" role=\"status\" aria-live=\"polite\" [attr.aria-label]=\"label()\">\n <ng-container *ngTemplateOutlet=\"spinnerTpl\" />\n </span>\n}\n", styles: [".sce-gears-loader{display:contents}.sce-gears-loader__overlay{position:fixed;inset:0;max-height:100svb;z-index:9999;display:flex;align-items:center;justify-content:center;background:var(--overlay-backdrop)}.sce-gears-loader__hint{position:absolute;inset-inline-start:var(--space-16);inset-inline-end:var(--space-16);bottom:var(--space-16);text-align:center;color:color-mix(in srgb,var(--text-text-primaryon-brand) 80%,transparent);font-size:var(--font-size-sm)}.sce-gears-loader__inline{display:inline-flex;align-items:center;justify-content:center}.sce-gears-loader__spinner{position:relative;display:inline-block;color:var(--background-bg-brand-solid)}.sce-gears-loader__gear{position:absolute;transform-origin:50% 50%}.sce-gears-loader__gear--primary{inset-inline-start:0;top:0;animation:spin 3s linear infinite}.sce-gears-loader__gear--secondary{opacity:.7;animation:spin 2.1s linear infinite reverse}\n"] }]
|
|
4949
5025
|
}], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], hintText: [{ type: i0.Input, args: [{ isSignal: true, alias: "hintText", required: false }] }] } });
|
|
4950
5026
|
|
|
5027
|
+
/** Design-system button that renders an `<a>` when `routerLink` or `href` is set and a `<button>` otherwise; note `fullWidth` defaults to true. */
|
|
4951
5028
|
class SceButton {
|
|
4952
5029
|
variant = input('primary', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
4953
5030
|
type = input('button', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
|
|
@@ -4991,6 +5068,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
4991
5068
|
args: [{ host: { class: 'sce-button' }, selector: 'sce-button', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [SceIcon, SceSkeleton, RouterLink, NgTemplateOutlet], template: "<ng-template #inner>\n @if (loading()) {\n <sce-skeleton variant=\"rounded\" width=\"var(--size-18)\" height=\"var(--size-18)\" borderRadius=\"50%\" animation=\"wave\" aria-hidden=\"true\" />\n }\n @if (icon() && iconPosition() === 'start') {\n <sce-icon [name]=\"icon()\" [size]=\"iconSize()\" />\n }\n <ng-content></ng-content>\n @if (icon() && iconPosition() === 'end') {\n <sce-icon [name]=\"icon()\" [size]=\"iconSize()\" />\n }\n</ng-template>\n\n@if (routerLink() !== null) {\n <!-- Anchor mode keeps real link semantics (middle-click, open-in-new-tab). -->\n <a\n [class]=\"classes()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : null\"\n [attr.tabindex]=\"isDisabled() ? -1 : null\"\n [routerLink]=\"routerLink()\"\n >\n <ng-container [ngTemplateOutlet]=\"inner\" />\n </a>\n} @else if (href() !== null) {\n <a\n [class]=\"classes()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : null\"\n [attr.tabindex]=\"isDisabled() ? -1 : null\"\n [href]=\"href()\"\n >\n <ng-container [ngTemplateOutlet]=\"inner\" />\n </a>\n} @else {\n <button [class]=\"classes()\" [attr.aria-label]=\"ariaLabel() || null\" [type]=\"type()\" [disabled]=\"isDisabled()\">\n <ng-container [ngTemplateOutlet]=\"inner\" />\n </button>\n}\n", styles: [":host{display:block}.btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-sm);height:var(--size-50);padding:0 var(--space-xl);font-size:var(--font-size-md);font-weight:var(--font-weight-medium);letter-spacing:.01em;border-radius:var(--radius-md);border:none;cursor:pointer;font-family:inherit;text-decoration:none;transition:background-color var(--transition-base),transform var(--transition-fast),box-shadow var(--transition-base)}.btn:active:not(:disabled){transform:scale(.985)}.btn--disabled{pointer-events:none;opacity:.6;cursor:not-allowed}.btn--primary{background-color:var(--color-brand-primary-800);color:var(--color-white)}.btn--secondary{background-color:var(--color-neutral-200);color:var(--color-text)}.btn--secondary:hover:not(:disabled){background-color:var(--color-neutral-300)}.btn--secondary:active:not(:disabled){background-color:var(--color-neutral-400)}.btn--transparent{background-color:transparent;color:var(--color-text)}.btn--transparent:hover:not(:disabled){background-color:var(--color-neutral)}.btn--transparent:active:not(:disabled){background-color:var(--color-neutral-500)}.btn--outline{background-color:transparent;color:var(--color-text);border:1px solid var(--color-border-primary)}.btn--outline:hover:not(:disabled){background-color:var(--color-brand-primary-800);color:var(--color-white)}.btn--outline:active:not(:disabled){background-color:var(--color-brand-primary-900);color:var(--color-white)}.btn--danger{background-color:transparent;color:var(--text-text-error-primary);border:1px solid var(--text-text-error-primary)}.btn--danger:hover:not(:disabled){background-color:var(--color-red-100)}.btn--danger:active:not(:disabled){background-color:var(--color-red-200)}.btn--link{background:none;color:var(--Border-border-success);text-decoration:underline;border:none;height:auto;padding:0;min-height:var(--size-32)}.btn--link:hover:not(:disabled){color:var(--color-primary)}.btn--link:active:not(:disabled){transform:none}.btn--text{background:none;color:var(--color-brand-primary-800);text-decoration:none;border:none;height:auto;padding:0;min-height:var(--size-32);font-weight:var(--font-weight-semibold)}.btn--text:hover:not(:disabled){color:var(--color-brand-primary-900)}.btn--text:active:not(:disabled){transform:none}.btn--black{background-color:var(--color-black);color:var(--color-white)}.btn--black:hover:not(:disabled){color:var(--color-white);background-color:var(--color-neutral-800);box-shadow:var(--shadow-md)}.btn--black:active:not(:disabled){background-color:var(--color-neutral-900);color:var(--color-white)}.btn--neutral{background-color:var(--color-neutral);color:var(--color-text-display)}.btn--neutral:hover:not(:disabled){background-color:var(--color-neutral-300)}.btn--neutral:active:not(:disabled){background-color:var(--color-neutral-400)}.btn--full-width{width:100%}.btn--loading{pointer-events:none;opacity:.8}.btn--compact{height:var(--size-24);padding:0 var(--space-xs)}.btn--mini{height:var(--size-32);font-size:var(--font-size-xs);padding:0 var(--space-sm)}.btn--extra-small{height:var(--size-32);font-size:var(--font-size-xs);padding:0 var(--space-12)}.btn--small-icon-only{height:var(--size-40);font-size:var(--font-size-xs);padding:0 var(--space-10)}.btn--small{height:var(--size-40);font-size:var(--font-size-sm);padding:0 var(--space-lg)}.btn--medium{height:var(--size-52);font-size:var(--font-size-md);padding:0 var(--space-xl)}.btn--large{height:var(--size-56);font-size:var(--font-size-lg);padding:0 var(--space-2xl)}.btn:disabled:not(.btn--loading){opacity:.45;cursor:not-allowed}.btn__spinner{display:inline-block;width:var(--size-18);height:var(--size-18);border:var(--space-2) solid var(--color-white-overlay-30);border-block-start-color:currentColor;border-radius:var(--radius-full);animation:spin .6s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}\n"] }]
|
|
4992
5069
|
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], iconPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconPosition", required: false }] }], iconSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconSize", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], routerLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "routerLink", required: false }] }], href: [{ type: i0.Input, args: [{ isSignal: true, alias: "href", required: false }] }] } });
|
|
4993
5070
|
|
|
5071
|
+
/** Labelled checkbox implementing `ControlValueAccessor`, so it works with `formControl`/`ngModel` as well as the `changed` output. */
|
|
4994
5072
|
class SceCheckbox {
|
|
4995
5073
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
4996
5074
|
inputId = input(undefined, ...(ngDevMode ? [{ debugName: "inputId" }] : /* istanbul ignore next */ []));
|
|
@@ -5041,6 +5119,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
5041
5119
|
args: ['class.disabled']
|
|
5042
5120
|
}], changed: [{ type: i0.Output, args: ["changed"] }] } });
|
|
5043
5121
|
|
|
5122
|
+
/** Wraps projected content in a PrimeNG tooltip with the required `text` and a configurable position and z-index. */
|
|
5044
5123
|
class SceTooltip {
|
|
5045
5124
|
text = input.required(...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []));
|
|
5046
5125
|
position = input('top', ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
|
|
@@ -5055,6 +5134,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
5055
5134
|
args: [{ host: { class: 'sce-tooltip' }, selector: 'sce-tooltip', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [Tooltip], template: "<span\n class=\"sce-tooltip__trigger\"\n [pTooltip]=\"text()\"\n [tooltipPosition]=\"position()\"\n [tooltipDisabled]=\"disabled()\"\n appendTo=\"body\"\n [tooltipZIndex]=\"zIndex()\"\n>\n <ng-content />\n</span>\n", styles: [":host{display:block;display:inline-block}.sce-tooltip__trigger{display:inline-block}\n"] }]
|
|
5056
5135
|
}], propDecorators: { text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: true }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], zIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "zIndex", required: false }] }] } });
|
|
5057
5136
|
|
|
5137
|
+
/** Linear progress bar whose fill direction follows the app locale, with an optional label and a leading thumb that is on by default. */
|
|
5058
5138
|
class SceProgressBar {
|
|
5059
5139
|
languageService = inject(LanguageService);
|
|
5060
5140
|
/** Matches app language: Arabic -> rtl (fill from the right), English -> ltr (fill from the left). */
|
|
@@ -5080,6 +5160,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
5080
5160
|
args: [{ host: { class: 'sce-progress-bar' }, selector: 'sce-progress-bar', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"progress-bar\"\n [attr.dir]=\"barDir()\"\n [attr.aria-valuenow]=\"progress()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"max()\"\n [attr.aria-label]=\"ariaLabel() || percentage() + '%'\"\n role=\"progressbar\"\n>\n <div class=\"progress-bar__track\">\n <div class=\"progress-bar__fill\" [style.width.%]=\"percentage()\" [style.background]=\"color()\"></div>\n </div>\n @if (showThumb()) {\n <span\n class=\"progress-bar__thumb\"\n [style.--progress-bar-thumb-position]=\"percentage() + '%'\"\n [style.background]=\"color()\"\n aria-hidden=\"true\"\n ></span>\n }\n @if (showLabel()) {\n <span class=\"progress-bar__label\">{{ roundedPercentage() }}%</span>\n }\n</div>\n", styles: [":host.sce-progress-bar{display:block}.progress-bar{--progress-bar-thumb-size: var(--size-18);position:relative;display:flex;align-items:center;width:100%;min-height:var(--progress-bar-thumb-size);overflow:visible}.progress-bar__track{width:100%;height:var(--progress-bar-height, var(--size-8));background:var(--color-progress-bar-bg);border-radius:var(--rail-radius)}.progress-bar__fill{height:100%;background:var(--color-primary);border-radius:var(--rail-radius);transition:width .3s ease}.progress-bar__thumb{position:absolute;top:50%;width:var(--progress-bar-thumb-size);height:var(--progress-bar-thumb-size);border-radius:var(--radius-full);background:var(--color-primary);transform:translate(-50%,-50%);transition:inset-inline-start .3s ease,background .2s ease;pointer-events:none;inset-inline-start:var(--progress-bar-thumb-position, 0%)}[dir=rtl] .progress-bar__thumb{margin-inline-start:-var(--space-15,var(--space-15))}.progress-bar__label{position:absolute;top:calc(-1 * var(--space-24));inset-inline-end:0;font-size:var(--font-size-sm);color:var(--color-text-secondary);font-weight:var(--font-weight-medium)}\n"] }]
|
|
5081
5161
|
}], propDecorators: { progress: [{ type: i0.Input, args: [{ isSignal: true, alias: "progress", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], showLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLabel", required: false }] }], showThumb: [{ type: i0.Input, args: [{ isSignal: true, alias: "showThumb", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
|
|
5082
5162
|
|
|
5163
|
+
/** SVG ring showing step progress (current of total) with an optional custom label, falling back to the COMMON.STEP_OF translation. */
|
|
5083
5164
|
class SceCircularProgress {
|
|
5084
5165
|
/** Current step (1-based). */
|
|
5085
5166
|
current = input(1, ...(ngDevMode ? [{ debugName: "current" }] : /* istanbul ignore next */ []));
|
|
@@ -5128,6 +5209,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
5128
5209
|
args: [{ host: { class: 'sce-circular-progress' }, selector: 'sce-circular-progress', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"circular-progress\"\n [style.width.px]=\"size()\"\n [style.height.px]=\"size()\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"current()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"total()\"\n [attr.aria-label]=\"displayLabel()\"\n>\n <svg class=\"circular-progress__svg\" [attr.viewBox]=\"viewBox()\" [attr.width]=\"size()\" [attr.height]=\"size()\">\n <!-- Background track -->\n <circle\n class=\"circular-progress__track\"\n [attr.cx]=\"center()\"\n [attr.cy]=\"center()\"\n [attr.r]=\"radius()\"\n [attr.stroke-width]=\"strokeWidth()\"\n [attr.stroke]=\"trackColor()\"\n fill=\"none\"\n />\n <!-- Progress segment (clockwise from top) -->\n <circle\n class=\"circular-progress__fill\"\n [attr.cx]=\"center()\"\n [attr.cy]=\"center()\"\n [attr.r]=\"radius()\"\n [attr.stroke-width]=\"strokeWidth()\"\n [attr.stroke]=\"progressColor()\"\n fill=\"none\"\n [attr.stroke-dasharray]=\"circumference()\"\n [attr.stroke-dashoffset]=\"strokeDashOffset()\"\n [attr.transform]=\"'rotate(-90 ' + center() + ' ' + center() + ')'\"\n />\n </svg>\n <span class=\"circular-progress__label\" [style.font-size.px]=\"labelFontSize()\">\n @if (label()) {\n {{ displayLabel() }}\n } @else {\n {{ 'COMMON.STEP_OF' | translate: stepOfParams() }}\n }\n </span>\n</div>\n", styles: [":host{display:inline-flex}.circular-progress{position:relative;display:flex;align-items:center;justify-content:center}.circular-progress__svg{display:block}.circular-progress__track{transition:stroke .2s}.circular-progress__fill{transition:stroke-dashoffset .3s ease}.circular-progress__label{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-weight:var(--font-weight-semibold);color:var(--color-text-display);line-height:1;text-align:center}\n"] }]
|
|
5129
5210
|
}], propDecorators: { current: [{ type: i0.Input, args: [{ isSignal: true, alias: "current", required: false }] }], total: [{ type: i0.Input, args: [{ isSignal: true, alias: "total", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], strokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "strokeWidth", required: false }] }], progressColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "progressColor", required: false }] }], trackColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackColor", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
|
|
5130
5211
|
|
|
5212
|
+
/** Form field label with optional sub-text and a required-marker; `text` is a required input. */
|
|
5131
5213
|
class SceFormLabel {
|
|
5132
5214
|
text = input.required(...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []));
|
|
5133
5215
|
subText = input(...(ngDevMode ? [undefined, { debugName: "subText" }] : /* istanbul ignore next */ []));
|
|
@@ -5140,6 +5222,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
5140
5222
|
args: [{ host: { class: 'sce-form-label' }, selector: 'sce-form-label', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (text()) {\n <span class=\"form-label\">\n {{ text() }}\n @if (required()) {\n <span class=\"form-label__required\">*</span>\n }\n </span>\n}\n@if (subText()) {\n <span class=\"form-label__sub text-secondary\">{{ subText() }}</span>\n}\n", styles: [":host{display:block}.form-label{display:block;font-size:var(--label-font-size, var(--font-size-sm));font-weight:var(--label-font-weight, var(--font-weight-medium));color:var(--label-color, var(--Form-field-text-label));margin-block-end:var(--space-sm)}.form-label__required{color:var(--color-danger);margin-inline-start:var(--space-xs)}.form-label__sub{display:block;font-size:var(--font-size-md);font-weight:var(--font-weight-regular);margin-block-end:var(--space-sm)}.text-secondary{color:var(--text-secondary-paragraph)}\n"] }]
|
|
5141
5223
|
}], propDecorators: { text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: true }] }], subText: [{ type: i0.Input, args: [{ isSignal: true, alias: "subText", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }] } });
|
|
5142
5224
|
|
|
5225
|
+
/** Inline form validation message rendered from a translation key; both `show` and `messageKey` are required inputs. */
|
|
5143
5226
|
class SceFormError {
|
|
5144
5227
|
show = input.required(...(ngDevMode ? [{ debugName: "show" }] : /* istanbul ignore next */ []));
|
|
5145
5228
|
messageKey = input.required(...(ngDevMode ? [{ debugName: "messageKey" }] : /* istanbul ignore next */ []));
|
|
@@ -5172,6 +5255,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
5172
5255
|
* React source: layout/scroll-to-top-button/scroll-to-top-button.tsx
|
|
5173
5256
|
*/
|
|
5174
5257
|
const SCROLL_THRESHOLD = 280;
|
|
5258
|
+
/** Floating button that appears once the window is scrolled past 280px and scrolls back to the top, using an instant jump when `prefers-reduced-motion` is set. */
|
|
5175
5259
|
class SceScrollToTopButtonComponent {
|
|
5176
5260
|
translate = inject(TranslateService);
|
|
5177
5261
|
ariaLabelOverride = input('', ...(ngDevMode ? [{ debugName: "ariaLabelOverride" }] : /* istanbul ignore next */ []));
|
|
@@ -5208,6 +5292,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
5208
5292
|
args: [{ host: { class: 'sce-scroll-to-top-button' }, selector: 'sce-scroll-to-top-button', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<button\n type=\"button\"\n class=\"button\"\n [attr.data-visible]=\"visible() ? 'true' : 'false'\"\n (click)=\"scrollToTop()\"\n [attr.aria-label]=\"ariaLabel()\"\n>\n <svg class=\"icon\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path\n fill-rule=\"evenodd\"\n clip-rule=\"evenodd\"\n d=\"M18.5293 13.0298L11.999 19.5601L5.46875 13.0298L6.5293 11.9692L11.999 17.439L17.4688 11.9692L18.5293 13.0298ZM18.5293 6.02979L11.999 12.5601L5.46875 6.02979L6.5293 4.96924L11.999 10.439L17.4688 4.96924L18.5293 6.02979Z\"\n fill=\"currentColor\"\n />\n </svg>\n</button>\n", styles: ["@charset \"UTF-8\";.button{position:fixed;z-index:45;inset-inline-end:max(1rem,env(safe-area-inset-right,0px));bottom:max(5.5rem,1rem + env(safe-area-inset-bottom,0px));width:var(--space-44);height:var(--space-44);border:0;border-radius:var(--radius-full);background:var(--color-brand-primary-800);color:var(--text-on-brand-highlight, var(--background-bg-primary));cursor:pointer;display:inline-flex;align-items:center;justify-content:center;box-shadow:0 8px 24px #00344947;opacity:0;visibility:hidden;pointer-events:none;transform:translateY(.5rem);transition:opacity .25s ease,visibility .25s ease,transform .25s ease,background-color .2s ease}.button[data-visible=true]{opacity:1;visibility:visible;pointer-events:auto;transform:translateY(0)}.button:hover,.button:focus-visible{background:var(--color-brand-primary-700);outline:none}.icon{transform:rotate(180deg)}.icon :where(path,circle,rect,line,polyline,polygon){fill:currentColor}\n"] }]
|
|
5209
5293
|
}], propDecorators: { ariaLabelOverride: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelOverride", required: false }] }] } });
|
|
5210
5294
|
|
|
5295
|
+
/** Full-screen image lightbox with prev/next navigation, arrow-key and Escape handling and body-scroll locking; supplying `activeIndex` switches it from self-managed to parent-controlled paging. */
|
|
5211
5296
|
class SceImageGallerySwapperComponent {
|
|
5212
5297
|
open = input(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
5213
5298
|
images = input([], ...(ngDevMode ? [{ debugName: "images" }] : /* istanbul ignore next */ []));
|
|
@@ -5319,6 +5404,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
5319
5404
|
args: [{ host: { class: 'sce-image-gallery-swapper' }, selector: 'sce-image-gallery-swapper', standalone: true, imports: [TranslatePipe], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (open() && total()) {\n <div class=\"overlay\" [dir]=\"dir()\" role=\"dialog\" aria-modal=\"true\" [attr.aria-label]=\"dialogLabel()\">\n <header class=\"header\">\n <button type=\"button\" class=\"closeButton\" (click)=\"onClose()\" [attr.aria-label]=\"'common.close' | translate\">\n <span class=\"closeIcon\" aria-hidden=\"true\">\u00D7</span>\n </button>\n <div class=\"titleBlock\">\n @if (title()?.trim()) {\n <h2 class=\"title\">{{ title() }}</h2>\n }\n <p class=\"counter\">{{ counter() }}</p>\n </div>\n </header>\n\n <div class=\"stage\">\n @if (closeOnBackdropClick()) {\n <button\n type=\"button\"\n class=\"backdropClick\"\n [attr.aria-label]=\"'common.close' | translate\"\n (click)=\"onClose()\"\n tabindex=\"-1\"\n ></button>\n }\n\n @if (showNav()) {\n <button type=\"button\" class=\"navButton navPrev\" (click)=\"prev()\" [attr.aria-label]=\"'gallery.previousImage' | translate\">\n <span class=\"navIcon\" aria-hidden=\"true\">\u2039</span>\n </button>\n }\n\n <div class=\"mainImageWrap\">\n <img [src]=\"current().src\" [alt]=\"current().alt ?? title() ?? ''\" class=\"mainImage\" draggable=\"false\" />\n </div>\n\n @if (showNav()) {\n <button type=\"button\" class=\"navButton navNext\" (click)=\"next()\" [attr.aria-label]=\"'gallery.nextImage' | translate\">\n <span class=\"navIcon\" aria-hidden=\"true\">\u203A</span>\n </button>\n }\n </div>\n\n @if (showNav()) {\n <div class=\"thumbs\" role=\"tablist\" [attr.aria-label]=\"'gallery.thumbnails' | translate\">\n @for (item of items(); track item.src + '-' + $index) {\n <button\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"$index === currentIndex()\"\n [attr.aria-label]=\"('gallery.imageNumber' | translate) + ' ' + ($index + 1)\"\n [class]=\"'thumbButton' + ($index === currentIndex() ? ' thumbActive' : '')\"\n (click)=\"setIndex($index)\"\n >\n <img [src]=\"item.src\" alt=\"\" class=\"thumbImage\" draggable=\"false\" />\n </button>\n }\n </div>\n }\n </div>\n}\n", styles: ["@charset \"UTF-8\";.overlay{position:fixed;inset:0;z-index:1100;display:flex;flex-direction:column;background:var(--color-fg);color:var(--color-base-white)}.header{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-16);padding:var(--space-20) var(--space-24) .75rem;flex-shrink:0;flex-direction:row-reverse}.titleBlock{display:flex;flex-direction:column;align-items:flex-end;gap:var(--space-4);min-width:0;text-align:end}.title{margin:0;font-size:var(--font-size-lg-18);font-weight:700;line-height:1.35;color:var(--color-base-white)}.counter{margin:0;font-size:var(--font-size-md);color:var(--color-muted-fg)}.closeButton{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:var(--space-40);height:var(--space-40);border:none;border-radius:var(--radius-pill);background:var(--surface-on-brand-soft);color:var(--color-base-white);cursor:pointer;transition:background .15s ease}.closeButton:hover{background:var(--surface-on-brand-strong)}.closeIcon{font-size:var(--space-20);line-height:1}.stage{position:relative;flex:1;display:flex;align-items:center;justify-content:center;min-height:0;padding:var(--space-8) 4.5rem}.mainImageWrap{max-width:min(var(--size-920),100%);max-height:100%;width:100%;display:flex;align-items:center;justify-content:center}.mainImage{max-width:100%;max-height:min(72vb,var(--size-640));width:auto;height:auto;object-fit:contain;border-radius:var(--radius-14);-webkit-user-select:none;user-select:none}.navButton{position:absolute;top:50%;transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;width:var(--space-44);height:var(--space-44);border:none;border-radius:var(--radius-pill);background:var(--color-base-white);color:var(--color-fg);cursor:pointer;box-shadow:var(--shadow-image-gallery);transition:transform .15s ease,opacity .15s ease}.navButton:hover:not(:disabled){transform:translateY(-50%) scale(1.04)}.navButton:disabled{opacity:.35;cursor:not-allowed}.navPrev{inset-inline-start:var(--space-20)}.navNext{inset-inline-end:var(--space-20)}.navIcon{font-size:var(--font-size-lg-18);line-height:1;font-weight:700}html[dir=rtl] .navIcon{display:inline-block;transform:scaleX(-1)}.thumbs{flex-shrink:0;display:flex;align-items:center;justify-content:center;gap:.65rem;padding:var(--space-16) var(--space-24) var(--space-24);overflow-x:auto}.thumbButton{flex-shrink:0;padding:0;border:2px solid transparent;border-radius:var(--radius-10);background:transparent;cursor:pointer;opacity:.55;transition:opacity .15s ease,border-color .15s ease}.thumbButton:hover{opacity:.85}.thumbActive{border-color:var(--color-base-white);opacity:1}.thumbImage{display:block;width:var(--space-72);height:var(--space-52, var(--size-52));object-fit:cover;border-radius:var(--radius-lg)}.backdropClick{position:absolute;inset:0;z-index:-1}@media(max-width:640px){.stage{padding:var(--space-8) 3.25rem}.navButton{width:2.25rem;height:2.25rem}.thumbImage{width:var(--space-56);height:var(--space-42, var(--size-42))}}\n"] }]
|
|
5320
5405
|
}], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], images: [{ type: i0.Input, args: [{ isSignal: true, alias: "images", required: false }] }], activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }], initialIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialIndex", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], closeOnBackdropClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdropClick", required: false }] }], close: [{ type: i0.Output, args: ["close"] }], activeIndexChange: [{ type: i0.Output, args: ["activeIndexChange"] }] } });
|
|
5321
5406
|
|
|
5407
|
+
/** Thumbnail grid of an office project's images that opens `sce-image-gallery-swapper` at the clicked index; `imageUrls` and `title` are required. */
|
|
5322
5408
|
class SceOfficeProjectGalleryComponent {
|
|
5323
5409
|
imageUrls = input.required(...(ngDevMode ? [{ debugName: "imageUrls" }] : /* istanbul ignore next */ []));
|
|
5324
5410
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
@@ -5352,6 +5438,7 @@ var officeProjectGallery_component = /*#__PURE__*/Object.freeze({
|
|
|
5352
5438
|
/**
|
|
5353
5439
|
* React source: feedback/async-page-gate.tsx
|
|
5354
5440
|
*/
|
|
5441
|
+
/** Wraps a page in its loading/error/ready states, showing a skeleton variant while loading and a `sce-result-state` on failure; with the default `recovery` it emits `reloadRequested` and calls `Location.back()` itself. */
|
|
5355
5442
|
class SceAsyncPageGateComponent {
|
|
5356
5443
|
translate = inject(TranslateService);
|
|
5357
5444
|
location = inject(Location);
|
|
@@ -5438,6 +5525,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
5438
5525
|
args: [{ selector: 'sce-offline-banner', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-offline-banner' }, template: "@if (visible()) {\n <div class=\"sce-offline-banner__bar\" role=\"alert\">\n <i class=\"pi pi-wifi sce-offline-banner__icon\" aria-hidden=\"true\"></i>\n <span class=\"sce-offline-banner__text\">\n {{ 'STATUS_PAGES.STATES.NETWORK_OFFLINE.TITLE' | translate }} \u2014\n {{ 'STATUS_PAGES.STATES.NETWORK_OFFLINE.SUBTITLE' | translate }}\n </span>\n </div>\n}\n", styles: [":host{display:block}.sce-offline-banner__bar{position:sticky;inset-block-start:0;z-index:var(--z-index-banner, 1000);display:flex;align-items:center;justify-content:center;gap:var(--space-8);padding:var(--space-8) var(--space-16);background:var(--color-warning-100, var(--color-surface-secondary));color:var(--color-warning-900, var(--color-text-default));border-block-end:var(--border-width-1) solid var(--color-warning-300, var(--color-border-subtle));font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);text-align:center}.sce-offline-banner__icon{font-size:var(--font-size-md);flex-shrink:0}.sce-offline-banner__text{min-width:0}\n"] }]
|
|
5439
5526
|
}], propDecorators: { forceVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "forceVisible", required: false }] }] } });
|
|
5440
5527
|
|
|
5528
|
+
/** Radio group rendering a required list of options with optional descriptions, where a parent can veto a selection through the `onBeforeChange` guard input. */
|
|
5441
5529
|
class SceRadioButtonComponent {
|
|
5442
5530
|
options = input.required(...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
5443
5531
|
value = input(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
@@ -5466,6 +5554,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
5466
5554
|
args: [{ host: { class: 'sce-radio-button' }, selector: 'sce-radio-button', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "@if (title()) {\n <h3 class=\"radioGroupTitle\" [id]=\"groupTitleId\">{{ title() }}</h3>\n}\n\n<div class=\"radioGroupGrid\" role=\"radiogroup\" [attr.aria-labelledby]=\"title() ? groupTitleId : null\">\n @for (item of options(); track item.value) {\n <div\n class=\"radioCard\"\n [class.radioCardChecked]=\"value() === item.value\"\n [class.radioCardDisabled]=\"disabled()\"\n role=\"radio\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n [attr.aria-checked]=\"value() === item.value\"\n [attr.aria-disabled]=\"disabled()\"\n (click)=\"tryChange(item.value)\"\n (keydown.enter)=\"tryChange(item.value)\"\n (keydown.space)=\"tryChange(item.value)\"\n >\n <span class=\"radioCircle\" [class.radioCircleChecked]=\"value() === item.value\">\n @if (value() === item.value) {\n <span class=\"radioCircleDot\"></span>\n }\n </span>\n <span class=\"radioContent\">\n <span class=\"radioLabel\" [class.radioLabelChecked]=\"value() === item.value\">\n {{ item.label }}\n </span>\n @if (item.description) {\n <p class=\"radioDescription\">{{ item.description }}</p>\n }\n </span>\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";.radioGroupTitle{margin:0 0 var(--space-12, var(--space-12));text-align:start;font-size:var(--font-size-md);font-weight:600}.radioGroupGrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12)}.radioCard{display:flex;align-items:center;gap:var(--space-12);border-radius:var(--radius-xl);border:1px solid var(--color-neutral-200);background:var(--color-surface);padding:var(--space-12) var(--space-16);cursor:pointer;transition:border-color .2s,box-shadow .2s}.radioCard:hover:not(.radioCardDisabled){border-color:var(--color-neutral-300)}.radioCardChecked{border-color:var(--color-success-500)}.radioCardDisabled{opacity:.6;cursor:not-allowed}.radioCircle{display:flex;align-items:center;justify-content:center;width:var(--space-20);height:var(--space-20);flex-shrink:0;border-radius:var(--radius-full);border:2px solid var(--color-neutral-400);transition:border-color .2s}.radioCircleChecked{border-color:var(--color-success-500)}.radioCircleDot{width:var(--space-10);height:var(--space-10);border-radius:var(--radius-full);background-color:var(--color-success-500)}.radioContent{flex:1;text-align:start}.radioLabel{display:block;font-size:var(--font-size-md);font-weight:500;color:var(--color-neutral-400)}.radioLabelChecked{color:var(--text-text-primary-900)}.radioDescription{margin:var(--space-4) 0 0;font-size:var(--font-size-xs);color:var(--form-field-text-placeholder)}\n"] }]
|
|
5467
5555
|
}], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], onBeforeChange: [{ type: i0.Input, args: [{ isSignal: true, alias: "onBeforeChange", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
|
|
5468
5556
|
|
|
5557
|
+
/** Dashboard shell that projects a sidebar, header, and main content into a grid; `sidebarCollapsed` narrows the sidebar column, and it uses `ViewEncapsulation.None`. */
|
|
5469
5558
|
class SceDashboardLayoutComponent {
|
|
5470
5559
|
sidebarCollapsed = input(false, ...(ngDevMode ? [{ debugName: "sidebarCollapsed" }] : /* istanbul ignore next */ []));
|
|
5471
5560
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SceDashboardLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -5476,6 +5565,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
5476
5565
|
args: [{ host: { class: 'sce-dashboard-layout' }, selector: 'sce-dashboard-layout', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-dashboard-layout\" [class.sce-dashboard-layout--collapsed]=\"sidebarCollapsed()\">\n <aside class=\"sce-dashboard-layout__sidebar\">\n <ng-content select=\"[sidebar]\" />\n </aside>\n <div class=\"sce-dashboard-layout__main\">\n <header class=\"sce-dashboard-layout__header\">\n <ng-content select=\"[header]\" />\n </header>\n <main class=\"sce-dashboard-layout__content\">\n <ng-content />\n </main>\n </div>\n</div>\n", styles: [".sce-dashboard-layout{display:flex;min-height:100vb}.sce-dashboard-layout__sidebar{width:var(--size-260);flex-shrink:0;background:var(--sce-sidebar-bg, var(--sce-bg));border-inline-end:1px solid var(--sce-border);transition:width .3s ease}.sce-dashboard-layout--collapsed .sce-dashboard-layout__sidebar{width:var(--space-64)}.sce-dashboard-layout__main{flex:1;display:flex;flex-direction:column;min-width:0}.sce-dashboard-layout__header{height:var(--space-64);display:flex;align-items:center;padding:0 var(--space-24);background:var(--sce-bg);border-block-end:1px solid var(--sce-border)}.sce-dashboard-layout__content{flex:1;padding:var(--space-24);overflow-y:auto}\n"] }]
|
|
5477
5566
|
}], propDecorators: { sidebarCollapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarCollapsed", required: false }] }] } });
|
|
5478
5567
|
|
|
5568
|
+
/** Page shell for a form: `title`/`subtitle` header, a projected form body, and an action footer; it owns the `<form>` element and re-emits its submit as `submitted`, and uses `ViewEncapsulation.None`. */
|
|
5479
5569
|
class SceFormPageLayoutComponent {
|
|
5480
5570
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
5481
5571
|
subtitle = input(...(ngDevMode ? [undefined, { debugName: "subtitle" }] : /* istanbul ignore next */ []));
|
|
@@ -5488,6 +5578,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
5488
5578
|
args: [{ host: { class: 'sce-form-page-layout' }, selector: 'sce-form-page-layout', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-form-page-layout\">\n <header class=\"sce-form-page-layout__header\">\n <h1 class=\"sce-form-page-layout__title\">{{ title() }}</h1>\n @if (subtitle(); as sub) {\n <p class=\"sce-form-page-layout__subtitle\">{{ sub }}</p>\n }\n </header>\n <div class=\"sce-form-page-layout__body\">\n <ng-content />\n </div>\n <footer class=\"sce-form-page-layout__footer\">\n <ng-content select=\"[actions]\" />\n </footer>\n</div>\n", styles: [".sce-form-page-layout{max-width:var(--size-800);margin:0 auto}.sce-form-page-layout__header{margin-block-end:var(--space-32)}.sce-form-page-layout__title{font-size:var(--space-24);font-weight:600;color:var(--sce-text-primary)}.sce-form-page-layout__subtitle{margin-block-start:var(--space-8);font-size:var(--font-size-md);color:var(--sce-text-secondary)}.sce-form-page-layout__body{display:flex;flex-direction:column;gap:var(--space-24)}.sce-form-page-layout__footer{margin-block-start:var(--space-32);display:flex;justify-content:flex-end;gap:var(--space-12);padding-block-start:var(--space-24);border-block-start:1px solid var(--sce-border)}\n"] }]
|
|
5489
5579
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], submitted: [{ type: i0.Output, args: ["submitted"] }] } });
|
|
5490
5580
|
|
|
5581
|
+
/** Page shell for a list/table screen: `title` header plus projected filter, toolbar, and content slots; `showFilters` defaults to true, and it uses `ViewEncapsulation.None`. */
|
|
5491
5582
|
class SceListPageLayoutComponent {
|
|
5492
5583
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
5493
5584
|
showFilters = input(true, ...(ngDevMode ? [{ debugName: "showFilters" }] : /* istanbul ignore next */ []));
|
|
@@ -5510,6 +5601,7 @@ function truncateWords(text, maxWords) {
|
|
|
5510
5601
|
}
|
|
5511
5602
|
return `${words.slice(0, maxWords).join(' ')}...`;
|
|
5512
5603
|
}
|
|
5604
|
+
/** Header trigger plus popover listing the user's accounts, emitting select/enter-dashboard/logout; requires `selectedAccountId`. */
|
|
5513
5605
|
class SceAccountSwitcherComponent {
|
|
5514
5606
|
language = inject(LanguageService);
|
|
5515
5607
|
elRef = inject(ElementRef);
|
|
@@ -5758,6 +5850,7 @@ function placePopover(spotlight, popoverSize) {
|
|
|
5758
5850
|
const left = Math.min(maxLeft, Math.max(VIEWPORT_PAD, centeredLeft));
|
|
5759
5851
|
return { top, left };
|
|
5760
5852
|
}
|
|
5853
|
+
/** Guided product tour overlay that scrolls to and spotlights each step's target selector and positions a popover beside it, emitting `complete` on the last step and `skip` on Escape. */
|
|
5761
5854
|
class SceGuidedTourComponent {
|
|
5762
5855
|
platformId = inject(PLATFORM_ID);
|
|
5763
5856
|
locale = input('ar', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
|
|
@@ -5873,6 +5966,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
5873
5966
|
args: [{ host: { class: 'sce-guided-tour' }, selector: 'sce-guided-tour', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "@if (active() && currentStep()) {\n <div class=\"root\" [attr.data-locale]=\"locale()\" role=\"presentation\">\n <button type=\"button\" class=\"backdrop\" [attr.aria-label]=\"'landing.tour.skip' | translate\" (click)=\"skip.emit()\"></button>\n\n @if (spotlight()) {\n <div\n class=\"spotlight\"\n [style.top.px]=\"spotlight()!.top\"\n [style.left.px]=\"spotlight()!.left\"\n [style.width.px]=\"spotlight()!.width\"\n [style.height.px]=\"spotlight()!.height\"\n ></div>\n }\n\n <div\n #popoverEl\n class=\"popover\"\n [style.top.px]=\"popoverPos()?.top\"\n [style.left.px]=\"popoverPos()?.left\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"guided-tour-title\"\n aria-describedby=\"guided-tour-body\"\n >\n <h3 class=\"popoverTitle\" id=\"guided-tour-title\">\n {{ currentStep()!.titleKey | translate }}\n </h3>\n <p class=\"popoverBody\" id=\"guided-tour-body\">\n {{ currentStep()!.bodyKey | translate }}\n </p>\n <p class=\"popoverMeta\">\n {{ 'landing.tour.stepOf' | translate: { current: stepIndex() + 1, total: steps().length } }}\n </p>\n\n <div class=\"popoverActions\">\n <button type=\"button\" class=\"skipButton\" (click)=\"skip.emit()\">\n {{ 'landing.tour.skip' | translate }}\n </button>\n <div class=\"popoverActionsEnd\">\n @if (stepIndex() > 0) {\n <button type=\"button\" class=\"backButton\" (click)=\"goBack()\">\n {{ 'landing.tour.back' | translate }}\n </button>\n }\n <button type=\"button\" class=\"nextButton\" (click)=\"goNext()\">\n {{ (isLastStep() ? 'landing.tour.finish' : 'landing.tour.next') | translate }}\n </button>\n </div>\n </div>\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";.root{position:fixed;inset:0;z-index:10000;pointer-events:none}.backdrop{position:fixed;inset:0;background:#0818206b;pointer-events:auto;animation:tourFadeIn .35s ease both}.spotlight{position:fixed;border-radius:var(--radius-lg);box-shadow:0 0 0 9999px #0818209e;border:2px solid var(--color-brand-secondary-500, var(--color-brand-secondary-500));pointer-events:none;transition:top .45s cubic-bezier(.22,1,.36,1),left .45s cubic-bezier(.22,1,.36,1),width .45s cubic-bezier(.22,1,.36,1),height .45s cubic-bezier(.22,1,.36,1);animation:tourPulse 2.4s ease-in-out infinite}.popover{position:fixed;width:min(22rem,100vi - 2rem);padding:var(--space-20) var(--space-20) 1rem;border-radius:var(--radius-lg);background:var(--color-base-white, var(--background-bg-primary));color:var(--text-primary-emphasis);box-shadow:0 18px 48px #00000038;pointer-events:auto;animation:tourFadeUp .35s ease both}.popoverTitle{margin:0;font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-lg, 1.125rem);font-weight:var(--font-weight-bold, 700);line-height:1.4}.popoverBody{margin:var(--space-8) 0 0;font-family:var(--font-almarai),var(--font-family-arabic-secondary),Arial,sans-serif;font-size:var(--font-size-md, 1rem);line-height:1.65;color:var(--text-primary-muted)}.popoverMeta{margin:.85rem 0 0;font-size:var(--font-size-sm, .875rem);color:var(--color-brand-primary-600)}.popoverActions{display:flex;align-items:center;justify-content:space-between;gap:var(--space-12);margin-block-start:var(--space-16)}.popoverActionsEnd{display:flex;align-items:center;gap:var(--space-8)}.skipButton,.backButton{appearance:none;border:0;background:transparent;padding:.35rem .5rem;font-family:inherit;font-size:var(--font-size-sm, .875rem);color:var(--text-primary-muted);cursor:pointer}.skipButton:hover,.backButton:hover{color:var(--text-primary-emphasis)}.nextButton{appearance:none;border:0;border-radius:var(--radius-lg);padding:.55rem 1rem;background:var(--color-brand-secondary-600, var(--color-brand-secondary-600));color:var(--text-on-brand-primary, var(--background-bg-primary));font-family:inherit;font-size:var(--font-size-sm, .875rem);font-weight:var(--font-weight-semibold, 600);cursor:pointer}.nextButton:hover{background:var(--color-brand-secondary-700)}.root[data-locale=en] .popoverTitle,.root[data-locale=en] .popoverBody,.root[data-locale=en] .popoverMeta,.root[data-locale=en] .skipButton,.root[data-locale=en] .backButton,.root[data-locale=en] .nextButton{font-family:var(--font-geist-sans),Arial,sans-serif}@keyframes tourFadeIn{0%{opacity:0}to{opacity:1}}@keyframes tourFadeUp{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@keyframes tourPulse{0%,to{box-shadow:0 0 0 9999px #0818209e,0 0 #2fcdc200}50%{box-shadow:0 0 0 9999px #0818209e,0 0 0 4px #2fcdc259}}@media(prefers-reduced-motion:reduce){.backdrop,.popover{animation:none}.spotlight{animation:none;transition:none}}\n"] }]
|
|
5874
5967
|
}], ctorParameters: () => [], propDecorators: { locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], tourId: [{ type: i0.Input, args: [{ isSignal: true, alias: "tourId", required: false }] }], steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: true }] }], active: [{ type: i0.Input, args: [{ isSignal: true, alias: "active", required: false }] }], complete: [{ type: i0.Output, args: ["complete"] }], skip: [{ type: i0.Output, args: ["skip"] }], popoverElRef: [{ type: i0.ViewChild, args: ['popoverEl', { isSignal: true }] }] } });
|
|
5875
5968
|
|
|
5969
|
+
/** Dialog that lets the user crop, zoom and rotate a profile photo and emits the result as a JPEG `File`; binding the `applying` input keeps the dialog open for an async upload instead of auto-closing on apply. */
|
|
5876
5970
|
class SceProfilePhotoEditDialogComponent {
|
|
5877
5971
|
translate = inject(TranslateService);
|
|
5878
5972
|
visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
@@ -6067,6 +6161,7 @@ const DEFAULT_CENTER = isGeoLookupRestricted()
|
|
|
6067
6161
|
? [JEDDAH_MAP_CENTER.lat, JEDDAH_MAP_CENTER.lng]
|
|
6068
6162
|
: [24.7136, 46.6753];
|
|
6069
6163
|
const DEFAULT_ZOOM = 6;
|
|
6164
|
+
/** Modal Leaflet map dialog for picking a coordinate, bounded to Saudi Arabia, which validates each click or marker drag, reverse-geocodes the position to an address via Nominatim, and reverts to the last valid point when validation fails. */
|
|
6070
6165
|
class SceLocationPickerDialogComponent {
|
|
6071
6166
|
visible = input(false, ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
6072
6167
|
locale = input('ar', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
|
|
@@ -6241,6 +6336,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
6241
6336
|
args: [{ host: { class: 'sce-location-picker-dialog' }, selector: 'sce-location-picker-dialog', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "@if (visible()) {\n <!-- Click-outside-to-dismiss backdrop. Keyboard users dismiss via the labelled close button\n below, so a key handler here would be cargo-cult, not accessibility. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div class=\"sce-location-picker-overlay\" (click)=\"onOverlayClick($event)\">\n <div class=\"sce-location-picker-dialog\">\n <div class=\"sce-location-picker-dialog__header\">\n <h3>{{ 'GEO.PICKER_TITLE' | translate }}</h3>\n <button\n type=\"button\"\n class=\"sce-location-picker-dialog__close\"\n [attr.aria-label]=\"'common.close' | translate\"\n (click)=\"dialogClose.emit()\"\n >\n ×\n </button>\n </div>\n <div class=\"sce-location-picker-dialog__map\" #mapContainer></div>\n <div class=\"sce-location-picker-dialog__address\">\n @if (resolvedAddress()) {\n <span>{{ resolvedAddress() }}</span>\n } @else if (isResolving()) {\n <span>...</span>\n }\n </div>\n <div class=\"sce-location-picker-dialog__footer\">\n <button type=\"button\" class=\"sce-location-picker-dialog__cancel\" (click)=\"dialogClose.emit()\">\n {{ 'common.cancel' | translate }}\n </button>\n <button type=\"button\" class=\"sce-location-picker-dialog__confirm\" [disabled]=\"!selectedLat()\" (click)=\"confirmLocation()\">\n {{ 'GEO.CONFIRM_LOCATION' | translate }}\n </button>\n </div>\n </div>\n </div>\n}\n", styles: [".sce-location-picker-overlay{position:fixed;inset:0;z-index:1000;display:flex;align-items:center;justify-content:center;background:#00000080}.sce-location-picker-dialog{width:90vi;max-width:var(--size-700);background:var(--color-surface-white);border-radius:var(--radius-lg);overflow:hidden;display:flex;flex-direction:column}.sce-location-picker-dialog__header{display:flex;align-items:center;justify-content:space-between;padding:var(--space-4) var(--space-5);border-block-end:1px solid var(--color-border-light)}.sce-location-picker-dialog__header h3{font-size:var(--font-size-md);font-weight:600;margin:0}.sce-location-picker-dialog__close{background:none;border:none;font-size:var(--font-size-xl);cursor:pointer;color:var(--color-text-secondary);line-height:1}.sce-location-picker-dialog__map{height:var(--size-400);width:100%}.sce-location-picker-dialog__address{padding:var(--space-3) var(--space-5);font-size:var(--font-size-sm);color:var(--color-text-secondary);min-height:var(--space-40);display:flex;align-items:center;border-block-start:1px solid var(--color-border-light)}.sce-location-picker-dialog__footer{display:flex;justify-content:flex-end;gap:var(--space-3);padding:var(--space-4) var(--space-5);border-block-start:1px solid var(--color-border-light)}.sce-location-picker-dialog__cancel{padding:var(--space-2) var(--space-5);font-size:var(--font-size-sm);border:1px solid var(--color-border-default);border-radius:var(--radius-md);background:transparent;cursor:pointer}.sce-location-picker-dialog__confirm{padding:var(--space-2) var(--space-5);font-size:var(--font-size-sm);border:none;border-radius:var(--radius-md);background:var(--color-primary);color:var(--color-text-white);cursor:pointer}.sce-location-picker-dialog__confirm:disabled{opacity:.5;cursor:not-allowed}\n"] }]
|
|
6242
6337
|
}], ctorParameters: () => [], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], initialLat: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialLat", required: false }] }], initialLng: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialLng", required: false }] }], dialogClose: [{ type: i0.Output, args: ["dialogClose"] }], confirm: [{ type: i0.Output, args: ["confirm"] }], mapContainer: [{ type: i0.ViewChild, args: ['mapContainer', { isSignal: true }] }] } });
|
|
6243
6338
|
|
|
6339
|
+
/** Geo-location field that displays the currently selected coordinates and address and opens `sce-location-picker-dialog` to choose a new one. */
|
|
6244
6340
|
class SceGeoLocationFieldComponent {
|
|
6245
6341
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
6246
6342
|
value = input(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
@@ -6274,6 +6370,7 @@ var geoLocationField_component = /*#__PURE__*/Object.freeze({
|
|
|
6274
6370
|
SceGeoLocationFieldComponent: SceGeoLocationFieldComponent
|
|
6275
6371
|
});
|
|
6276
6372
|
|
|
6373
|
+
/** Dashboard page heading rendering a single translated `<h1>` from `titleKey`; the whole header is omitted when `titleKey` is empty. */
|
|
6277
6374
|
class DashboardPageHeaderComponent {
|
|
6278
6375
|
titleKey = input('nav.enterDashboard', ...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
|
|
6279
6376
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: DashboardPageHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -6284,6 +6381,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
6284
6381
|
args: [{ host: { class: 'sce-dashboard-page-header' }, selector: 'sce-dashboard-page-header', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (titleKey()) {\n <header class=\"pageTop\">\n <div class=\"pageTopHeading\">\n <h1 class=\"pageTopTitle\">{{ titleKey() | translate }}</h1>\n </div>\n </header>\n}\n", styles: [":host{display:block}.sce-dashboard-page-header{display:contents}\n"] }]
|
|
6285
6382
|
}], propDecorators: { titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: false }] }] } });
|
|
6286
6383
|
|
|
6384
|
+
/** OpenStreetMap Leaflet map that lazily loads Leaflet, renders the given markers and emits map clicks and marker drag-ends; setting `interactive` to false disables panning, zooming, the zoom control and click events. */
|
|
6287
6385
|
class SceOsmLeafletMapComponent {
|
|
6288
6386
|
latitude = input(24.7136, ...(ngDevMode ? [{ debugName: "latitude" }] : /* istanbul ignore next */ []));
|
|
6289
6387
|
longitude = input(46.6753, ...(ngDevMode ? [{ debugName: "longitude" }] : /* istanbul ignore next */ []));
|
|
@@ -6397,6 +6495,7 @@ function buildGoogleEmbedUrl(lat, lng, address) {
|
|
|
6397
6495
|
}
|
|
6398
6496
|
return null;
|
|
6399
6497
|
}
|
|
6498
|
+
/** Read-only map of an office's location: a Leaflet map with a marker when valid coordinates are given, a Google Maps embed built from the address when they are not, and a "not specified" fallback when neither is available. */
|
|
6400
6499
|
class SceOfficeLocationMapComponent {
|
|
6401
6500
|
sanitizer = inject(DomSanitizer);
|
|
6402
6501
|
latitude = input(...(ngDevMode ? [undefined, { debugName: "latitude" }] : /* istanbul ignore next */ []));
|
|
@@ -6470,6 +6569,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
6470
6569
|
args: ['mapContainer']
|
|
6471
6570
|
}] } });
|
|
6472
6571
|
|
|
6572
|
+
/** Location picker pairing an OSM Leaflet map with a Nominatim search box, which validates every clicked, dragged or searched position before placing a draggable pin and emitting it with its reverse-geocoded address. */
|
|
6473
6573
|
class SceOsmLocationPickerComponent {
|
|
6474
6574
|
initialLat = input(isGeoLookupRestricted() ? JEDDAH_MAP_CENTER.lat : 24.7136, ...(ngDevMode ? [{ debugName: "initialLat" }] : /* istanbul ignore next */ []));
|
|
6475
6575
|
initialLng = input(isGeoLookupRestricted() ? JEDDAH_MAP_CENTER.lng : 46.6753, ...(ngDevMode ? [{ debugName: "initialLng" }] : /* istanbul ignore next */ []));
|
|
@@ -6558,6 +6658,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
6558
6658
|
args: [{ host: { class: 'sce-osm-location-picker' }, selector: 'sce-osm-location-picker', standalone: true, imports: [FormsModule, TranslatePipe, SceSkeleton, SceOsmLeafletMapComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div>\n <div class=\"searchRow\">\n <input\n class=\"searchInput\"\n type=\"text\"\n [placeholder]=\"'MAPS.SEARCH_PLACEHOLDER' | translate\"\n [(ngModel)]=\"searchQuery\"\n (keydown.enter)=\"onSearch()\"\n />\n <button type=\"button\" class=\"searchButton\" [disabled]=\"isSearching()\" (click)=\"onSearch()\">\n @if (isSearching()) {\n <sce-skeleton variant=\"rounded\" width=\"1.25rem\" height=\"1.25rem\" animation=\"wave\" aria-hidden=\"true\" />\n } @else {\n {{ 'MAPS.SEARCH' | translate }}\n }\n </button>\n </div>\n <p class=\"providerNote\">{{ 'MAPS.PROVIDER_NOTE' | translate }}</p>\n\n <div style=\"height: 300px; margin-top: 0.75rem; border-radius: 0.75rem; overflow: hidden\">\n <sce-osm-leaflet-map\n [latitude]=\"currentLat()\"\n [longitude]=\"currentLng()\"\n [zoom]=\"zoom()\"\n [markers]=\"currentMarkers()\"\n [interactive]=\"true\"\n (mapClick)=\"onMapClick($event)\"\n (markerDragEnd)=\"onMarkerDragEnd($event)\"\n />\n </div>\n\n @if (selectedLocation()) {\n <p style=\"margin: 0.5rem 0 0; font-size: 0.8rem; color: var(--color-text-secondary)\">\n <span dir=\"ltr\">{{ selectedLocation()!.lat.toFixed(6) }}, {{ selectedLocation()!.lng.toFixed(6) }}</span>\n @if (selectedLocation()!.address) {\n \u2014 {{ selectedLocation()!.address }}\n }\n </p>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host.sce-osm-location-picker{display:block}.providerNote{margin:var(--space-4) 0 0;font-size:var(--font-size-xs);color:var(--color-neutral-500)}.searchRow{display:flex;gap:var(--space-8);align-items:stretch}.searchRow .searchInput{flex:1;min-width:0}.searchButton{flex-shrink:0;min-height:var(--space-44, var(--size-44));padding:0 1rem;border:0;border-radius:var(--radius-10);background:var(--button-background-primary-bg-primary);color:var(--color-base-white);font-size:.9rem;font-weight:600;cursor:pointer}.searchButton:disabled{opacity:.55;cursor:not-allowed}.searchFeedback{margin:0;font-size:.8rem;color:var(--color-neutral-600)}.searchResults{margin:0;padding:0;list-style:none;max-height:var(--size-160);overflow:auto;border:1px solid var(--color-neutral-200);border-radius:var(--radius-10)}.searchResultButton{width:100%;padding:.65rem .85rem;border:0;border-block-end:1px solid var(--color-neutral-100);background:var(--color-base-white);text-align:start;font-size:.85rem;color:var(--text-text-primary-900);cursor:pointer}.searchResultButton:hover{background:var(--color-neutral-50)}.searchResults li:last-child .searchResultButton{border-block-end:0}.mapWrapper{position:relative;width:100%;height:var(--size-360);border-radius:var(--radius-xl);overflow:hidden}.inlineMapWrapper{position:relative;width:100%;border-radius:var(--radius-xl);overflow:hidden;border:1px solid var(--color-neutral-200);background:var(--color-neutral-200)}.mapHost{position:absolute;inset:0;z-index:1}.mapHost .leaflet-container{width:100%;height:100%;font-family:inherit;background:var(--color-neutral-200)}.mapHost .leaflet-container img.leaflet-tile.leaflet-tile,.mapHost .leaflet-container img.leaflet-marker-icon.leaflet-marker-icon,.mapHost .leaflet-container img.leaflet-marker-shadow.leaflet-marker-shadow{max-width:none;max-height:none;width:auto;height:auto}.mapHost .leaflet-pane,.mapHost .leaflet-tile-pane,.mapHost .leaflet-overlay-pane{z-index:auto}.mapLoadingOverlay{position:absolute;inset:0;z-index:2;pointer-events:none;background:linear-gradient(90deg,var(--color-neutral-100) 25%,var(--color-neutral-300) 50%,var(--color-neutral-100) 75%);background-size:200% 100%;animation:mapLoadingShimmer 1.2s ease-in-out infinite}.inlineMapShell{position:relative;width:100%}.fullscreenButton{position:absolute;top:.65rem;inset-inline-start:.65rem;z-index:1001;display:inline-flex;align-items:center;justify-content:center;gap:.35rem;min-width:2.25rem;height:2.25rem;padding:0 .55rem;border:0;border-radius:var(--radius-lg);background:#fffffff2;color:var(--text-text-primary-900);box-shadow:0 2px 10px #0000002e;cursor:pointer;pointer-events:auto}.fullscreenButton:hover{background:var(--color-base-white)}.fullscreenButton:focus-visible{outline:2px solid var(--button-background-primary-bg-primary);outline-offset:2px}.fullscreenButtonLabel{font-size:var(--font-size-xs);font-weight:600;line-height:1}.expandedMapWrapper{position:relative;width:100%;height:min(70vb,var(--size-520));border-radius:var(--radius-xl);overflow:hidden}@keyframes mapLoadingShimmer{0%{background-position:100% 0}to{background-position:-100% 0}}\n"] }]
|
|
6559
6659
|
}], ctorParameters: () => [], propDecorators: { initialLat: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialLat", required: false }] }], initialLng: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialLng", required: false }] }], zoom: [{ type: i0.Input, args: [{ isSignal: true, alias: "zoom", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], locationSelect: [{ type: i0.Output, args: ["locationSelect"] }] } });
|
|
6560
6660
|
|
|
6661
|
+
/** Google Maps location picker that lazily injects the Maps JS API, drops a marker where the user clicks and emits the coordinate; it stays blank unless an `apiKey` is supplied. */
|
|
6561
6662
|
class SceGoogleMapsLocationPickerComponent {
|
|
6562
6663
|
apiKey = input('', ...(ngDevMode ? [{ debugName: "apiKey" }] : /* istanbul ignore next */ []));
|
|
6563
6664
|
initialLat = input(24.7136, ...(ngDevMode ? [{ debugName: "initialLat" }] : /* istanbul ignore next */ []));
|
|
@@ -6668,6 +6769,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
6668
6769
|
args: [{ host: { class: 'sce-overview-stat-sparkline' }, selector: 'sce-overview-stat-sparkline', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<svg\n [class]=\"className()\"\n width=\"100%\"\n height=\"100%\"\n viewBox=\"0 0 128 29\"\n fill=\"none\"\n preserveAspectRatio=\"none\"\n aria-hidden=\"true\"\n [style.color]=\"color()\"\n>\n <defs>\n <linearGradient [attr.id]=\"gradientId()\" x1=\"64\" y1=\"-13\" x2=\"64.0833\" y2=\"29\" gradientUnits=\"userSpaceOnUse\">\n <stop stop-color=\"currentColor\" />\n <stop offset=\"1\" stop-color=\"currentColor\" stop-opacity=\"0\" />\n </linearGradient>\n <clipPath [attr.id]=\"clipId()\">\n <rect width=\"128\" height=\"29\" fill=\"white\" />\n </clipPath>\n </defs>\n <g [attr.clip-path]=\"'url(#' + clipId() + ')'\">\n <path [attr.d]=\"areaPath\" [attr.fill]=\"'url(#' + gradientId() + ')'\" />\n <path [attr.d]=\"linePath\" stroke=\"currentColor\" stroke-width=\"1.20912\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <circle cx=\"125.167\" cy=\"2.90261\" r=\"1.93459\" fill=\"currentColor\" stroke=\"white\" stroke-width=\"0.967296\" />\n </g>\n</svg>\n", styles: [":host{display:block}.sce-overview-stat-sparkline{display:contents}\n", ":host{display:inline-flex}svg{display:block}\n"] }]
|
|
6669
6770
|
}], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }] } });
|
|
6670
6771
|
|
|
6772
|
+
/** Standalone chart legend rendering colour markers and labels in a row or column — used instead of the built-in ECharts legend. */
|
|
6671
6773
|
class SceChartLegendComponent {
|
|
6672
6774
|
/** List of legend items to display */
|
|
6673
6775
|
items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
@@ -6801,6 +6903,7 @@ function formatItemTooltip(params, valueSuffix = '') {
|
|
|
6801
6903
|
</div>`;
|
|
6802
6904
|
}
|
|
6803
6905
|
|
|
6906
|
+
/** ECharts bar chart with optional stacking, overlay line series and a custom legend; axis side auto-detects RTL unless `isRtl` overrides it. */
|
|
6804
6907
|
class SceBarChartComponent {
|
|
6805
6908
|
el = inject(ElementRef);
|
|
6806
6909
|
/** Manual direction override; null auto-detects from computed style (RTL-first default). */
|
|
@@ -6914,6 +7017,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
6914
7017
|
args: [{ host: { class: 'sce-bar-chart' }, selector: 'sce-bar-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgxEchartsDirective, SceChartLegendComponent], providers: [provideEchartsCore({ echarts })], template: "<div class=\"bar-chart\" [style.height.px]=\"height()\" [style.width.px]=\"width()\">\n <div class=\"bar-chart__body\">\n <div echarts [options]=\"chartOptions()\" class=\"bar-chart__canvas\"></div>\n </div>\n @if (showLegend()) {\n <div class=\"bar-chart__legend\">\n <sce-chart-legend [items]=\"legendItems()\" [justifyContent]=\"'start'\" />\n </div>\n }\n</div>\n", styles: [":host{display:block}.bar-chart{width:100%;height:100%;position:relative;display:flex;flex-direction:column}.bar-chart__body{flex:1;min-height:0;position:relative}.bar-chart__canvas{width:100%;height:100%}.bar-chart__legend{flex-shrink:0}\n"] }]
|
|
6915
7018
|
}], ctorParameters: () => [], propDecorators: { isRtl: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRtl", required: false }] }], series: [{ type: i0.Input, args: [{ isSignal: true, alias: "series", required: false }] }], overlayLineSeries: [{ type: i0.Input, args: [{ isSignal: true, alias: "overlayLineSeries", required: false }] }], categories: [{ type: i0.Input, args: [{ isSignal: true, alias: "categories", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], barWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "barWidth", required: false }] }], borderRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "borderRadius", required: false }] }], showLegend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLegend", required: false }] }], showGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGrid", required: false }] }] } });
|
|
6916
7019
|
|
|
7020
|
+
/** Pure-CSS horizontal bar chart (no ECharts) where each bar is split into `segments` that fill proportionally to its value. */
|
|
6917
7021
|
class SceHorizontalBarChartComponent {
|
|
6918
7022
|
/** Data items for horizontal bars */
|
|
6919
7023
|
data = input([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
@@ -6965,6 +7069,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
6965
7069
|
args: [{ host: { class: 'sce-horizontal-bar-chart' }, selector: 'sce-horizontal-bar-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SceIcon], template: "<div class=\"horizontal-bar-chart\">\n @for (item of computedItems(); track item.label; let last = $last) {\n <div class=\"horizontal-bar-chart__item\" [style.margin-bottom.px]=\"last ? 0 : gap()\">\n <div class=\"horizontal-bar-chart__header\">\n <span class=\"horizontal-bar-chart__label\">{{ item.label }}</span>\n @if (showValues()) {\n <span class=\"horizontal-bar-chart__value\" [style.color]=\"item.barColor\">\n {{ item.value }}\n <sce-icon name=\"arrow-left\" [size]=\"18\" [style.color]=\"item.barColor\"></sce-icon>\n </span>\n }\n </div>\n <div class=\"horizontal-bar-chart__segments\">\n <!-- track $index: fixed number of chart segments, derived from the segments() count -->\n @for (fill of item.segmentFills; track $index) {\n <div class=\"horizontal-bar-chart__segment\" [style.height.px]=\"barHeight()\" [style.background-color]=\"trackColor()\">\n <div class=\"horizontal-bar-chart__fill\" [style.width.%]=\"fill\" [style.background-color]=\"item.barColor\"></div>\n </div>\n }\n </div>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%}.horizontal-bar-chart{width:100%;height:100%;overflow-y:auto}.horizontal-bar-chart__header{display:flex;justify-content:space-between;align-items:center;margin-block-end:var(--space-sm)}.horizontal-bar-chart__label{font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-neutral-800)}.horizontal-bar-chart__value{font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);display:flex;align-items:center;gap:var(--space-xs)}.horizontal-bar-chart__chevron{font-size:var(--font-size-xs);opacity:.7}.horizontal-bar-chart__segments{display:flex;gap:var(--space-xs)}.horizontal-bar-chart__segment{flex:1;border-radius:var(--radius-sm);overflow:hidden;position:relative}.horizontal-bar-chart__fill{height:100%;border-radius:var(--radius-sm);transition:width var(--motion-duration-slow) ease}\n"] }]
|
|
6966
7070
|
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], maxValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxValue", required: false }] }], showValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValues", required: false }] }], defaultColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultColor", required: false }] }], trackColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackColor", required: false }] }], barHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "barHeight", required: false }] }], gap: [{ type: i0.Input, args: [{ isSignal: true, alias: "gap", required: false }] }], segments: [{ type: i0.Input, args: [{ isSignal: true, alias: "segments", required: false }] }] } });
|
|
6967
7071
|
|
|
7072
|
+
/** ECharts multi-series line chart with optional area fill and a highlight bar/marker at `highlightIndex`; axis side auto-detects RTL unless `isRtl` overrides it. */
|
|
6968
7073
|
class SceLineChartComponent {
|
|
6969
7074
|
el = inject(ElementRef);
|
|
6970
7075
|
/** Manual direction override; null auto-detects from computed style (RTL-first default). */
|
|
@@ -7090,6 +7195,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
7090
7195
|
args: [{ host: { class: 'sce-line-chart' }, selector: 'sce-line-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgxEchartsDirective, SceChartLegendComponent], providers: [provideEchartsCore({ echarts })], template: "<div class=\"line-chart\" [style.height.px]=\"height()\" [style.width.px]=\"width()\">\n <div class=\"line-chart__wrapper\">\n <div echarts [options]=\"chartOptions()\" class=\"line-chart__canvas\"></div>\n </div>\n @if (showLegend()) {\n <div>\n <sce-chart-legend [items]=\"legendItems()\" [justifyContent]=\"'start'\" />\n </div>\n }\n</div>\n", styles: [":host{display:block}.line-chart{display:flex;flex-direction:column;width:100%;height:100%;position:relative}.line-chart__wrapper{flex:1;min-height:0;position:relative}.line-chart__canvas{width:100%;height:100%}\n"] }]
|
|
7091
7196
|
}], ctorParameters: () => [], propDecorators: { isRtl: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRtl", required: false }] }], series: [{ type: i0.Input, args: [{ isSignal: true, alias: "series", required: false }] }], categories: [{ type: i0.Input, args: [{ isSignal: true, alias: "categories", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], showArea: [{ type: i0.Input, args: [{ isSignal: true, alias: "showArea", required: false }] }], smooth: [{ type: i0.Input, args: [{ isSignal: true, alias: "smooth", required: false }] }], showLegend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLegend", required: false }] }], showGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGrid", required: false }] }], showXAxisLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "showXAxisLabels", required: false }] }], highlightIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlightIndex", required: false }] }] } });
|
|
7092
7197
|
|
|
7198
|
+
/** ECharts gradient area chart with hidden axes and an optional highlighted point marker at `highlightIndex`. */
|
|
7093
7199
|
class SceAreaChartComponent {
|
|
7094
7200
|
/** Data points for the chart */
|
|
7095
7201
|
data = input([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
@@ -7221,6 +7327,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
7221
7327
|
args: [{ host: { class: 'sce-area-chart' }, selector: 'sce-area-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgxEchartsDirective], providers: [provideEchartsCore({ echarts })], template: "<div class=\"area-chart\" [style.height.px]=\"height()\" [style.width.px]=\"width()\">\n <div echarts [options]=\"chartOptions()\" class=\"area-chart__canvas\"></div>\n</div>\n", styles: [":host{display:block}.area-chart{width:100%;height:100%;position:relative}.area-chart__canvas{width:100%;height:100%}\n"] }]
|
|
7222
7328
|
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], categories: [{ type: i0.Input, args: [{ isSignal: true, alias: "categories", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], startColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "startColor", required: false }] }], endColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "endColor", required: false }] }], smooth: [{ type: i0.Input, args: [{ isSignal: true, alias: "smooth", required: false }] }], tooltipLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltipLabel", required: false }] }], highlightIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlightIndex", required: false }] }] } });
|
|
7223
7329
|
|
|
7330
|
+
/** ECharts pie chart with optional in-slice percentage labels, an optional centre hole and a custom legend. */
|
|
7224
7331
|
class ScePieChartComponent {
|
|
7225
7332
|
/** Data items for the pie segments */
|
|
7226
7333
|
data = input([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
@@ -7304,6 +7411,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
7304
7411
|
args: [{ host: { class: 'sce-pie-chart' }, selector: 'sce-pie-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgxEchartsDirective, SceChartLegendComponent], providers: [provideEchartsCore({ echarts })], template: "<div class=\"pie-chart\" [style.height.px]=\"height()\" [style.width.px]=\"width()\">\n <div class=\"pie-chart__wrapper\">\n <div echarts [options]=\"chartOptions()\" class=\"pie-chart__canvas\"></div>\n </div>\n @if (showLegend()) {\n <div>\n <sce-chart-legend [items]=\"legendItems()\" [justifyContent]=\"'start'\" />\n </div>\n }\n</div>\n", styles: [":host{display:block}.pie-chart{display:flex;flex-direction:column;width:100%;height:100%;position:relative}.pie-chart__wrapper{flex:1;min-height:0;position:relative}.pie-chart__canvas{width:100%;height:100%}\n"] }]
|
|
7305
7412
|
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], radius: [{ type: i0.Input, args: [{ isSignal: true, alias: "radius", required: false }] }], showLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLabels", required: false }] }], showLegend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLegend", required: false }] }], startAngle: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAngle", required: false }] }], showCenterHole: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCenterHole", required: false }] }], innerRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "innerRadius", required: false }] }], itemRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemRadius", required: false }] }] } });
|
|
7306
7413
|
|
|
7414
|
+
/** Concentric ring ("donut") chart where each data item gets its own gauge ring sized against `maxRingValue`, with optional centred value and label. */
|
|
7307
7415
|
class SceDonutChartComponent {
|
|
7308
7416
|
/** Data items for the donut rings */
|
|
7309
7417
|
data = input([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
@@ -7469,6 +7577,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
7469
7577
|
args: [{ host: { class: 'sce-donut-chart' }, selector: 'sce-donut-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgxEchartsDirective, SceChartLegendComponent], providers: [provideEchartsCore({ echarts })], template: "<div class=\"donut-chart\" [style.height.px]=\"height()\">\n <div class=\"donut-chart__wrapper\">\n <div echarts [options]=\"chartOptions()\" class=\"donut-chart__canvas\"></div>\n </div>\n @if (showLegend()) {\n <div>\n <sce-chart-legend [items]=\"legendItems()\" [justifyContent]=\"'start'\" />\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%}.donut-chart{display:flex;flex-direction:column;width:100%;height:100%;position:relative}.donut-chart__wrapper{flex:1;min-height:0;position:relative}.donut-chart__canvas{width:100%;height:100%}\n"] }]
|
|
7470
7578
|
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], centerValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "centerValue", required: false }] }], centerLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "centerLabel", required: false }] }], innerRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "innerRadius", required: false }] }], outerRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "outerRadius", required: false }] }], showLegend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLegend", required: false }] }], showGap: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGap", required: false }] }], startAngle: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAngle", required: false }] }], total: [{ type: i0.Input, args: [{ isSignal: true, alias: "total", required: false }] }], maxRingValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRingValue", required: false }] }] } });
|
|
7471
7579
|
|
|
7580
|
+
/** ECharts donut ring with a centred label/value and a legend that also shows each item's value; the tooltip unit is hard-coded to Arabic "طلبات". */
|
|
7472
7581
|
class SceRingChartComponent {
|
|
7473
7582
|
/** Data items for the ring segments */
|
|
7474
7583
|
data = input([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
@@ -7533,6 +7642,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
7533
7642
|
args: [{ host: { class: 'sce-ring-chart' }, selector: 'sce-ring-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgxEchartsDirective], providers: [provideEchartsCore({ echarts })], template: "<div class=\"sce-ring-chart\">\n <div class=\"sce-ring-chart__canvas-wrap\" [style.height.px]=\"height()\">\n <div echarts [options]=\"chartOptions()\" class=\"sce-ring-chart__canvas\"></div>\n\n @if (centerValue() !== null) {\n <div class=\"sce-ring-chart__overlay\" aria-hidden=\"true\">\n @if (centerLabel()) {\n <span class=\"sce-ring-chart__center-label\">{{ centerLabel() }}</span>\n }\n <span class=\"sce-ring-chart__center-value\">{{ centerValue() }}</span>\n </div>\n }\n </div>\n\n @if (showLegend() && legendItems().length) {\n <div class=\"sce-ring-chart__legend\">\n @for (item of legendItems(); track item.name) {\n <div class=\"sce-ring-chart__legend-row\">\n <div class=\"sce-ring-chart__legend-marker\" [style.background-color]=\"item.color\"></div>\n <span class=\"sce-ring-chart__legend-name\">{{ item.name }}</span>\n <span class=\"sce-ring-chart__legend-value\">{{ item.value }}</span>\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%}.sce-ring-chart{display:flex;flex-direction:column;width:100%}.sce-ring-chart__canvas-wrap{position:relative;width:100%;flex-shrink:0}.sce-ring-chart__canvas{width:100%;height:100%}.sce-ring-chart__overlay{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none}.sce-ring-chart__center-label{font-size:var(--font-size-sm);color:var(--color-text-muted);line-height:1.375}.sce-ring-chart__center-value{font-size:var(--font-size-4xl);font-weight:var(--font-weight-bold);color:var(--color-text-primary);line-height:1}.sce-ring-chart__legend{display:flex;flex-direction:column;gap:var(--space-16);padding-block-start:var(--space-sm)}.sce-ring-chart__legend-row{display:flex;align-items:center;gap:var(--space-sm)}.sce-ring-chart__legend-name{flex:1;font-size:var(--font-size-sm);color:var(--color-text-muted);font-weight:var(--font-weight-medium);text-align:start}.sce-ring-chart__legend-marker{inline-size:var(--space-sm);block-size:var(--space-sm);border-radius:var(--radius-md);width:var(--space-20);height:var(--space-20);flex-shrink:0}.sce-ring-chart__legend-value{font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--color-text-primary)}\n"] }]
|
|
7534
7643
|
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], centerLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "centerLabel", required: false }] }], centerValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "centerValue", required: false }] }], innerRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "innerRadius", required: false }] }], outerRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "outerRadius", required: false }] }], showLegend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLegend", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], startAngle: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAngle", required: false }] }] } });
|
|
7535
7644
|
|
|
7645
|
+
/** Semicircular tick-mark gauge for a 0-100 value; when `isRtl` is set the chart's own text is hidden so the caller can overlay it unmirrored. */
|
|
7536
7646
|
class SceGaugeChartComponent {
|
|
7537
7647
|
/** Current value (0-100) */
|
|
7538
7648
|
value = input(0, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
@@ -7633,6 +7743,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
7633
7743
|
args: [{ host: { class: 'sce-gauge-chart' }, selector: 'sce-gauge-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgxEchartsDirective], providers: [provideEchartsCore({ echarts })], template: "<div class=\"gauge-chart\" [style.height.px]=\"height()\" [style.width.px]=\"width()\">\n <div class=\"gauge-chart__canvas\" [class.gauge-chart__canvas--rtl]=\"isRtl()\">\n <div echarts [options]=\"chartOptions()\" class=\"gauge-chart__canvas-inner\"></div>\n </div>\n @if (isRtl() && showValue()) {\n <div class=\"gauge-chart__label-overlay\" aria-hidden=\"true\">\n <span class=\"gauge-chart__value\">%{{ value() }}</span>\n @if (label()) {\n <span class=\"gauge-chart__label\">{{ label() }}</span>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%}.gauge-chart{width:100%;height:100%;position:relative}.gauge-chart__canvas{width:100%;height:100%}.gauge-chart__canvas--rtl{transform:scaleX(-1)}.gauge-chart__canvas-inner{width:100%;height:100%}.gauge-chart__label-overlay{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none;font-family:var(--font-family-base);transform:translateY(-8%)}.gauge-chart__value{font-size:var(--font-size-4xl);font-weight:var(--font-weight-bold);color:var(--color-text-primary);line-height:1}.gauge-chart__label{font-size:var(--font-size-sm);color:var(--color-text-muted);margin-block-start:var(--space-xs)}\n"] }]
|
|
7634
7744
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], backgroundColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "backgroundColor", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }], startAngle: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAngle", required: false }] }], endAngle: [{ type: i0.Input, args: [{ isSignal: true, alias: "endAngle", required: false }] }], isRtl: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRtl", required: false }] }] } });
|
|
7635
7745
|
|
|
7746
|
+
/** Pure-CSS horizontal bars (no ECharts), each split into `segmentCount` sub-segments that fill against the item's own `maxValue`. */
|
|
7636
7747
|
class SceMultiSegmentBarChartComponent {
|
|
7637
7748
|
el = inject(ElementRef);
|
|
7638
7749
|
/** Data items for the bar chart */
|
|
@@ -7695,6 +7806,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
7695
7806
|
args: [{ host: { class: 'sce-multi-segment-bar-chart' }, selector: 'sce-multi-segment-bar-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-multi-segment-bar-chart\" [style.row-gap.px]=\"rowGap()\">\n @for (bar of computedBars(); track bar.label) {\n <div class=\"sce-multi-segment-bar-chart__item\">\n <!-- Segmented Bar -->\n <div class=\"sce-multi-segment-bar-chart__bar\" [style.height.px]=\"barHeight()\" [style.gap.px]=\"segmentGap()\">\n <!-- track $index: fixed number of chart segments, derived from the segmentCount() input -->\n @for (seg of bar.segments; track $index; let first = $first; let last = $last) {\n <div\n class=\"sce-multi-segment-bar-chart__segment\"\n [class.sce-multi-segment-bar-chart__segment--first]=\"first\"\n [class.sce-multi-segment-bar-chart__segment--last]=\"last\"\n [style.background-color]=\"trackColor()\"\n >\n <div class=\"sce-multi-segment-bar-chart__fill\" [style.width.%]=\"seg.fill\" [style.background-color]=\"bar.color\"></div>\n </div>\n }\n </div>\n\n <!-- Info Row -->\n <div class=\"sce-multi-segment-bar-chart__row\">\n <div class=\"sce-multi-segment-bar-chart__meta\">\n <span class=\"sce-multi-segment-bar-chart__marker\" [style.background-color]=\"bar.color\" [attr.aria-hidden]=\"true\"></span>\n <span class=\"sce-multi-segment-bar-chart__label\">{{ bar.label }}</span>\n </div>\n <span class=\"sce-multi-segment-bar-chart__value\">{{ bar.value }}</span>\n </div>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%}.sce-multi-segment-bar-chart{display:flex;flex-direction:column;width:100%}.sce-multi-segment-bar-chart__item{display:flex;flex-direction:column;gap:var(--space-md)}.sce-multi-segment-bar-chart__bar{display:flex;width:100%}.sce-multi-segment-bar-chart__segment{flex:1;position:relative;overflow:hidden}.sce-multi-segment-bar-chart__segment--first{border-start-start-radius:var(--radius-2xl);border-end-start-radius:var(--radius-2xl)}.sce-multi-segment-bar-chart__segment--last{border-start-end-radius:var(--radius-2xl);border-end-end-radius:var(--radius-2xl)}.sce-multi-segment-bar-chart__fill{height:100%;transition:width .3s ease}.sce-multi-segment-bar-chart__row{display:flex;align-items:center;justify-content:space-between}:host-context([dir=rtl]) .sce-multi-segment-bar-chart__row{flex-direction:row-reverse}.sce-multi-segment-bar-chart__meta{display:flex;align-items:center;gap:var(--space-sm)}:host-context([dir=rtl]) .sce-multi-segment-bar-chart__meta{flex-direction:row-reverse}.sce-multi-segment-bar-chart__marker{inline-size:var(--space-xl);block-size:var(--space-xl);border-radius:var(--radius-md);flex-shrink:0}.sce-multi-segment-bar-chart__label{color:var(--color-text-secondary);font-size:var(--font-size-lg);font-weight:var(--font-weight-medium)}.sce-multi-segment-bar-chart__value{color:var(--color-text-primary);font-size:var(--font-size-2xl);font-weight:var(--font-weight-bold)}\n"] }]
|
|
7696
7807
|
}], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], barHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "barHeight", required: false }] }], segmentCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "segmentCount", required: false }] }], segmentGap: [{ type: i0.Input, args: [{ isSignal: true, alias: "segmentGap", required: false }] }], rowGap: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowGap", required: false }] }], defaultColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultColor", required: false }] }], trackColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackColor", required: false }] }], isRtl: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRtl", required: false }] }] } });
|
|
7697
7808
|
|
|
7809
|
+
/** Half-circle ECharts gauge whose arc is coloured by proportional segment stops, with an optional centred label and value. */
|
|
7698
7810
|
class SceMultiSegmentGaugeComponent {
|
|
7699
7811
|
/** Segments to display on the gauge arc */
|
|
7700
7812
|
segments = input([], ...(ngDevMode ? [{ debugName: "segments" }] : /* istanbul ignore next */ []));
|
|
@@ -7760,6 +7872,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
7760
7872
|
args: [{ host: { class: 'sce-multi-segment-gauge' }, selector: 'sce-multi-segment-gauge', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgxEchartsDirective], providers: [provideEchartsCore({ echarts })], template: "<div class=\"sce-multi-segment-gauge\">\n <div class=\"sce-multi-segment-gauge__canvas-wrap\" [style.height.px]=\"height()\">\n <div echarts [options]=\"chartOptions()\" class=\"sce-multi-segment-gauge__canvas\"></div>\n\n @if (centerValue() !== null) {\n <div class=\"sce-multi-segment-gauge__overlay\" aria-hidden=\"true\">\n @if (centerLabel()) {\n <span class=\"sce-multi-segment-gauge__center-label\">{{ centerLabel() }}</span>\n }\n <span class=\"sce-multi-segment-gauge__center-value\">{{ centerValue() }}</span>\n </div>\n }\n </div>\n\n @if (showLegend() && legendItems().length) {\n <div class=\"sce-multi-segment-gauge__legend\">\n @for (item of legendItems(); track item.name) {\n <div class=\"sce-multi-segment-gauge__legend-item\">\n <span class=\"sce-multi-segment-gauge__legend-label\">{{ item.name }}</span>\n <div class=\"sce-multi-segment-gauge__legend-dot\" [style.background-color]=\"item.color\"></div>\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%}.sce-multi-segment-gauge{display:flex;flex-direction:column;align-items:center;width:100%}.sce-multi-segment-gauge__canvas-wrap{position:relative;width:100%;flex-shrink:0}.sce-multi-segment-gauge__canvas{width:100%;height:100%}.sce-multi-segment-gauge__overlay{position:absolute;inset-inline:0;inset-block-end:0;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;padding-block-end:var(--space-sm);pointer-events:none;font-family:var(--font-family-primary)}.sce-multi-segment-gauge__center-label{font-size:var(--font-size-sm);color:var(--color-text-muted);line-height:var(--line-height-normal)}.sce-multi-segment-gauge__center-value{font-size:var(--font-size-4xl);font-weight:var(--font-weight-bold);color:var(--color-text-primary);line-height:var(--line-height-normal)}.sce-multi-segment-gauge__legend{width:100%;display:flex;flex-direction:column;gap:var(--space-xs);padding-block-start:var(--space-sm);padding-inline-start:var(--space-xs)}.sce-multi-segment-gauge__legend-item{display:flex;align-items:center;gap:var(--space-sm)}.sce-multi-segment-gauge__legend-label{flex:1;font-size:var(--font-size-sm);color:var(--color-text-secondary);text-align:start}.sce-multi-segment-gauge__legend-dot{inline-size:var(--space-sm);block-size:var(--space-sm);border-radius:var(--radius-full);flex-shrink:0}\n"] }]
|
|
7761
7873
|
}], propDecorators: { segments: [{ type: i0.Input, args: [{ isSignal: true, alias: "segments", required: false }] }], centerLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "centerLabel", required: false }] }], centerValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "centerValue", required: false }] }], showLegend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLegend", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], backgroundColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "backgroundColor", required: false }] }] } });
|
|
7762
7874
|
|
|
7875
|
+
/** Single stacked bar showing each item's share of the total plus a legend row per item, with an auto-generated aria summary and RTL auto-detection. */
|
|
7763
7876
|
class SceStackedDistributionChartComponent {
|
|
7764
7877
|
el = inject(ElementRef);
|
|
7765
7878
|
/** Segments rendered in the distribution bar and legend rows */
|
|
@@ -7823,6 +7936,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
7823
7936
|
args: [{ host: { class: 'sce-stacked-distribution-chart' }, selector: 'sce-stacked-distribution-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-stacked-distribution-chart\">\n <div\n class=\"sce-stacked-distribution-chart__bar\"\n [style.height.px]=\"barHeight()\"\n [style.gap.px]=\"segmentGap()\"\n role=\"img\"\n [attr.aria-label]=\"ariaLabel()\"\n >\n @if (total() > 0 && computedItems().length) {\n @for (item of computedItems(); track item.label; let itemFirst = $first; let itemLast = $last) {\n <!-- track $index: fixed number of chart sub-segments within a single distribution item -->\n @for (val of item.subSegments; track $index; let subFirst = $first; let subLast = $last) {\n <div\n class=\"sce-stacked-distribution-chart__segment\"\n [class.sce-stacked-distribution-chart__segment--first]=\"itemFirst && subFirst\"\n [class.sce-stacked-distribution-chart__segment--last]=\"itemLast && subLast\"\n [class.sce-stacked-distribution-chart__segment--patterned]=\"item.patterned\"\n [style.flex-grow]=\"val\"\n [style.background-color]=\"item.color\"\n [attr.aria-hidden]=\"true\"\n ></div>\n }\n }\n } @else {\n <div\n class=\"sce-stacked-distribution-chart__segment sce-stacked-distribution-chart__segment--first sce-stacked-distribution-chart__segment--last\"\n [style.background-color]=\"emptyColor()\"\n [attr.aria-hidden]=\"true\"\n ></div>\n }\n </div>\n\n <div class=\"sce-stacked-distribution-chart__legend\" [style.row-gap.px]=\"rowGap()\" role=\"list\">\n @for (item of computedItems(); track item.label) {\n <div class=\"sce-stacked-distribution-chart__row\" role=\"listitem\">\n <div class=\"sce-stacked-distribution-chart__meta\">\n <span\n class=\"sce-stacked-distribution-chart__marker\"\n [style.background-color]=\"item.color\"\n [style.inline-size.px]=\"markerSize()\"\n [style.block-size.px]=\"markerSize()\"\n [attr.aria-hidden]=\"true\"\n ></span>\n <span class=\"sce-stacked-distribution-chart__label\">{{ item.label }}</span>\n </div>\n\n <span class=\"sce-stacked-distribution-chart__value\">{{ item.value }}</span>\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%}.sce-stacked-distribution-chart{display:flex;flex-direction:column;gap:var(--space-20);width:100%}.sce-stacked-distribution-chart__bar{display:flex;width:100%}.sce-stacked-distribution-chart__segment{position:relative;flex-basis:0;min-inline-size:0;block-size:100%;overflow:hidden;transition:flex-grow .25s ease;border-radius:var(--radius-2xl)}.sce-stacked-distribution-chart__segment--patterned:after{content:\"\";position:absolute;inset:0;background-image:repeating-linear-gradient(90deg,rgba(255,255,255,.15) 0 1px,transparent 1px 100%);pointer-events:none}.sce-stacked-distribution-chart__legend{display:flex;flex-direction:column}:host-context([dir=ltr]) .sce-stacked-distribution-chart__legend .sce-stacked-distribution-chart__row{flex-direction:row-reverse}:host-context([dir=ltr]) .sce-stacked-distribution-chart__legend .sce-stacked-distribution-chart__meta{flex-direction:row-reverse}.sce-stacked-distribution-chart__row{display:flex;align-items:center;justify-content:space-between;gap:var(--space-lg)}.sce-stacked-distribution-chart__meta{display:flex;align-items:center;gap:var(--space-md);min-inline-size:0}.sce-stacked-distribution-chart__marker{border-radius:var(--radius-md);flex-shrink:0}.sce-stacked-distribution-chart__label{color:var(--color-text-secondary);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);line-height:var(--line-height-normal);text-align:start;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sce-stacked-distribution-chart__value{color:var(--color-text-display);font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);line-height:var(--line-height-normal);flex-shrink:0}\n"] }]
|
|
7824
7937
|
}], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], barHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "barHeight", required: false }] }], segmentGap: [{ type: i0.Input, args: [{ isSignal: true, alias: "segmentGap", required: false }] }], rowGap: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowGap", required: false }] }], markerSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "markerSize", required: false }] }], defaultColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultColor", required: false }] }], emptyColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyColor", required: false }] }], isRtl: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRtl", required: false }] }] } });
|
|
7825
7938
|
|
|
7939
|
+
/** Half-circle gauge of `value` out of `total`, rendered with a subtitle and a list of colour-coded stat rows below it. */
|
|
7826
7940
|
class SceStatGaugeComponent {
|
|
7827
7941
|
/** Current (numerator) value, e.g. 120 */
|
|
7828
7942
|
value = input(0, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
@@ -7888,6 +8002,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
7888
8002
|
args: [{ host: { class: 'sce-stat-gauge' }, selector: 'sce-stat-gauge', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgxEchartsDirective], providers: [provideEchartsCore({ echarts })], template: "<div class=\"sce-stat-gauge\">\n <div class=\"sce-stat-gauge__canvas-wrap\" [style.height.px]=\"height()\">\n <div echarts [options]=\"chartOptions()\" class=\"sce-stat-gauge__canvas\"></div>\n\n <div class=\"sce-stat-gauge__overlay\" aria-hidden=\"true\">\n <span class=\"sce-stat-gauge__percentage\">{{ percentage() }}%</span>\n @if (subtitle()) {\n <span class=\"sce-stat-gauge__subtitle\">{{ subtitle() }}</span>\n }\n </div>\n </div>\n\n @if (stats().length) {\n <div class=\"sce-stat-gauge__stats\">\n @for (row of stats(); track row.label) {\n <div class=\"sce-stat-gauge__stat-row\">\n <div class=\"sce-stat-gauge__stat-row__meta\">\n <span\n class=\"sce-stat-gauge__marker\"\n [style.background-color]=\"row.color\"\n [style.inline-size.px]=\"markerSize()\"\n [style.block-size.px]=\"markerSize()\"\n [attr.aria-hidden]=\"true\"\n ></span>\n <span class=\"sce-stat-gauge__stat-label\">{{ row.label }}</span>\n </div>\n\n <span class=\"sce-stat-gauge__stat-value\">{{ row.value }}</span>\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%}.sce-stat-gauge{display:flex;flex-direction:column;align-items:center;width:100%}.sce-stat-gauge__canvas-wrap{position:relative;width:100%}.sce-stat-gauge__canvas{width:100%;height:100%}.sce-stat-gauge__overlay{position:absolute;inset-inline:0;inset-block-end:0;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;padding-block-end:var(--space-sm);pointer-events:none;font-family:var(--font-family-primary)}.sce-stat-gauge__percentage{font-size:var(--font-size-chart-value, var(--font-size-4xl));font-weight:var(--font-weight-bold);color:var(--color-chart-text, var(--color-text-primary));line-height:1}.sce-stat-gauge__subtitle{font-size:var(--font-size-chart-label, var(--font-size-sm));color:var(--color-chart-text-secondary, var(--color-text-muted));margin-block-start:var(--space-xs)}.sce-stat-gauge__marker{border-radius:var(--radius-md);flex-shrink:0}.sce-stat-gauge__stats{width:100%;display:flex;flex-direction:column;gap:var(--space-xs);padding-block-start:var(--space-sm)}.sce-stat-gauge__stat-row{display:flex;justify-content:space-between;align-items:center;padding-inline:var(--space-xs)}.sce-stat-gauge__stat-row__meta{display:flex;align-items:center;gap:var(--space-md);min-inline-size:0}.sce-stat-gauge__stat-label{font-size:var(--font-size-sm);color:var(--color-text-secondary)}.sce-stat-gauge__stat-value{font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--color-text-primary)}\n"] }]
|
|
7889
8003
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], total: [{ type: i0.Input, args: [{ isSignal: true, alias: "total", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], stats: [{ type: i0.Input, args: [{ isSignal: true, alias: "stats", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], backgroundColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "backgroundColor", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], markerSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "markerSize", required: false }] }] } });
|
|
7890
8004
|
|
|
8005
|
+
/** SVG progress ring (no ECharts) with a centred label and value, an optional gradient stroke and RTL auto-detection; `progress` may exceed 100. */
|
|
7891
8006
|
class SceStatRingComponent {
|
|
7892
8007
|
el = inject(ElementRef);
|
|
7893
8008
|
/** Center label shown above the value */
|
|
@@ -7957,6 +8072,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
7957
8072
|
args: [{ host: { class: 'sce-stat-ring' }, selector: 'sce-stat-ring', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-stat-ring\" [style.width.px]=\"size()\" [style.height.px]=\"size()\">\n <svg\n class=\"sce-stat-ring__svg\"\n [attr.viewBox]=\"viewBox()\"\n [attr.width]=\"size()\"\n [attr.height]=\"size()\"\n role=\"img\"\n [attr.aria-label]=\"label() + ' ' + value()\"\n >\n @if (useGradient()) {\n <defs>\n <linearGradient [id]=\"gradientId()\" x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"100%\">\n <stop offset=\"0%\" [attr.stop-color]=\"gradientStartColor()\" />\n <stop offset=\"100%\" [attr.stop-color]=\"gradientEndColor()\" />\n </linearGradient>\n </defs>\n }\n\n <circle\n class=\"sce-stat-ring__track\"\n [attr.cx]=\"center()\"\n [attr.cy]=\"center()\"\n [attr.r]=\"radius()\"\n [attr.stroke-width]=\"trackStrokeWidth()\"\n [attr.stroke]=\"trackColor()\"\n fill=\"none\"\n />\n <circle\n class=\"sce-stat-ring__fill\"\n [attr.cx]=\"center()\"\n [attr.cy]=\"center()\"\n [attr.r]=\"radius()\"\n [attr.stroke-width]=\"strokeWidth()\"\n [attr.stroke]=\"useGradient() ? 'url(#' + gradientId() + ')' : color()\"\n stroke-linecap=\"round\"\n [attr.stroke-dasharray]=\"circumference()\"\n [attr.stroke-dashoffset]=\"strokeDashOffset()\"\n [attr.transform]=\"'rotate(' + startAngle() + ' ' + center() + ' ' + center() + ')'\"\n fill=\"none\"\n />\n </svg>\n\n <div class=\"sce-stat-ring__content\" aria-hidden=\"true\">\n @if (label()) {\n <span class=\"sce-stat-ring__label\">{{ label() }}</span>\n }\n <span class=\"sce-stat-ring__value\">{{ value() }}</span>\n </div>\n</div>\n", styles: [":host{display:inline-flex}.sce-stat-ring{position:relative;display:inline-flex;align-items:center;justify-content:center}.sce-stat-ring__svg{display:block;overflow:visible}:host-context([dir=rtl]) .sce-stat-ring__svg{transform:scaleY(-1)}.sce-stat-ring__track,.sce-stat-ring__fill{stroke-linecap:round}.sce-stat-ring__fill{transition:stroke-dashoffset .3s ease}.sce-stat-ring__content{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-2xs);pointer-events:none;text-align:center}.sce-stat-ring__label{color:var(--color-text-secondary);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);line-height:1.2}.sce-stat-ring__value{color:var(--color-text-primary);font-size:var(--font-size-xl);font-weight:var(--font-weight-bold);line-height:1}\n"] }]
|
|
7958
8073
|
}], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], progress: [{ type: i0.Input, args: [{ isSignal: true, alias: "progress", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], strokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "strokeWidth", required: false }] }], trackStrokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackStrokeWidth", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], gradientStartColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "gradientStartColor", required: false }] }], gradientEndColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "gradientEndColor", required: false }] }], trackColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackColor", required: false }] }], startAngle: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAngle", required: false }] }], useGradient: [{ type: i0.Input, args: [{ isSignal: true, alias: "useGradient", required: false }] }], isRtl: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRtl", required: false }] }] } });
|
|
7959
8074
|
|
|
8075
|
+
/** Three-segment scale track showing either a single thumb or a highlighted range when both `start` and `end` are given; the segment labels default to hardcoded Arabic strings. */
|
|
7960
8076
|
class SceScaleIndicatorComponent {
|
|
7961
8077
|
/** Title displayed above the scale */
|
|
7962
8078
|
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
@@ -8025,6 +8141,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
8025
8141
|
args: [{ host: { class: 'sce-scale-indicator' }, selector: 'sce-scale-indicator', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-scale-indicator\">\n @if (title()) {\n <h4 class=\"sce-scale-indicator__title\">{{ title() }}</h4>\n }\n\n <div class=\"sce-scale-indicator__track\">\n <div class=\"sce-scale-indicator__segment\"></div>\n <div class=\"sce-scale-indicator__segment\"></div>\n <div class=\"sce-scale-indicator__segment\"></div>\n\n @if (isRangeMode()) {\n <div\n class=\"sce-scale-indicator__range\"\n [style.left.%]=\"rangeStartPercent()\"\n [style.width.%]=\"rangeWidthPercent()\"\n [style.background-color]=\"activeColor()\"\n ></div>\n } @else {\n <div\n class=\"sce-scale-indicator__thumb\"\n [style.height.px]=\"barHeight()\"\n [style.left.%]=\"thumbPercent()\"\n [style.background-color]=\"activeColor()\"\n ></div>\n }\n </div>\n\n <div class=\"sce-scale-indicator__labels\">\n <span class=\"sce-scale-indicator__label\">{{ labels().high }}</span>\n <span class=\"sce-scale-indicator__label\">{{ labels().mid }}</span>\n <span class=\"sce-scale-indicator__label\">{{ labels().low }}</span>\n </div>\n</div>\n", styles: [":host{display:block;width:100%;height:100%}.sce-scale-indicator{width:100%;height:100%}.sce-scale-indicator__title{text-align:center;font-size:var(--font-size-md);font-weight:var(--font-weight-semibold);color:var(--color-neutral-800);margin-block:0 var(--space-md);margin-inline:0}.sce-scale-indicator__track{position:relative;display:flex;gap:var(--space-xs);height:var(--size-8);margin-block-end:var(--space-sm)}.sce-scale-indicator__segment{flex:1;border-radius:var(--radius-xs);background-color:var(--color-neutral-200)}.sce-scale-indicator__thumb{position:absolute;top:50%;transform:translate(-50%,-50%);width:var(--size-32);height:var(--size-8);border-radius:var(--radius-sm);transition:left .3s ease}.sce-scale-indicator__range{position:absolute;top:50%;transform:translateY(-50%);height:var(--size-8);min-width:4%;border-radius:var(--radius-sm);transition:left .3s ease,width .3s ease}.sce-scale-indicator__labels{display:flex;justify-content:space-between}.sce-scale-indicator__label{flex:1;text-align:center;font-size:var(--font-size-xs);color:var(--color-neutral-400)}\n"] }]
|
|
8026
8142
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], start: [{ type: i0.Input, args: [{ isSignal: true, alias: "start", required: false }] }], end: [{ type: i0.Input, args: [{ isSignal: true, alias: "end", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], activeColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeColor", required: false }] }], trackColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackColor", required: false }] }], barHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "barHeight", required: false }] }] } });
|
|
8027
8143
|
|
|
8144
|
+
/** Dashboard overview tile showing a stat value, translated label, icon on a coloured background and an optional trend sparkline. */
|
|
8028
8145
|
class SceOverviewStatCardComponent {
|
|
8029
8146
|
value = input.required(...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
8030
8147
|
labelKey = input.required(...(ngDevMode ? [{ debugName: "labelKey" }] : /* istanbul ignore next */ []));
|
|
@@ -8039,6 +8156,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
8039
8156
|
args: [{ host: { class: 'sce-overview-stat-card' }, selector: 'sce-overview-stat-card', standalone: true, imports: [TranslatePipe, SceOverviewStatSparklineComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<article class=\"stat-card\">\n <!-- Top Row: Icon (start/right) and Trend (end/left) -->\n <div class=\"stat-header\">\n <div class=\"stat-icon-wrap\" [style.background]=\"iconBg()\">\n <img [src]=\"icon()\" width=\"22\" height=\"22\" alt=\"\" aria-hidden=\"true\" class=\"stat-icon\" />\n </div>\n @if (trend()) {\n <div class=\"stat-trend\">\n {{ trend() }}\n </div>\n }\n </div>\n\n <!-- Bottom Row: Text (start/right) and Sparkline (end/left) -->\n <div class=\"stat-body\">\n <div class=\"stat-text\">\n <p class=\"stat-value\">{{ value() }}</p>\n <p class=\"stat-label\">{{ labelKey() | translate }}</p>\n </div>\n <div class=\"sparkline-container\" aria-hidden=\"true\">\n <sce-overview-stat-sparkline [color]=\"iconBg()\" className=\"sparkline-img\" />\n </div>\n </div>\n</article>\n", styles: [":host{display:block;width:100%}.stat-card{background:var(--surface-primary);border:1px solid var(--color-border);box-shadow:0 1px 3px #1018280d,0 1px 2px #10182808;border-radius:var(--radius-brand-sm);padding:var(--space-20);display:flex;flex-direction:column;justify-content:space-between;min-height:var(--size-156);position:relative;z-index:0;overflow:hidden;box-sizing:border-box;transition:transform .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1)}@media(prefers-reduced-motion:no-preference){.stat-card:hover{transform:translateY(-4px);box-shadow:0 12px 24px #10182814;border-color:#0000000d}}.stat-header{display:flex;justify-content:space-between;align-items:center;width:100%}.stat-icon-wrap{width:var(--space-44, var(--size-44));height:var(--space-44, var(--size-44));border-radius:var(--radius-xl);display:inline-flex;align-items:center;justify-content:center}.stat-icon{display:block;filter:brightness(0) invert(1)}.stat-trend{font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-md);font-weight:600;color:var(--text-text-primary-900, var(--color-neutral-900));display:flex;align-items:center;gap:var(--space-4);direction:ltr}.stat-body{display:flex;justify-content:space-between;align-items:flex-end;width:100%;margin-block-start:auto}.stat-text{display:flex;flex-direction:column;gap:var(--space-4);align-items:flex-start;text-align:start}.stat-value{margin:.6rem 0 .2rem;font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-2xl);font-weight:700;color:var(--text-text-primary-900, var(--color-neutral-900))}.stat-label{margin:0;font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-md);font-weight:500;color:var(--text-text-secondary-600);line-height:1.4;white-space:nowrap}.sparkline-container{width:60%;max-width:var(--size-110);height:var(--space-32);display:block}.sparkline-container sce-overview-stat-sparkline{display:block;width:100%;height:100%}\n"] }]
|
|
8040
8157
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], labelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelKey", required: true }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: true }] }], iconBg: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconBg", required: true }] }], trend: [{ type: i0.Input, args: [{ isSignal: true, alias: "trend", required: false }] }] } });
|
|
8041
8158
|
|
|
8159
|
+
/** Small dashboard card linking to a service, showing its icon and a count with a role-aware translated suffix. */
|
|
8042
8160
|
class SceServiceMiniCardComponent {
|
|
8043
8161
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
8044
8162
|
count = input.required(...(ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []));
|
|
@@ -8054,6 +8172,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
8054
8172
|
args: [{ host: { class: 'sce-service-mini-card' }, selector: 'sce-service-mini-card', standalone: true, imports: [RouterLink, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<a [routerLink]=\"link()\" class=\"service-card\">\n <!-- Right Column (Start side): Icon and Text -->\n <div class=\"service-info-group\">\n <div class=\"service-icon-wrap\">\n <img [src]=\"icon()\" width=\"24\" height=\"24\" alt=\"\" aria-hidden=\"true\" class=\"service-icon\" />\n </div>\n <div class=\"service-text\">\n <h3 class=\"service-title\">{{ title() }}</h3>\n <span class=\"service-count\"> {{ count() }} {{ countSuffix() | translate }} </span>\n </div>\n </div>\n\n <!-- Left Column (End side): Circular Arrow Button -->\n <div class=\"service-arrow-btn\" aria-hidden=\"true\">\n <span class=\"arrow-icon\"><img src=\"/assets/icons/arrow-left.svg\" height=\"12\" width=\"12\" alt=\"\" /></span>\n </div>\n</a>\n", styles: [":host{display:block;width:100%}.service-card{display:flex;justify-content:space-between;align-items:center;background:var(--surface-primary);border:1px solid var(--color-border);box-shadow:0 1px 3px #1018280d,0 1px 2px #10182808;border-radius:var(--radius-brand-sm);padding:var(--space-16) var(--space-20);text-decoration:none;color:inherit;box-sizing:border-box;width:100%;transition:transform .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1)}@media(prefers-reduced-motion:no-preference){.service-card:hover{transform:translateY(-2px);box-shadow:0 8px 16px #1018280f;border-color:#0000000d}}.service-info-group{display:flex;align-items:center;gap:var(--space-16)}.service-icon-wrap{width:var(--space-56);height:var(--space-56);border-radius:var(--radius-2xl, var(--radius-2xl));background:var(--color-brand-primary-800);display:flex;align-items:center;justify-content:center;flex-shrink:0}.service-icon{display:block;filter:brightness(0) invert(1)}.service-text{display:flex;flex-direction:column;gap:var(--space-4);align-items:flex-start;text-align:start}.service-title{margin:0;font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-lg-18);font-weight:700;color:var(--text-text-primary-900, var(--color-neutral-900));line-height:1.2}.service-count{margin:0;font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-md);font-weight:500;color:var(--text-text-secondary-600);line-height:1.4}.service-arrow-btn{width:var(--space-36);height:var(--space-36);border-radius:var(--radius-full);background:var(--background-bg-secondary);display:flex;align-items:center;justify-content:center;color:var(--text-text-primary-900, var(--color-neutral-900));transition:background .2s ease,transform .2s ease;flex-shrink:0}.arrow-icon{display:inline-block;font-size:var(--font-size-lg-18);line-height:1;font-weight:700;transition:transform .2s ease}.service-card:hover .service-arrow-btn{background:var(--color-neutral-200)}.service-card:hover .service-arrow-btn{transform:translate(calc(var(--dir) * 4px))}:host-context([dir=ltr]) .arrow-icon{transform:rotate(180deg)}\n"] }]
|
|
8055
8173
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: true }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: true }] }], link: [{ type: i0.Input, args: [{ isSignal: true, alias: "link", required: true }] }], countSuffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "countSuffix", required: false }] }] } });
|
|
8056
8174
|
|
|
8175
|
+
/** Dashboard card for a featured engineering office showing rating, review count, country and service tabs; a zero review count renders the "no reviews yet" fallback. */
|
|
8057
8176
|
class SceFeaturedOfficeCardComponent {
|
|
8058
8177
|
office = input.required(...(ngDevMode ? [{ debugName: "office" }] : /* istanbul ignore next */ []));
|
|
8059
8178
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SceFeaturedOfficeCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -8064,6 +8183,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
8064
8183
|
args: [{ host: { class: 'sce-featured-office-card' }, selector: 'sce-featured-office-card', standalone: true, imports: [RouterLink, TranslatePipe, SceIcon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<article class=\"featured-office-card\">\n <!-- Right Side (Start side): Avatar + Meta Details -->\n <div class=\"office-lead-group\">\n <div class=\"office-avatar-wrap\">\n <img src=\"/assets/icons/avatar.svg\" width=\"64\" height=\"64\" alt=\"\" aria-hidden=\"true\" class=\"office-avatar\" />\n </div>\n\n <div class=\"office-meta-details\">\n <div class=\"office-title-row\">\n <h3 class=\"office-title\">{{ office().title }}</h3>\n <sce-icon name=\"checkmark-badge\" [size]=\"16\" class=\"office-checkmark\" aria-hidden=\"true\" />\n </div>\n\n <div class=\"office-stats-row\">\n <span class=\"office-rating-badge\">\n <img src=\"/assets/icons/star copy.svg\" width=\"12\" height=\"12\" alt=\"\" aria-hidden=\"true\" class=\"rating-star\" />\n <span class=\"office-rating-value\">{{ office().rating }}</span>\n </span>\n\n <span class=\"office-separator\" aria-hidden=\"true\">\u2022</span>\n\n <span class=\"office-review-count\">\n @if (office().reviewCount > 0) {\n {{ office().reviewCountLabel }} {{ 'dashboard.overview.reviewCountSuffix' | translate }}\n } @else {\n {{ 'dashboard.overview.noReviewsYet' | translate }}\n }\n </span>\n\n <span class=\"office-separator\" aria-hidden=\"true\">\u2022</span>\n\n <span class=\"office-location\">\n <img src=\"/assets/icons/location.svg\" width=\"14\" height=\"14\" alt=\"\" aria-hidden=\"true\" class=\"location-icon\" />\n {{ office().country }}\n </span>\n </div>\n </div>\n </div>\n\n <!-- Middle: Dynamic Capsule Tags -->\n @if (office().tabs.length) {\n <div class=\"office-tags-wrap\">\n @for (tab of office().tabs; track tab) {\n <span class=\"office-tag\">{{ tab }}</span>\n }\n </div>\n }\n\n <!-- Left Side (End side): Action Button \"\u0639\u0631\u0636 \u0627\u0644\u0645\u0644\u0641\" -->\n <a [routerLink]=\"office().href\" class=\"office-profile-btn\">\n <span class=\"btn-text\">{{ 'dashboard.overview.viewProfile' | translate }}</span>\n <span class=\"arrow-icon\" aria-hidden=\"true\">\n <img src=\"/assets/icons/arrow-left.svg\" width=\"12\" height=\"12\" alt=\"\" />\n </span>\n </a>\n</article>\n", styles: [":host{display:block;width:100%}.featured-office-card{position:relative;display:flex;align-items:center;justify-content:space-between;gap:var(--space-24);background:var(--surface-primary, var(--color-white));border:1px solid var(--color-border);border-radius:var(--radius-2xl);padding:var(--space-16) var(--space-24);width:100%;box-sizing:border-box;transition:transform .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1);min-width:0}.featured-office-card:hover{transform:translateY(-2px);box-shadow:0 12px 24px #1018280f;border-color:var(--color-primary-200, var(--color-input-border))}.office-lead-group{display:flex;align-items:center;gap:var(--space-16);flex:1;min-width:0}.office-avatar-wrap{width:var(--space-64);height:var(--space-64);border-radius:var(--radius-xl);overflow:hidden;flex-shrink:0;background:var(--color-neutral-100, var(--color-neutral-100));display:flex;align-items:center;justify-content:center;border:1px solid var(--color-border)}.office-avatar-wrap .office-avatar{width:100%;height:100%;object-fit:cover}.office-meta-details{display:flex;flex-direction:column;gap:var(--space-6);min-width:0;text-align:start}.office-title-row{display:flex;align-items:center;gap:var(--space-6);min-width:0}.office-title{margin:0;font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-lg);font-weight:700;color:var(--text-text-primary-900, var(--text-primary-default));line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.office-checkmark{flex-shrink:0}.office-stats-row{display:flex;align-items:center;gap:var(--space-8);flex-wrap:wrap;font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-sm);color:var(--text-text-secondary-600, var(--color-subtle));line-height:1.4}.office-rating-badge{display:inline-flex;direction:ltr;align-items:center;gap:var(--space-4);background:var(--color-warning-50, var(--color-warning-100));border-radius:var(--space-100);padding:var(--space-2) var(--space-8);flex-shrink:0}.office-rating-value{font-size:var(--font-size-xs);font-weight:700;color:var(--text-text-primary-900, var(--text-primary-default));line-height:1}.rating-star{flex-shrink:0}.office-separator{color:var(--color-black);font-weight:700;font-size:var(--font-size-lg);-webkit-user-select:none;user-select:none;margin-block-end:.4rem}.office-projects-count{font-weight:500}.office-location{display:inline-flex;align-items:center;gap:var(--space-4);font-weight:500}.location-icon{flex-shrink:0}.office-tags-wrap{display:flex;align-items:center;gap:var(--space-8);flex-wrap:wrap;justify-content:center}.office-tag{background:var(--background-bg-secondary, var(--app-canvas-bg));border:1px solid var(--color-border);color:var(--text-text-secondary-700);font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-xs);font-weight:500;padding:var(--space-6) var(--space-14);border-radius:var(--space-100);white-space:nowrap}.office-profile-btn{position:relative;z-index:2;display:inline-flex;align-items:center;gap:var(--space-8);background:var(--background-bg-secondary, var(--app-canvas-bg));color:var(--text-text-primary-900, var(--text-primary-default));font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-md);font-weight:600;padding:var(--space-8) var(--space-20);border-radius:var(--space-100);text-decoration:none;transition:background-color .2s ease,transform .2s ease;flex-shrink:0}.office-profile-btn:hover{background:var(--color-border)}.arrow-icon{display:inline-flex;align-items:center;justify-content:center;transition:transform .2s ease}.featured-office-card:hover .office-profile-btn{background:var(--color-border)}.featured-office-card:hover .arrow-icon{transform:translate(-4px)}:host-context([dir=ltr]) .featured-office-card:hover .arrow-icon{transform:translate(4px)}:host-context([dir=ltr]) .arrow-icon{transform:rotate(180deg)}@media(max-width:992px){.featured-office-card{flex-direction:column;align-items:stretch;gap:var(--space-16);padding:var(--space-20)}.office-tags-wrap{justify-content:flex-start}.office-profile-btn{align-self:flex-start;width:100%;justify-content:center}}@media(max-width:480px){.office-avatar-wrap{width:var(--space-52, var(--size-52));height:var(--space-52, var(--size-52))}.office-title{font-size:var(--font-size-md-15)}.office-stats-row{font-size:var(--font-size-xs);gap:var(--space-6)}.office-profile-btn{padding:var(--space-10) var(--space-16)}}\n"] }]
|
|
8065
8184
|
}], propDecorators: { office: [{ type: i0.Input, args: [{ isSignal: true, alias: "office", required: true }] }] } });
|
|
8066
8185
|
|
|
8186
|
+
/** Dashboard card summarising a contract request (office, location, deadline, budget) with tone-resolved tags, linking to its detail route. */
|
|
8067
8187
|
class SceContractRequestCardComponent {
|
|
8068
8188
|
request = input.required(...(ngDevMode ? [{ debugName: "request" }] : /* istanbul ignore next */ []));
|
|
8069
8189
|
tagTones = computed(() => this.request().tags.map(tag => resolveBusinessStatusTone(tag)), ...(ngDevMode ? [{ debugName: "tagTones" }] : /* istanbul ignore next */ []));
|
|
@@ -8075,6 +8195,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
8075
8195
|
args: [{ host: { class: 'sce-contract-request-card' }, selector: 'sce-contract-request-card', standalone: true, imports: [RouterLink, TranslatePipe, SceBusinessStatusTagComponent, SceBidiIsolate], changeDetection: ChangeDetectionStrategy.OnPush, template: "<a [routerLink]=\"'/dashboard/contracts-requests/' + request().id\" [queryParams]=\"{ source: 'contracts-requests' }\" class=\"request-card\">\n <!-- Tags Row (Start side) -->\n <div class=\"tags-row\">\n @for (tag of request().tags; track tag; let i = $index) {\n <sce-business-status-tag [label]=\"tag\" [tone]=\"tagTones()[i]\" size=\"sm\" />\n }\n </div>\n\n <!-- Title (Start side) -->\n <h3 class=\"card-title\">{{ request().title }}</h3>\n\n <!-- Meta Subtitle (Start side) -->\n <div class=\"card-meta\">\n <span class=\"meta-item\"\n ><sce-bidi-isolate>{{ request().requestNumber }}</sce-bidi-isolate></span\n >\n <span class=\"meta-divider\" aria-hidden=\"true\">•</span>\n <span class=\"meta-item brand-name\">{{ request().officeName }}</span>\n </div>\n\n <!-- Divider -->\n <hr class=\"card-divider\" />\n\n <!-- Details List -->\n <div class=\"card-details\">\n <!-- Row 1: Location -->\n <div class=\"detail-row\">\n <span class=\"detail-label\">\n <img src=\"/assets/icons/location.svg\" width=\"17\" height=\"18\" alt=\"\" aria-hidden=\"true\" class=\"detail-icon\" />\n {{ 'dashboard.overview.locationLabel' | translate }}\n </span>\n <span class=\"detail-value\">{{ request().location }}</span>\n </div>\n\n <!-- Row 2: Deadline -->\n <div class=\"detail-row\">\n <span class=\"detail-label\">\n <img src=\"/assets/icons/calendar-04.svg\" width=\"17\" height=\"18\" alt=\"\" aria-hidden=\"true\" class=\"detail-icon\" />\n {{ 'dashboard.overview.deadlineLabel' | translate }}\n </span>\n <span class=\"detail-value\"\n ><sce-bidi-isolate>{{ request().deadline }}</sce-bidi-isolate></span\n >\n </div>\n\n <!-- Row 3: Offers -->\n @if (request().offersCount !== undefined) {\n <div class=\"detail-row\">\n <span class=\"detail-label\">\n <img\n src=\"/assets/icons/nav-contracts-requests.svg\"\n width=\"17\"\n height=\"18\"\n alt=\"\"\n aria-hidden=\"true\"\n class=\"detail-icon\"\n style=\"filter: grayscale(1) opacity(0.7)\"\n />\n {{ 'dashboard.overview.offersLabel' | translate }}\n </span>\n <span class=\"detail-value\"> {{ request().offersCount }} {{ 'dashboard.overview.offersSuffix' | translate }} </span>\n </div>\n }\n </div>\n\n <!-- Budget Section (Bottom Row) -->\n <div class=\"budget-section\">\n <span class=\"budget-label\">{{ 'dashboard.overview.budgetLabel' | translate }}</span>\n <span class=\"budget-value\">\n @if (request().budget && request().budget !== '\u2014') {\n <!-- The Rial sign (U+FDFC) is a strong-RTL character \u2014 isolate it with the\n amount so it can't reorder the number in an LTR (English) layout. -->\n <sce-bidi-isolate>\n <span class=\"budget-amount\">{{ request().budget }}</span>\n <span class=\"currency-symbol\">﷼</span>\n </sce-bidi-isolate>\n } @else {\n <span class=\"budget-amount-empty\">{{ 'common.notSpecified' | translate }}</span>\n }\n </span>\n </div>\n</a>\n", styles: [":host{display:block;width:100%}.request-card{display:flex;flex-direction:column;background:var(--surface-primary, var(--color-white));border:1px solid var(--color-border);box-shadow:0 1px 3px #1018280d,0 1px 2px #10182808;border-radius:var(--space-20);padding:var(--space-24);text-decoration:none;color:inherit;box-sizing:border-box;height:100%;transition:transform .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1)}@media(prefers-reduced-motion:no-preference){.request-card:hover{transform:translateY(-4px);box-shadow:0 12px 24px #10182814;border-color:#0000000d}}.tags-row{display:flex;flex-wrap:wrap;gap:var(--space-8);justify-content:flex-start}.card-title{margin:var(--space-16) 0 var(--space-8) 0;font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-xl);font-weight:700;color:var(--text-text-primary-900, var(--text-primary-default));text-align:start;line-height:1.3}.card-meta{display:flex;align-items:center;gap:var(--space-6);font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-md);font-weight:500;color:var(--text-text-secondary-600, var(--color-subtle));text-align:start;margin-block-end:var(--space-16)}.brand-name{color:var(--text-text-brand-primary, var(--color-brand-primary-600))}.meta-divider{color:var(--color-input-border)}.card-divider{border:0;border-block-start:1px solid var(--color-neutral-100);margin:0 0 var(--space-16) 0;width:100%}.card-details{display:flex;flex-direction:column;gap:var(--space-12);margin-block-end:var(--space-16)}.detail-row{display:flex;justify-content:space-between;align-items:center;font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-md);font-weight:500}.detail-label{display:inline-flex;align-items:center;gap:var(--space-8);color:var(--text-text-secondary-600, var(--color-subtle))}.detail-icon{display:block}.detail-value{color:var(--text-text-primary-900, var(--text-primary-default));font-weight:600}.budget-section{display:flex;justify-content:space-between;align-items:center;background:var(--background-bg-secondary, var(--color-surface-2));border-radius:var(--radius-xl);padding:var(--space-12) var(--space-16);width:100%;box-sizing:border-box;margin-block-start:auto}.budget-label{font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-md);font-weight:500;color:var(--text-text-secondary-600, var(--color-muted-fg))}.budget-value{display:inline-flex;align-items:center;gap:var(--space-4);font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-lg-18);font-weight:700;color:var(--text-text-primary-900, var(--text-primary-default))}.currency-symbol{font-size:var(--font-size-lg);font-weight:600;color:var(--text-text-secondary-600, var(--color-muted-fg))}.budget-amount-empty{font-size:var(--font-size-md);font-weight:500;color:var(--text-text-secondary-600, var(--color-subtle))}\n"] }]
|
|
8076
8196
|
}], propDecorators: { request: [{ type: i0.Input, args: [{ isSignal: true, alias: "request", required: true }] }] } });
|
|
8077
8197
|
|
|
8198
|
+
/** Dashboard table of the latest contracts with status tags, showing five skeleton rows while `loading`; the party column header label is caller-supplied. */
|
|
8078
8199
|
class SceLatestContractsTableComponent {
|
|
8079
8200
|
contracts = input.required(...(ngDevMode ? [{ debugName: "contracts" }] : /* istanbul ignore next */ []));
|
|
8080
8201
|
partyColumnLabel = input.required(...(ngDevMode ? [{ debugName: "partyColumnLabel" }] : /* istanbul ignore next */ []));
|
|
@@ -8088,6 +8209,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
8088
8209
|
args: [{ host: { class: 'sce-latest-contracts-table' }, selector: 'sce-latest-contracts-table', standalone: true, imports: [RouterLink, TranslatePipe, SceBusinessStatusTagComponent, SceSkeleton, SceBidiIsolate], changeDetection: ChangeDetectionStrategy.OnPush, template: "<section class=\"block\" data-tour=\"dashboard-contracts\">\n <div class=\"sectionHeader\">\n <h2 class=\"sectionTitle\">{{ 'dashboard.sections.latestContracts' | translate }}</h2>\n <a routerLink=\"/dashboard/contracts\" class=\"viewAllLink\">{{ 'dashboard.overview.viewAll' | translate }}</a>\n </div>\n\n <div class=\"contractTableWrap\">\n <table class=\"contractTable\">\n <thead>\n <tr>\n <th>{{ 'dashboard.overview.table.contractNumber' | translate }}</th>\n <th>{{ 'dashboard.overview.table.service' | translate }}</th>\n <th>{{ partyColumnLabel() }}</th>\n <th>{{ 'dashboard.overview.table.completionDate' | translate }}</th>\n <th>{{ 'dashboard.overview.table.projectStatus' | translate }}</th>\n </tr>\n </thead>\n <tbody>\n @if (loading()) {\n @for (row of skeletonRows(); track row) {\n <tr>\n <td><sce-skeleton variant=\"text\" animation=\"wave\" width=\"80px\" /></td>\n <td><sce-skeleton variant=\"text\" animation=\"wave\" /></td>\n <td><sce-skeleton variant=\"text\" animation=\"wave\" /></td>\n <td><sce-skeleton variant=\"text\" animation=\"wave\" width=\"90px\" /></td>\n <td><sce-skeleton variant=\"rounded\" animation=\"wave\" width=\"72px\" height=\"24px\" /></td>\n </tr>\n }\n } @else {\n @for (row of contracts(); track row.contractNumber) {\n <tr>\n <td>\n <span class=\"contract-number\">\n <sce-bidi-isolate [value]=\"row.contractNumber\" tabular />\n </span>\n </td>\n <td>{{ row.service }}</td>\n <td>{{ row.client }}</td>\n <td>{{ row.endDate }}</td>\n <td>\n <sce-business-status-tag [label]=\"row.status\" [tone]=\"row.statusVariant\" />\n </td>\n </tr>\n }\n @if (contracts().length === 0) {\n <tr>\n <td colspan=\"5\" class=\"table-empty-cell\">\n {{ 'dashboard.overview.tableEmpty' | translate }}\n </td>\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n</section>\n", styles: [":host{display:block;width:100%}.block{background:var(--surface-primary);border:1px solid var(--color-primary-100);border-radius:var(--radius-2xl, var(--radius-2xl));padding:var(--space-24);display:grid;gap:var(--space-12);width:100%;box-sizing:border-box}.sectionHeader{display:flex;justify-content:space-between;align-items:center;gap:var(--space-12);width:100%}.sectionTitle{margin:0;font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-xl, var(--font-size-xl));font-weight:700;color:var(--text-text-primary-900, var(--color-neutral-900))}.viewAllLink{text-decoration:none;border:1.5px solid var(--color-brand-primary-800);border-radius:var(--radius-xl);padding:var(--space-8) var(--space-16);display:inline-flex;align-items:center;justify-content:center;font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-md, var(--font-size-md));font-weight:500;color:var(--text-text-brand-primary, var(--color-brand-primary-800));transition:background-color .2s ease,color .2s ease}.viewAllLink:hover{background:var(--background-bg-secondary)}.contractTableWrap{border-radius:var(--radius-xl);overflow:hidden;border:1px solid var(--border-subtle)}.contractTable{width:100%;border-collapse:collapse}.contractTable thead th{text-align:start;padding:var(--space-12) var(--space-16);background:var(--details-row-bg, var(--color-surface-2));color:var(--form-field-text-placeholder, var(--color-neutral-400));font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-xs, var(--font-size-xs));font-weight:600}.contractTable tbody td{text-align:start;padding:var(--space-20) var(--space-16);border-block-start:1px solid var(--border-subtle);color:var(--color-text-heading-700, var(--color-neutral-700));font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-sm, var(--font-size-md));font-weight:500}.contract-number{font-weight:600;color:var(--text-text-primary-900, var(--color-neutral-900))}.table-empty-cell{padding:var(--space-32);text-align:center;color:var(--text-text-secondary-700, var(--text-text-secondary-600));font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-sm, var(--font-size-md))}@media(max-width:768px){.block{padding:var(--space-16)}.contractTableWrap{overflow-x:auto;-webkit-overflow-scrolling:touch}.contractTable{min-width:32rem}.contractTable thead th,.contractTable tbody td{padding-inline:var(--space-12);padding-block:var(--space-14);font-size:var(--font-size-xs, var(--font-size-xs))}}\n"] }]
|
|
8089
8210
|
}], propDecorators: { contracts: [{ type: i0.Input, args: [{ isSignal: true, alias: "contracts", required: true }] }], partyColumnLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "partyColumnLabel", required: true }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }] } });
|
|
8090
8211
|
|
|
8212
|
+
/** Login flow step presenting the selectable user-type cards and emitting the picked type plus a continue action. */
|
|
8091
8213
|
class SceLoginUserTypeStepComponent {
|
|
8092
8214
|
cards = input.required(...(ngDevMode ? [{ debugName: "cards" }] : /* istanbul ignore next */ []));
|
|
8093
8215
|
selectedType = input(null, ...(ngDevMode ? [{ debugName: "selectedType" }] : /* istanbul ignore next */ []));
|
|
@@ -8105,6 +8227,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
8105
8227
|
args: [{ host: { class: 'sce-login-user-type-step' }, selector: 'sce-login-user-type-step', standalone: true, imports: [TranslatePipe, Button], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"head\">\n <h2 class=\"title\">{{ 'loginModal.chooseLoginTypeTitle' | translate }}</h2>\n <p class=\"subtitle\">{{ 'loginModal.chooseLoginTypeSubtitle' | translate }}</p>\n</div>\n\n<div class=\"userTypeList\">\n @for (card of cardViews(); track card.type) {\n <button\n type=\"button\"\n class=\"userTypeCard\"\n [class.userTypeCardSelected]=\"card.selected\"\n [attr.aria-pressed]=\"card.selected\"\n (click)=\"selectType.emit(card.type)\"\n >\n <span\n class=\"userTypeIcon\"\n [class.userTypeIconPrimary]=\"card.iconVariant === 'primary'\"\n [class.userTypeIconMuted]=\"card.iconVariant === 'muted'\"\n >\n <img [src]=\"card.icon\" width=\"24\" height=\"24\" alt=\"\" aria-hidden=\"true\" />\n </span>\n <div class=\"userTypeText\">\n <span class=\"userTypeTitle\">{{ card.titleKey | translate }}</span>\n <span class=\"userTypeDesc\">{{ card.descriptionKey | translate }}</span>\n </div>\n <span class=\"userTypeRadio\" [class.userTypeRadioSelected]=\"card.selected\" aria-hidden=\"true\"></span>\n </button>\n }\n</div>\n\n<p-button type=\"button\" [label]=\"'common.continue' | translate\" styleClass=\"submit w-full\" (onClick)=\"continue.emit()\" />\n" }]
|
|
8106
8228
|
}], propDecorators: { cards: [{ type: i0.Input, args: [{ isSignal: true, alias: "cards", required: true }] }], selectedType: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedType", required: false }] }], selectType: [{ type: i0.Output, args: ["selectType"] }], continue: [{ type: i0.Output, args: ["continue"] }] } });
|
|
8107
8229
|
|
|
8230
|
+
/** Login flow step capturing national ID and birth date (Hijri/Gregorian), fully controlled — every field value and error is an input. */
|
|
8108
8231
|
class SceLoginCredentialsStepComponent {
|
|
8109
8232
|
titleKey = input.required(...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
|
|
8110
8233
|
subtitleKey = input.required(...(ngDevMode ? [{ debugName: "subtitleKey" }] : /* istanbul ignore next */ []));
|
|
@@ -8161,6 +8284,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
8161
8284
|
}]
|
|
8162
8285
|
}] });
|
|
8163
8286
|
|
|
8287
|
+
/** Login flow step with the OTP input, mask toggle and resend countdown; the timer label is supplied by the parent. */
|
|
8164
8288
|
class SceLoginOtpStepComponent {
|
|
8165
8289
|
otpValue = input.required(...(ngDevMode ? [{ debugName: "otpValue" }] : /* istanbul ignore next */ []));
|
|
8166
8290
|
showOtpVisible = input(false, ...(ngDevMode ? [{ debugName: "showOtpVisible" }] : /* istanbul ignore next */ []));
|
|
@@ -8180,6 +8304,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
8180
8304
|
args: [{ host: { class: 'sce-login-otp-step' }, selector: 'sce-login-otp-step', standalone: true, imports: [TranslatePipe, FormsModule, Button, InputOtp, SceSkeleton, SceOtpAriaDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"head\">\n <h2 class=\"title\">{{ 'loginModal.otpTitle' | translate }}</h2>\n <p class=\"subtitle\">{{ 'loginModal.otpSubtitle' | translate }}</p>\n</div>\n\n<div class=\"form\">\n <div class=\"otpRow\">\n <div class=\"otpContainer\" [class.otpMasked]=\"!showOtpVisible()\" [class.otpInvalid]=\"otpError()\">\n <p-inputotp sceOtpAria [ngModel]=\"otpValue()\" (ngModelChange)=\"otpValueChange.emit($event)\" [length]=\"6\" [integerOnly]=\"true\" />\n </div>\n <button\n type=\"button\"\n class=\"otpToggleBtn\"\n (click)=\"showOtpToggle.emit()\"\n [attr.aria-pressed]=\"showOtpVisible()\"\n [attr.aria-label]=\"(showOtpVisible() ? 'loginModal.otpHide' : 'loginModal.otpShow') | translate\"\n >\n <i [class]=\"showOtpVisible() ? 'pi pi-eye-slash' : 'pi pi-eye'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n @if (otpError()) {\n <div class=\"otpError\" role=\"alert\">{{ otpError() }}</div>\n }\n\n <p class=\"resendRow\">\n <button type=\"button\" class=\"resendBtn\" [disabled]=\"resendSeconds() > 0 || submitting()\" (click)=\"resend.emit()\">\n {{ 'loginModal.resendOtp' | translate }}\n ({{ resendTimerLabel() }})\n </button>\n <span class=\"resendHint\">{{ 'loginModal.didNotReceiveCode' | translate }}</span>\n </p>\n\n <p-button\n type=\"button\"\n styleClass=\"submit w-full\"\n [ariaLabel]=\"'loginModal.otpSubmit' | translate\"\n [disabled]=\"submitting()\"\n (onClick)=\"submitted.emit()\"\n >\n @if (submitting()) {\n <sce-skeleton variant=\"text\" width=\"7rem\" height=\"1rem\" animation=\"wave\" aria-hidden=\"true\" />\n } @else {\n {{ 'loginModal.otpSubmit' | translate }}\n }\n </p-button>\n</div>\n" }]
|
|
8181
8305
|
}], propDecorators: { otpValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "otpValue", required: true }] }], showOtpVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "showOtpVisible", required: false }] }], otpError: [{ type: i0.Input, args: [{ isSignal: true, alias: "otpError", required: false }] }], resendSeconds: [{ type: i0.Input, args: [{ isSignal: true, alias: "resendSeconds", required: false }] }], submitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitting", required: false }] }], resendTimerLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "resendTimerLabel", required: true }] }], otpValueChange: [{ type: i0.Output, args: ["otpValueChange"] }], showOtpToggle: [{ type: i0.Output, args: ["showOtpToggle"] }], resend: [{ type: i0.Output, args: ["resend"] }], submitted: [{ type: i0.Output, args: ["submitted"] }] } });
|
|
8182
8306
|
|
|
8307
|
+
/** Login flow step that lists the accounts available to the authenticated user and emits the chosen account id. */
|
|
8183
8308
|
class SceLoginAccountSelectStepComponent {
|
|
8184
8309
|
accounts = input.required(...(ngDevMode ? [{ debugName: "accounts" }] : /* istanbul ignore next */ []));
|
|
8185
8310
|
selectedAccountId = input(null, ...(ngDevMode ? [{ debugName: "selectedAccountId" }] : /* istanbul ignore next */ []));
|
|
@@ -8195,6 +8320,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
8195
8320
|
args: [{ host: { class: 'sce-login-account-select-step' }, selector: 'sce-login-account-select-step', standalone: true, imports: [TranslatePipe, Button, SceDashboardAccountRoleIconComponent, SceInlineApiErrorComponent, SceSkeleton], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"selectAccountLayout\">\n <div class=\"head\">\n <h2 class=\"title\">{{ 'loginModal.selectAccountTitle' | translate }}</h2>\n <p class=\"subtitle\">{{ 'loginModal.selectAccountSubtitle' | translate }}</p>\n </div>\n\n <div class=\"accountList\">\n @for (account of accounts(); track account.id) {\n <button\n type=\"button\"\n class=\"accountCard\"\n [class.accountCardSelected]=\"selectedAccountId() === account.id\"\n [attr.aria-pressed]=\"selectedAccountId() === account.id\"\n (click)=\"selectAccount.emit(account.id)\"\n >\n <div class=\"accountAvatar\">\n <sce-dashboard-account-role-icon\n [role]=\"$any(account.role)\"\n [accountKind]=\"account.kind\"\n [alt]=\"account.name\"\n [width]=\"56\"\n [height]=\"56\"\n [photoUrl]=\"account.avatarSrc ?? null\"\n />\n </div>\n <div class=\"accountInfo\">\n <span class=\"accountNameRow\">\n <span class=\"accountName\">{{ account.name }}</span>\n <span class=\"accountTag\">{{ account.tag }}</span>\n </span>\n <span class=\"accountDescription\">{{ account.description }}</span>\n </div>\n <span class=\"accountRadio\" [class.accountRadioSelected]=\"selectedAccountId() === account.id\" aria-hidden=\"true\"></span>\n </button>\n }\n </div>\n\n <div class=\"selectAccountFooter\">\n @if (apiError()) {\n <sce-inline-api-error [message]=\"apiError()!\" />\n }\n <p-button\n type=\"button\"\n styleClass=\"submit w-full\"\n [ariaLabel]=\"'loginModal.enterPlatform' | translate\"\n [disabled]=\"submitting()\"\n (onClick)=\"submitted.emit()\"\n >\n @if (submitting()) {\n <sce-skeleton variant=\"text\" width=\"7rem\" height=\"1rem\" animation=\"wave\" aria-hidden=\"true\" />\n } @else {\n {{ 'loginModal.enterPlatform' | translate }}\n }\n </p-button>\n </div>\n</div>\n" }]
|
|
8196
8321
|
}], propDecorators: { accounts: [{ type: i0.Input, args: [{ isSignal: true, alias: "accounts", required: true }] }], selectedAccountId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedAccountId", required: false }] }], apiError: [{ type: i0.Input, args: [{ isSignal: true, alias: "apiError", required: false }] }], submitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitting", required: false }] }], selectAccount: [{ type: i0.Output, args: ["selectAccount"] }], submitted: [{ type: i0.Output, args: ["submitted"] }] } });
|
|
8197
8322
|
|
|
8323
|
+
/** Login flow step collecting the missing mobile and email of a profile, emitting each change and the final submit. */
|
|
8198
8324
|
class SceLoginCompleteDataStepComponent {
|
|
8199
8325
|
mobile = input.required(...(ngDevMode ? [{ debugName: "mobile" }] : /* istanbul ignore next */ []));
|
|
8200
8326
|
email = input.required(...(ngDevMode ? [{ debugName: "email" }] : /* istanbul ignore next */ []));
|
|
@@ -8212,6 +8338,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
8212
8338
|
args: [{ host: { class: 'sce-login-complete-data-step' }, selector: 'sce-login-complete-data-step', standalone: true, imports: [TranslatePipe, Button, SceTextFieldComponent, SceSkeleton], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"head\">\n <h2 class=\"title\">{{ 'loginModal.completeDataTitle' | translate }}</h2>\n <p class=\"subtitle\">{{ 'loginModal.completeDataSubtitle' | translate }}</p>\n</div>\n\n<div class=\"form\">\n <sce-text-field\n id=\"login-mobile\"\n [label]=\"'loginModal.mobileNumber' | translate\"\n [value]=\"mobile()\"\n [error]=\"mobileError()\"\n (valueChange)=\"mobileChange.emit($event)\"\n />\n <sce-text-field\n id=\"login-email\"\n [label]=\"'loginModal.email' | translate\"\n [value]=\"email()\"\n [error]=\"emailError()\"\n (valueChange)=\"emailChange.emit($event)\"\n />\n <p-button\n type=\"button\"\n styleClass=\"submit w-full\"\n [ariaLabel]=\"'loginModal.saveAndContinue' | translate\"\n [disabled]=\"submitting()\"\n (onClick)=\"submitted.emit()\"\n >\n @if (submitting()) {\n <sce-skeleton variant=\"text\" width=\"7rem\" height=\"1rem\" animation=\"wave\" aria-hidden=\"true\" />\n } @else {\n {{ 'loginModal.saveAndContinue' | translate }}\n }\n </p-button>\n</div>\n" }]
|
|
8213
8339
|
}], propDecorators: { mobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobile", required: true }] }], email: [{ type: i0.Input, args: [{ isSignal: true, alias: "email", required: true }] }], mobileError: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileError", required: false }] }], emailError: [{ type: i0.Input, args: [{ isSignal: true, alias: "emailError", required: false }] }], submitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitting", required: false }] }], mobileChange: [{ type: i0.Output, args: ["mobileChange"] }], emailChange: [{ type: i0.Output, args: ["emailChange"] }], submitted: [{ type: i0.Output, args: ["submitted"] }] } });
|
|
8214
8340
|
|
|
8341
|
+
/** Login flow step showing a failure message with a retry action. */
|
|
8215
8342
|
class SceLoginErrorStepComponent {
|
|
8216
8343
|
errorMessage = input(...(ngDevMode ? [undefined, { debugName: "errorMessage" }] : /* istanbul ignore next */ []));
|
|
8217
8344
|
submitting = input(false, ...(ngDevMode ? [{ debugName: "submitting" }] : /* istanbul ignore next */ []));
|
|
@@ -8224,6 +8351,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
8224
8351
|
args: [{ host: { class: 'sce-login-error-step' }, selector: 'sce-login-error-step', standalone: true, imports: [TranslatePipe, Button, SceIcon, SceSkeleton], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"errorStep\">\n <div class=\"errorIconWrap\">\n <sce-icon name=\"alert-01\" [size]=\"52\" aria-hidden=\"true\" />\n </div>\n <h2 class=\"errorTitle\" role=\"alert\">\n {{ errorMessage() || ('loginModal.verifyFailedTitle' | translate) }}\n </h2>\n @if (!errorMessage()) {\n <p class=\"errorSubtitle\">{{ 'loginModal.verifyFailedSubtitle' | translate }}</p>\n }\n <p-button\n type=\"button\"\n styleClass=\"submit w-full\"\n [ariaLabel]=\"'loginModal.tryAgain' | translate\"\n [disabled]=\"submitting()\"\n (onClick)=\"retry.emit()\"\n >\n @if (submitting()) {\n <sce-skeleton variant=\"text\" width=\"7rem\" height=\"1rem\" animation=\"wave\" aria-hidden=\"true\" />\n } @else {\n {{ 'loginModal.tryAgain' | translate }}\n }\n </p-button>\n</div>\n", styles: [":host{display:block}.errorStep{display:flex;flex-direction:column;align-items:center;text-align:center;gap:var(--space-16);padding-block-start:var(--space-8)}.errorIconWrap{width:var(--space-80);height:var(--space-80);border-radius:var(--radius-2xl);display:flex;align-items:center;justify-content:center}.errorTitle{margin:0;font-weight:var(--font-weight-bold);font-size:var(--font-size-xl);line-height:var(--line-height-normal);color:var(--text-text-primary-900);white-space:pre-wrap}.errorSubtitle{font-weight:var(--font-weight-regular);font-size:var(--font-size-lg);color:var(--text-text-secondary-700)}\n"] }]
|
|
8225
8352
|
}], propDecorators: { errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], submitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitting", required: false }] }], retry: [{ type: i0.Output, args: ["retry"] }] } });
|
|
8226
8353
|
|
|
8354
|
+
/** Landing-page hero header with a title, breadcrumb trail and optional background image, rendered either as decorative left-aligned artwork or as a full-bleed cover photo. */
|
|
8227
8355
|
class SceLandingHeroHeaderComponent {
|
|
8228
8356
|
title = input(...(ngDevMode ? [undefined, { debugName: "title" }] : /* istanbul ignore next */ []));
|
|
8229
8357
|
breadcrumbs = input([], ...(ngDevMode ? [{ debugName: "breadcrumbs" }] : /* istanbul ignore next */ []));
|
|
@@ -8259,6 +8387,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
8259
8387
|
args: [{ host: { class: 'sce-dashboard-feature-coming-soon' }, selector: 'sce-dashboard-feature-coming-soon', standalone: true, imports: [SceEmptyStateComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<section class=\"sce-dashboard-feature-coming-soon__panel\">\n <sce-empty-state [titleKey]=\"titleKey()\" [subtitleKey]=\"subtitleKey()\" [icon]=\"icon()\" [compact]=\"false\" tone=\"info\" />\n</section>\n", styles: [":host{display:block;width:100%}.sce-dashboard-feature-coming-soon__panel{display:flex;align-items:center;justify-content:center;min-block-size:var(--space-320, 20rem);padding:var(--space-8)}\n"] }]
|
|
8260
8388
|
}], propDecorators: { titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: true }] }], subtitleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitleKey", required: true }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }] } });
|
|
8261
8389
|
|
|
8390
|
+
/** Cell renderer selected for a `GridColumn` (text, status tag, progress bar, toggle, action button/menu, custom template…). */
|
|
8262
8391
|
var ColumnsEnum;
|
|
8263
8392
|
(function (ColumnsEnum) {
|
|
8264
8393
|
ColumnsEnum["TOGGLE"] = "toggle";
|
|
@@ -8338,6 +8467,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
8338
8467
|
args: [{ name: 'statusConfig', standalone: true }]
|
|
8339
8468
|
}] });
|
|
8340
8469
|
|
|
8470
|
+
/** Marks an `<ng-template sceCustomCol="columnDef">` inside `sce-grid-table` as the renderer for the column whose `columnDef` matches. */
|
|
8341
8471
|
class SceCustomColsDirective {
|
|
8342
8472
|
sceCustomCol = input.required(...(ngDevMode ? [{ debugName: "sceCustomCol" }] : /* istanbul ignore next */ []));
|
|
8343
8473
|
templateRef = inject((TemplateRef));
|
|
@@ -8352,6 +8482,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
8352
8482
|
}]
|
|
8353
8483
|
}], propDecorators: { sceCustomCol: [{ type: i0.Input, args: [{ isSignal: true, alias: "sceCustomCol", required: true }] }] } });
|
|
8354
8484
|
|
|
8485
|
+
/** Marks an `<ng-template sceGridExpansion>` as the expanded-row body of `sce-grid-table`; the row is passed as `$implicit`. */
|
|
8355
8486
|
class SceGridExpansionDirective {
|
|
8356
8487
|
templateRef = inject((TemplateRef));
|
|
8357
8488
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SceGridExpansionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
@@ -8366,6 +8497,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
8366
8497
|
}] });
|
|
8367
8498
|
|
|
8368
8499
|
const GRID_TABLE_LOADING_DELAY_MS = 300;
|
|
8500
|
+
/** PrimeNG-backed data table driven by a `columns` config: renders typed cells, row actions/menus, selection, expandable rows and skeletons, and switches between empty, filtered, searched and error result states; supports both client-side and `lazy` server-side paging/sorting, emitting `pageChange`/`sortChange` rather than fetching itself. */
|
|
8369
8501
|
class SceGridTableComponent {
|
|
8370
8502
|
showSelect = input(false, ...(ngDevMode ? [{ debugName: "showSelect" }] : /* istanbul ignore next */ []));
|
|
8371
8503
|
btnLabel = input('table.addNewCard', ...(ngDevMode ? [{ debugName: "btnLabel" }] : /* istanbul ignore next */ []));
|
|
@@ -8689,6 +8821,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
8689
8821
|
}], ctorParameters: () => [], propDecorators: { showSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSelect", required: false }] }], btnLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "btnLabel", required: false }] }], selectedItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItems", required: false }] }, { type: i0.Output, args: ["selectedItemsChange"] }], searchPipeKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPipeKey", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], showAddButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAddButton", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], loadingDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingDelay", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], rowsPerPageOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowsPerPageOptions", required: false }] }], pagination: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagination", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], totalRecords: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalRecords", required: false }] }], totalPages: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalPages", required: false }] }], pageNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageNumber", required: false }] }], first: [{ type: i0.Input, args: [{ isSignal: true, alias: "first", required: false }] }], tableMinWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "tableMinWidth", required: false }] }], emptyStateIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyStateIcon", required: false }] }], emptyStateTitleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyStateTitleKey", required: false }] }], emptyStateSubtitleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyStateSubtitleKey", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], errorTitleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorTitleKey", required: false }] }], errorSubtitleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorSubtitleKey", required: false }] }], errorStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorStatus", required: false }] }], filtered: [{ type: i0.Input, args: [{ isSignal: true, alias: "filtered", required: false }] }], searching: [{ type: i0.Input, args: [{ isSignal: true, alias: "searching", required: false }] }], sortField: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortField", required: false }] }], sortOrder: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortOrder", required: false }] }], rowRoute: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowRoute", required: false }] }], rowClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowClass", required: false }] }], addActionEvent: [{ type: i0.Output, args: ["addActionEvent"] }], searchQuery: [{ type: i0.Output, args: ["searchQuery"] }], selectItems: [{ type: i0.Output, args: ["selectItems"] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], errorRetry: [{ type: i0.Output, args: ["errorRetry"] }], clearFilters: [{ type: i0.Output, args: ["clearFilters"] }], clearSearch: [{ type: i0.Output, args: ["clearSearch"] }], rowNavigate: [{ type: i0.Output, args: ["rowNavigate"] }], customColumnTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => SceCustomColsDirective), { isSignal: true }] }], expansionTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SceGridExpansionDirective), { isSignal: true }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }] } });
|
|
8690
8822
|
|
|
8691
8823
|
const MULTI_TYPES = new Set(['checkbox', 'checkbox-search', 'multiselect', 'date-range']);
|
|
8824
|
+
/** Renders a filter bar from a declarative `config` (it is not a reactive form — values live in a plain `model` signal), emits `filterChange` debounced (default 300 ms), sanitises typed text against HTML/script injection, and can show a quick-filter chip bar with per-chip removal. */
|
|
8692
8825
|
class SceFilterFormComponent {
|
|
8693
8826
|
config = input.required(...(ngDevMode ? [{ debugName: "config" }] : /* istanbul ignore next */ []));
|
|
8694
8827
|
quickFilterTitle = input('', ...(ngDevMode ? [{ debugName: "quickFilterTitle" }] : /* istanbul ignore next */ []));
|
|
@@ -8879,6 +9012,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
8879
9012
|
args: [{ host: { class: 'sce-filter-form' }, selector: 'sce-filter-form', standalone: true, imports: [FormsModule, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<form class=\"sce-filter-form\" (submit)=\"$event.preventDefault(); onSubmit()\">\n <div class=\"sce-filter-form__grid\" [style.grid-template-columns]=\"gridTemplateColumns()\">\n @for (field of config().fields; track field.key) {\n <div class=\"sce-filter-form__cell\" [style.grid-column]=\"config().columns != null ? 'span ' + (field.colspan ?? 1) : ''\">\n @if (field.type === 'divider') {\n <hr class=\"sce-filter-form__divider\" />\n } @else if (field.type === 'select') {\n <div class=\"sce-filter-form__field\">\n @if (field.label) {\n <label class=\"sce-filter-form__label\" [for]=\"'filter-' + field.key\">{{ field.label | translate }}</label>\n }\n <select\n class=\"sce-filter-form__select\"\n [id]=\"'filter-' + field.key\"\n [attr.aria-label]=\"field.label ? null : (field.placeholder ?? field.key | translate)\"\n [disabled]=\"field.disabled ?? false\"\n [value]=\"fieldStringValues()[field.key]\"\n (change)=\"onSelectChange(field.key, $event)\"\n >\n @if (field.placeholder) {\n <option value=\"\">{{ field.placeholder | translate }}</option>\n }\n @for (opt of field.options ?? []; track opt.value) {\n <option [value]=\"opt.value\">{{ opt.label | translate }}</option>\n }\n </select>\n </div>\n } @else if (field.type === 'search') {\n <div class=\"sce-filter-form__field\">\n @if (field.label) {\n <label class=\"sce-filter-form__label\" [for]=\"'filter-' + field.key\">{{ field.label | translate }}</label>\n }\n <div class=\"sce-filter-form__input-wrapper\">\n @if (field.icon && field.iconPosition !== 'end') {\n <i class=\"pi\" [class]=\"field.icon\" aria-hidden=\"true\"></i>\n }\n <input\n type=\"text\"\n class=\"sce-filter-form__input\"\n [id]=\"'filter-' + field.key\"\n [placeholder]=\"field.placeholder ? (field.placeholder | translate) : ''\"\n [disabled]=\"field.disabled ?? false\"\n [value]=\"fieldStringValues()[field.key]\"\n (input)=\"onInputChange(field.key, $event)\"\n />\n @if (field.icon && field.iconPosition === 'end') {\n <i class=\"pi\" [class]=\"field.icon\" aria-hidden=\"true\"></i>\n }\n </div>\n </div>\n } @else if (field.type === 'date' || field.type === 'datetime') {\n <div class=\"sce-filter-form__field\">\n @if (field.label) {\n <label class=\"sce-filter-form__label\" [for]=\"'filter-' + field.key\">{{ field.label | translate }}</label>\n }\n <input\n [type]=\"field.type === 'datetime' ? 'datetime-local' : 'date'\"\n class=\"sce-filter-form__input\"\n [id]=\"'filter-' + field.key\"\n [placeholder]=\"field.placeholder ? (field.placeholder | translate) : ''\"\n [disabled]=\"field.disabled ?? false\"\n [value]=\"fieldStringValues()[field.key]\"\n (input)=\"onInputChange(field.key, $event)\"\n />\n </div>\n } @else if (field.type === 'number') {\n <div class=\"sce-filter-form__field\">\n @if (field.label) {\n <label class=\"sce-filter-form__label\" [for]=\"'filter-' + field.key\">{{ field.label | translate }}</label>\n }\n <input\n type=\"number\"\n class=\"sce-filter-form__input\"\n [id]=\"'filter-' + field.key\"\n [placeholder]=\"field.placeholder ? (field.placeholder | translate) : ''\"\n [disabled]=\"field.disabled ?? false\"\n [value]=\"fieldStringValues()[field.key]\"\n (input)=\"onInputChange(field.key, $event)\"\n />\n </div>\n } @else {\n <!-- Default: text input -->\n <div class=\"sce-filter-form__field\">\n @if (field.label) {\n <label class=\"sce-filter-form__label\" [for]=\"'filter-' + field.key\">{{ field.label | translate }}</label>\n }\n <input\n type=\"text\"\n class=\"sce-filter-form__input\"\n [id]=\"'filter-' + field.key\"\n [placeholder]=\"field.placeholder ? (field.placeholder | translate) : ''\"\n [disabled]=\"field.disabled ?? false\"\n [value]=\"fieldStringValues()[field.key]\"\n (input)=\"onInputChange(field.key, $event)\"\n />\n </div>\n }\n </div>\n }\n </div>\n\n @if (showSubmit() || showReset()) {\n <div class=\"sce-filter-form__actions\">\n @if (showSubmit()) {\n <button type=\"submit\" class=\"sce-filter-form__btn sce-filter-form__btn--primary\">\n {{ 'FILTER.APPLY' | translate }}\n </button>\n }\n @if (showReset()) {\n <button type=\"button\" class=\"sce-filter-form__btn sce-filter-form__btn--ghost\" [disabled]=\"!hasActiveFilters()\" (click)=\"onReset()\">\n {{ 'FILTER.RESET' | translate }}\n </button>\n }\n </div>\n }\n\n @if (showQuickFilterBar() && hasActiveFilters()) {\n <div class=\"sce-filter-form__quick-filters\" [style.justify-content]=\"quickFilterRowJustify()\">\n <div class=\"sce-filter-form__tags\" [style.gap]=\"quickFilterTagGap()\">\n @for (tag of activeFilterTags(); track tag.key) {\n <span class=\"sce-filter-form__tag\">\n <span class=\"sce-filter-form__tag-label\">{{ tag.label | translate }}:</span>\n <span class=\"sce-filter-form__tag-value\">{{ tag.value || (tag.values ?? []).join(', ') }}</span>\n @if (showRemoveOnTag()) {\n <button\n type=\"button\"\n class=\"sce-filter-form__tag-remove\"\n (click)=\"onFilterTagClick(tag)\"\n [attr.aria-label]=\"'aria.removeFilter' | translate\"\n >\n <i class=\"pi pi-times sce-filter-form__tag-remove-icon\"></i>\n </button>\n }\n </span>\n }\n </div>\n <div class=\"sce-filter-form__quick-actions\">\n @if (showClearAll()) {\n <button type=\"button\" class=\"sce-filter-form__link-btn\" (click)=\"onClearAll()\">\n {{ 'FILTER.CLEAR_ALL' | translate }}\n </button>\n }\n @if (showSaveFilter()) {\n <button type=\"button\" class=\"sce-filter-form__link-btn\" (click)=\"saveFilterClick.emit()\">\n {{ 'FILTER.SAVE_FILTER' | translate }}\n </button>\n }\n </div>\n </div>\n }\n</form>\n", styles: ["@charset \"UTF-8\";:host{display:block}.sce-filter-form{width:100%}.sce-filter-form__divider{border:none;border-block-start:1px solid var(--color-border);margin-block-start:var(--space-12)}.sce-filter-form__grid{display:grid;align-items:end;gap:var(--space-12)}.sce-filter-form__grid>*{min-width:0}.sce-filter-form__cell{min-width:0}.sce-filter-form__field{display:flex;flex-direction:column;gap:var(--space-4);width:100%}.sce-filter-form__label{font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-text-default)}.sce-filter-form__input-wrapper{display:flex;align-items:center;gap:var(--space-8);border:1px solid var(--border-neutral-primary);border-radius:var(--radius-md);padding-block:0;padding-inline:var(--space-12);background:var(--color-white, var(--background-bg-primary));transition:border-color .15s ease}.sce-filter-form__input-wrapper:focus-within{border-color:var(--color-primary);box-shadow:0 0 0 1px var(--color-primary)}.sce-filter-form__input-wrapper .pi{color:var(--color-icon-default);font-size:var(--font-size-sm)}.sce-filter-form__input-wrapper .sce-filter-form__input{border:none;padding-inline:0;box-shadow:none}.sce-filter-form__input-wrapper .sce-filter-form__input:focus{box-shadow:none}.sce-filter-form__input,.sce-filter-form__select{width:100%;height:var(--space-36);padding-block:0;padding-inline:var(--space-12);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-text-default);background:var(--color-white, var(--background-bg-primary));border:1px solid var(--border-neutral-primary);border-radius:var(--radius-md);transition:border-color .15s ease}.sce-filter-form__input::placeholder,.sce-filter-form__select::placeholder{color:var(--form-field-text-placeholder);font-weight:var(--font-weight-medium);font-size:var(--font-size-sm)}.sce-filter-form__input:focus,.sce-filter-form__select:focus{outline:none;border-color:var(--color-primary);box-shadow:0 0 0 1px var(--color-primary)}.sce-filter-form__input:disabled,.sce-filter-form__select:disabled{opacity:.5;cursor:not-allowed}.sce-filter-form__select{appearance:none;background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e\");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-inline-end:var(--space-40)}:host-context([dir=rtl]) .sce-filter-form__select{background-position:left .5rem center}.sce-filter-form__actions{display:flex;align-items:center;gap:var(--space-8);padding-block-start:var(--space-12)}.sce-filter-form__btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-24);height:var(--space-36);padding-block:0;padding-inline:var(--space-16);border-radius:var(--radius-md);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);cursor:pointer;transition:background-color .15s ease,color .15s ease,border-color .15s ease;white-space:nowrap}.sce-filter-form__btn:disabled{opacity:.45;cursor:not-allowed}.sce-filter-form__btn--primary{background:var(--color-primary);color:var(--color-white, var(--background-bg-primary));border:1px solid var(--color-primary)}.sce-filter-form__btn--primary:not(:disabled):hover{background:var(--color-primary-dark, var(--color-primary-700));border-color:var(--color-primary-dark, var(--color-primary-700))}.sce-filter-form__btn--ghost{background:transparent;color:var(--color-text-secondary);border:1px solid var(--color-border)}.sce-filter-form__btn--ghost:not(:disabled):hover{background:var(--color-surface-subtle);color:var(--color-text-default)}.sce-filter-form__quick-filters{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-12);padding-block-start:var(--space-12)}.sce-filter-form__tags{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-8)}.sce-filter-form__tag{display:inline-flex;align-items:center;gap:var(--space-4);padding:var(--space-4) var(--space-8);background:var(--color-surface-subtle);border-radius:var(--radius-full);font-size:var(--font-size-xs);color:var(--color-text-default)}.sce-filter-form__tag-label{font-weight:var(--font-weight-medium)}.sce-filter-form__tag-value{color:var(--color-text-secondary)}.sce-filter-form__tag-remove{display:inline-flex;align-items:center;justify-content:center;width:var(--space-16);height:var(--space-16);border:none;background:transparent;cursor:pointer;color:var(--color-text-secondary);border-radius:var(--radius-full);transition:background .15s ease}.sce-filter-form__tag-remove:hover{background:var(--color-border);color:var(--color-text-default)}.sce-filter-form__tag-remove-icon{font-size:var(--font-size-xs)}.sce-filter-form__quick-actions{display:flex;align-items:center;gap:var(--space-12)}.sce-filter-form__link-btn{display:inline-flex;align-items:center;font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-primary);background:transparent;border:none;cursor:pointer;padding:0;text-decoration:none}.sce-filter-form__link-btn:hover{text-decoration:underline}@media(max-width:1280px){.sce-filter-form__grid{display:flex;flex-wrap:wrap}.sce-filter-form__grid .sce-filter-form__cell{flex:1 1 180px;min-width:0}}@media(max-width:768px){.sce-filter-form__grid .sce-filter-form__cell{flex:1 1 140px}}@media(max-width:640px){.sce-filter-form__grid .sce-filter-form__cell{flex:1 1 100%}.sce-filter-form__actions{flex-direction:column}.sce-filter-form__actions .sce-filter-form__btn{width:100%}}\n"] }]
|
|
8880
9013
|
}], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], quickFilterTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickFilterTitle", required: false }] }], quickFilterCounter: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickFilterCounter", required: false }] }], filterChange: [{ type: i0.Output, args: ["filterChange"] }], filterSubmit: [{ type: i0.Output, args: ["filterSubmit"] }], filterReset: [{ type: i0.Output, args: ["filterReset"] }], saveFilterClick: [{ type: i0.Output, args: ["saveFilterClick"] }] } });
|
|
8881
9014
|
|
|
9015
|
+
/** All-in-one labelled field that switches its control on the `type` input (text, password, phone, number, select, multiselect, date/datetime, textarea, checkbox/radio); it is a self-registering `ControlValueAccessor` (`NgControl` is injected with `self`, so `formControlName` works) and maps validator errors to i18n keys, overridable per field via `errorMessages`. */
|
|
8882
9016
|
class FormInput {
|
|
8883
9017
|
static nextId = 0;
|
|
8884
9018
|
phoneConfig = PHONE_CONFIG;
|
|
@@ -9144,6 +9278,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
9144
9278
|
args: [{ host: { class: 'sce-form-input' }, selector: 'sce-form-input', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (label() || subText()) {\n <label class=\"form-input__label\" [id]=\"fieldId + '-label'\" [attr.for]=\"isCheckboxRadio() ? null : fieldId\">\n @if (label()) {\n <span class=\"form-input__label-text\">{{ label() | translate }}</span>\n }\n @if (required()) {\n <span class=\"form-input__required\" aria-hidden=\"true\">*</span>\n }\n @if (subText()) {\n <span class=\"form-input__sub-text\">{{ subText() | translate }}</span>\n }\n </label>\n}\n\n<div\n class=\"form-input__wrapper\"\n [class.form-input__wrapper--focused]=\"focused()\"\n [class.form-input__wrapper--disabled]=\"disabled()\"\n [class.form-input__wrapper--error]=\"showError()\"\n [class.form-input__wrapper--has-toggle]=\"isPassword()\"\n [class.form-input__wrapper--textarea]=\"isTextarea()\"\n [class.is-ltr]=\"isPhone()\"\n [class.form-input__wrapper--small]=\"size() === 'small'\"\n [class.form-input__wrapper--medium]=\"size() === 'medium'\"\n [class.form-input__wrapper--large]=\"size() === 'large'\"\n [class.form-input__wrapper--date-picker]=\"isDatePicker()\"\n [class.form-input__wrapper--borderless]=\"isCheckboxRadio()\"\n [class.form-input__wrapper--with-inline-suffix]=\"!!inlineSuffix()\"\n>\n @if (isSelect()) {\n <select\n class=\"form-input__select\"\n [id]=\"fieldId\"\n [attr.aria-label]=\"label() ? null : (placeholder() | translate)\"\n [value]=\"value()\"\n [disabled]=\"disabled()\"\n (change)=\"onSelectChange($any($event).target.value)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n >\n @if (placeholder()) {\n <option value=\"\" disabled selected>{{ placeholder() | translate }}</option>\n }\n @for (opt of options(); track opt.value) {\n <option [value]=\"opt.value\">{{ opt.label }}</option>\n }\n </select>\n } @else if (isMultiSelect()) {\n <select\n class=\"form-input__select\"\n multiple\n [id]=\"fieldId\"\n [attr.aria-label]=\"label() ? null : (placeholder() | translate)\"\n [disabled]=\"disabled()\"\n (change)=\"onMultiSelectChange($any($event))\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n >\n @for (opt of options(); track opt.value) {\n <option [value]=\"opt.value\">{{ opt.label }}</option>\n }\n </select>\n } @else if (isTextarea()) {\n <textarea\n class=\"form-input__textarea\"\n [id]=\"fieldId\"\n [rows]=\"rows()\"\n [placeholder]=\"placeholder() | translate\"\n [disabled]=\"disabled()\"\n [value]=\"value()\"\n [attr.maxlength]=\"maxLength()\"\n (input)=\"onInput($any($event).target.value)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n ></textarea>\n } @else if (isCheckboxRadio()) {\n <div class=\"form-input__checkbox-group\" [class.form-input__checkbox-group--horizontal]=\"layout() === 'horizontal'\">\n @for (opt of options(); track opt.value) {\n <label class=\"form-input__checkbox-label\">\n <input\n [type]=\"type() === 'radio' ? 'radio' : 'checkbox'\"\n [name]=\"radioName()\"\n [value]=\"opt.value\"\n [checked]=\"type() === 'radio' ? value() === opt.value : multiValue().includes(opt.value)\"\n [disabled]=\"disabled()\"\n (change)=\"type() === 'radio' ? onRadioChange(opt.value) : onCheckboxChange(\n $any($event).target.checked\n ? [...multiValue(), opt.value]\n : multiValue().filter(v => v !== opt.value)\n )\"\n />\n <span>{{ opt.label }}</span>\n </label>\n }\n </div>\n } @else {\n @if (isPhone()) {\n <div class=\"form-input__countrycode\" aria-hidden=\"true\">\n <span dir=\"ltr\">{{ phoneConfig.COUNTRY_CODE }}</span>\n </div>\n }\n\n <input\n class=\"form-input__field\"\n [id]=\"fieldId\"\n [type]=\"inputType()\"\n [value]=\"value()\"\n [placeholder]=\"placeholder() | translate\"\n [disabled]=\"disabled()\"\n [attr.maxlength]=\"maxLengthOverride() ?? maxLength()\"\n [attr.inputmode]=\"inputMode()\"\n [attr.autocomplete]=\"autocomplete()\"\n [attr.dir]=\"isPhone() ? 'ltr' : null\"\n (input)=\"onInput($any($event).target.value)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n />\n\n @if (inlineSuffix()) {\n <span class=\"form-input__inline-suffix\" aria-hidden=\"true\">{{ inlineSuffix() }}</span>\n }\n }\n\n @if (isPassword()) {\n <button\n type=\"button\"\n class=\"form-input__password-toggle\"\n (click)=\"togglePassword()\"\n [attr.aria-label]=\"showPassword() ? ('COMMON.HIDE_PASSWORD' | translate) : ('COMMON.SHOW_PASSWORD' | translate)\"\n >\n <i class=\"pi\" [class.pi-eye]=\"!showPassword()\" [class.pi-eye-slash]=\"showPassword()\"></i>\n </button>\n }\n</div>\n\n@if (showError()) {\n <p class=\"form-input__error\" role=\"alert\">{{ errorKey() | translate }}</p>\n}\n", styles: [":host.sce-form-input{display:block}.form-input__label{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--space-xs);margin-block-end:var(--space-xs)}.form-input__label-text{font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--Form-field-text-label)}.form-input__required{color:var(--color-error);font-weight:var(--font-weight-semibold)}.form-input__sub-text{font-size:var(--font-size-xs);color:var(--color-text-muted)}.form-input__wrapper{position:relative;display:flex;align-items:center;background-color:var(--color-white);border:1px solid var(--border-neutral-primary);border-radius:var(--radius-md);transition:border-color var(--transition-base),box-shadow var(--transition-base)}@media(hover:hover)and (pointer:fine){.form-input__wrapper:hover:not(.form-input__wrapper--disabled):not(.form-input__wrapper--focused):not(.form-input__wrapper--error){border-color:var(--field-border-hovered)}}.form-input__wrapper:after{content:\"\";position:absolute;inset-block-end:0;inset-inline:50%;height:var(--border-width-1);background:var(--field-border-pressed);transition:inset-inline var(--transition-base);border-end-start-radius:var(--radius-md);border-end-end-radius:var(--radius-md)}.form-input__wrapper:active:not(.form-input__wrapper--disabled):not(.form-input__wrapper--error){background-color:var(--field-background-pressed)}.form-input__wrapper:active:not(.form-input__wrapper--disabled):not(.form-input__wrapper--error):after{inset-inline:0}.form-input__wrapper--focused:not(.form-input__wrapper--disabled):not(.form-input__wrapper--error){border-color:var(--color-border-focus)}.form-input__wrapper--focused:not(.form-input__wrapper--disabled):not(.form-input__wrapper--error):after{inset-inline:0}.form-input__wrapper--small .form-input__field,.form-input__wrapper--small .form-input__select,.form-input__wrapper--small .form-input__textarea{padding:var(--space-sm) var(--space-md)}.form-input__wrapper--large{min-inline-size:var(--size-360)}.form-input__wrapper--disabled{background-color:var(--color-disabled-bg);cursor:not-allowed}.form-input__wrapper--error{border-color:var(--color-error)}.form-input__wrapper--borderless{border:none;background:transparent}.form-input__wrapper--borderless:after{display:none}.form-input__wrapper--date-picker{cursor:pointer}.form-input__wrapper--textarea{align-items:flex-start;min-block-size:var(--space-80)}.form-input__wrapper--with-inline-suffix .form-input__field{flex:1;min-inline-size:0}.form-input__wrapper.is-ltr{direction:ltr;unicode-bidi:isolate}.form-input__wrapper.is-ltr .form-input__field{direction:ltr;text-align:start;flex:1;min-inline-size:0}.form-input__field{width:100%;padding:var(--space-md) var(--space-lg);font-size:var(--font-size-sm);font-family:inherit;color:var(--color-text);background:transparent;border:none;outline:none}.form-input__field::placeholder{color:var(--Form-field-text-placeholder, var(--color-neutral-500));font-size:var(--font-size-sm);font-weight:500}.form-input__field:disabled{cursor:not-allowed;opacity:.6}.form-input__select{width:100%;padding:var(--space-md) var(--space-lg);font-size:var(--font-size-sm);font-family:inherit;color:var(--color-text);background:transparent;border:none;outline:none;cursor:pointer;appearance:none}.form-input__select:disabled{cursor:not-allowed;opacity:.6}.form-input__inline-suffix{flex-shrink:0;padding-inline-end:var(--space-md);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-text-display);-webkit-user-select:none;user-select:none}.form-input__textarea{width:100%;padding:var(--space-md) var(--space-lg);font-size:var(--font-size-sm);font-family:inherit;color:var(--color-text);background:transparent;border:none;border-radius:var(--radius-md);outline:none;resize:block;overflow-y:auto;line-height:1.5}.form-input__textarea::placeholder{color:var(--Form-field-text-placeholder, var(--color-neutral-500));font-size:var(--font-size-sm);font-weight:500}.form-input__textarea:focus-visible{outline:none}.form-input__textarea:disabled{cursor:not-allowed;opacity:.6}.form-input__countrycode{display:flex;flex-shrink:0;align-items:center;align-self:stretch;padding:0 var(--space-md);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--text-secondary-700, var(--color-neutral-600));background:var(--app-surface-muted, var(--color-neutral-50));border-inline-end:1px solid var(--border-neutral-primary);-webkit-user-select:none;user-select:none;direction:ltr;unicode-bidi:isolate}.form-input__countrycode span{direction:ltr;unicode-bidi:isolate;white-space:nowrap}.form-input__password-toggle{position:absolute;inset-inline-end:var(--space-md);display:flex;align-items:center;justify-content:center;background:transparent;border:none;cursor:pointer;color:var(--color-icon-default);padding:var(--space-xs)}.form-input__password-toggle:hover{color:var(--color-primary)}.form-input__password-toggle:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px;border-radius:var(--radius-md)}.form-input__checkbox-group{display:flex;flex-direction:column;gap:var(--space-sm);padding:var(--space-sm)}.form-input__checkbox-group--horizontal{flex-direction:row;flex-wrap:wrap}.form-input__checkbox-label{display:flex;align-items:center;gap:var(--space-xs);font-size:var(--font-size-sm);color:var(--color-text);cursor:pointer}.form-input__checkbox-label input{accent-color:var(--color-primary)}.form-input__error{margin-block-start:var(--space-xs);font-size:var(--font-size-sm);color:var(--color-error)}\n"] }]
|
|
9145
9279
|
}], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], subText: [{ type: i0.Input, args: [{ isSignal: true, alias: "subText", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], submitted: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitted", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], dateAppendToBody: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateAppendToBody", required: false }] }], dateSelectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateSelectionMode", required: false }] }], dateShowDropdownIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateShowDropdownIcon", required: false }] }], dateFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFormat", required: false }] }], valueDateFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueDateFormat", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], radioName: [{ type: i0.Input, args: [{ isSignal: true, alias: "radioName", required: false }] }], selectShowFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectShowFilter", required: false }] }], selectAppendToBody: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAppendToBody", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], iconPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconPosition", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], restrictInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "restrictInput", required: false }] }], filterOverride: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterOverride", required: false }] }], maxLengthOverride: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLengthOverride", required: false }] }], inlineSuffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "inlineSuffix", required: false }] }], errorMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessages", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], multiValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiValue", required: false }] }, { type: i0.Output, args: ["multiValueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }] } });
|
|
9146
9280
|
|
|
9281
|
+
/** Row of `length` single-digit OTP boxes (default `VALIDATION_LENGTHS.OTP`) with auto-advance, backspace-back and paste-to-fill; a self-registering `ControlValueAccessor` whose value is the joined digit string. */
|
|
9147
9282
|
class OtpInput {
|
|
9148
9283
|
length = input(VALIDATION_LENGTHS.OTP, ...(ngDevMode ? [{ debugName: "length" }] : /* istanbul ignore next */ []));
|
|
9149
9284
|
submitted = input(false, ...(ngDevMode ? [{ debugName: "submitted" }] : /* istanbul ignore next */ []));
|
|
@@ -9625,6 +9760,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
9625
9760
|
], host: { class: 'sce-dynamic-form' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<form class=\"sce-dynamic-form__form\" [formGroup]=\"form()\" (ngSubmit)=\"onSubmit()\">\n @for (section of renderSections(); track section.fields[0].key) {\n <section class=\"sce-dynamic-form__section\">\n @if (section.title) {\n <h3 class=\"sce-dynamic-form__section-title\">{{ section.title | translate }}</h3>\n }\n @if (section.description) {\n <p class=\"sce-dynamic-form__section-desc\">{{ section.description | translate }}</p>\n }\n <div class=\"sce-dynamic-form__grid\" [style.grid-template-columns]=\"section.gridTemplateColumns\" [style.gap]=\"gap()\">\n @for (field of section.fields; track field.key) {\n <div class=\"sce-dynamic-form__field\" [style.grid-column]=\"field.gridColumn\">\n @if (field.isMulti) {\n <sce-form-input\n [type]=\"$any(field.type)\"\n [label]=\"field.label ?? ''\"\n [subText]=\"field.subText ?? ''\"\n [placeholder]=\"field.placeholder ?? ''\"\n [options]=\"field.options ?? []\"\n [layout]=\"field.layout ?? 'vertical'\"\n [required]=\"!!field.validators?.required\"\n [submitted]=\"effectiveSubmitted()\"\n [errorMessages]=\"field.errorMessages ?? {}\"\n [disabled]=\"!!field.disabled\"\n [multiValue]=\"multiValues()[field.key]\"\n (multiValueChange)=\"onMultiChange(field.key, $event)\"\n />\n } @else if (field.type === 'currency') {\n <sce-currency-input\n [id]=\"field.key\"\n [label]=\"field.label ?? '' | translate\"\n [placeholder]=\"field.placeholder ? (field.placeholder | translate) : '0.00'\"\n [value]=\"$any(liveValues()[field.key])\"\n [required]=\"!!field.validators?.required\"\n [disabled]=\"!!field.disabled\"\n [error]=\"fieldErrors()[field.key]\"\n [invalid]=\"!!fieldErrors()[field.key]\"\n (valueChange)=\"setControlValue(field.key, $event)\"\n />\n } @else if (field.type === 'unit') {\n <sce-unit-input-field\n [id]=\"field.key\"\n [label]=\"field.label ?? '' | translate\"\n [unitInput]=\"field.unit ?? '' | translate\"\n [placeholder]=\"field.placeholder ?? ''\"\n [value]=\"$any(liveValues()[field.key])\"\n [required]=\"!!field.validators?.required\"\n [allowDecimal]=\"field.allowDecimal ?? true\"\n [error]=\"fieldErrors()[field.key]\"\n (valueChange)=\"setControlValue(field.key, $event)\"\n />\n } @else if (field.type === 'switch') {\n <sce-field\n [id]=\"field.key\"\n [label]=\"field.label ?? '' | translate\"\n [required]=\"!!field.validators?.required\"\n [error]=\"fieldErrors()[field.key]\"\n >\n <sce-switch\n [checked]=\"$any(liveValues()[field.key])\"\n [disabled]=\"!!field.disabled\"\n [showLabel]=\"!!(field.activeLabel || field.inactiveLabel)\"\n [activeLabel]=\"field.activeLabel ?? '' | translate\"\n [inactiveLabel]=\"field.inactiveLabel ?? '' | translate\"\n (checkedChange)=\"setControlValue(field.key, $event)\"\n />\n </sce-field>\n } @else if (field.type === 'rating') {\n <sce-field [id]=\"field.key\" [label]=\"field.label ?? '' | translate\" [required]=\"!!field.validators?.required\">\n <sce-star-rating-input\n [value]=\"$any(liveValues()[field.key])\"\n [disabled]=\"!!field.disabled\"\n [ariaLabel]=\"field.ariaLabel ?? field.label ?? '' | translate\"\n [error]=\"fieldErrors()[field.key]\"\n (valueChange)=\"setControlValue(field.key, $event)\"\n />\n </sce-field>\n } @else if (field.type === 'otp') {\n <sce-field [id]=\"field.key\" [label]=\"field.label ?? '' | translate\" [required]=\"!!field.validators?.required\">\n <sce-otp-input [length]=\"field.length ?? 4\" [submitted]=\"effectiveSubmitted()\" [formControlName]=\"field.key\" />\n </sce-field>\n } @else {\n <sce-form-input\n [type]=\"$any(field.type)\"\n [label]=\"field.label ?? ''\"\n [subText]=\"field.subText ?? ''\"\n [placeholder]=\"field.placeholder ?? ''\"\n [options]=\"field.options ?? []\"\n [rows]=\"field.rows ?? 4\"\n [icon]=\"field.icon ?? ''\"\n [size]=\"field.size ?? 'medium'\"\n [inlineSuffix]=\"field.inlineSuffix ?? ''\"\n [layout]=\"field.layout ?? 'vertical'\"\n [minDate]=\"field.minDate ?? null\"\n [maxDate]=\"field.maxDate ?? null\"\n [restrictInput]=\"field.restrictInput ?? null\"\n [required]=\"!!field.validators?.required\"\n [submitted]=\"effectiveSubmitted()\"\n [errorMessages]=\"field.errorMessages ?? {}\"\n [formControlName]=\"field.key\"\n />\n }\n </div>\n }\n </div>\n </section>\n }\n\n @if (showSubmit()) {\n <div class=\"sce-dynamic-form__actions\">\n <button type=\"submit\" class=\"sce-dynamic-form__submit\">\n {{ submitLabel() | translate }}\n </button>\n </div>\n }\n</form>\n", styles: [":host{display:block}.sce-dynamic-form__form{display:flex;flex-direction:column;gap:var(--space-24)}.sce-dynamic-form__section{display:flex;flex-direction:column;gap:var(--space-3)}.sce-dynamic-form__section-title{margin:0;font-size:var(--font-size-base);font-weight:var(--font-weight-semibold);color:var(--color-text-primary)}.sce-dynamic-form__section-desc{margin:0;font-size:var(--font-size-sm);color:var(--color-text-secondary)}.sce-dynamic-form__grid{display:grid;align-items:start}.sce-dynamic-form__field{min-width:0}.sce-dynamic-form__actions{grid-column:1/-1;display:flex;justify-content:flex-end;margin-block-start:var(--space-2)}.sce-dynamic-form__submit{display:inline-flex;align-items:center;justify-content:center;padding-block:var(--space-3);padding-inline:var(--space-24);border:none;border-radius:var(--radius-lg);background-color:var(--color-primary);color:var(--color-on-primary);font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);cursor:pointer;transition:background-color var(--transition-fast)}.sce-dynamic-form__submit:hover{background-color:var(--color-primary-hover)}.sce-dynamic-form__submit:disabled{opacity:.6;cursor:not-allowed}\n"] }]
|
|
9626
9761
|
}], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], initialValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialValue", required: false }] }], submitted: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitted", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], formSubmit: [{ type: i0.Output, args: ["formSubmit"] }], formInvalid: [{ type: i0.Output, args: ["formInvalid"] }] } });
|
|
9627
9762
|
|
|
9763
|
+
/** Modal shell over PrimeNG `p-dialog` (portaled to `body`) with projected header/body/footer slots; `size` maps to a max-width and `dismissed` fires exactly once whether closed by button, backdrop or ESC — note it uses `ViewEncapsulation.None`, so its styles are global. */
|
|
9628
9764
|
class Popup {
|
|
9629
9765
|
open = input(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
9630
9766
|
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
@@ -9691,6 +9827,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
9691
9827
|
args: [{ selector: 'sce-popup', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [Dialog, TranslatePipe], host: { class: 'sce-popup' }, template: "<p-dialog\n [visible]=\"open()\"\n (onHide)=\"onHide()\"\n [modal]=\"true\"\n [dismissableMask]=\"closeOnBackdropClick()\"\n [closeOnEscape]=\"closeOnBackdropClick()\"\n [draggable]=\"false\"\n [resizable]=\"false\"\n [closable]=\"false\"\n [showHeader]=\"false\"\n [blockScroll]=\"true\"\n [style]=\"dialogStyle()\"\n [styleClass]=\"dialogStyleClass()\"\n [appendTo]=\"dialogAppendTo\"\n>\n @if (showHeader()) {\n <div class=\"popup__header\" [class.popup__header--large]=\"largeHeader()\">\n <div class=\"popup__header-main\">\n @if (showBackButton()) {\n <button type=\"button\" class=\"popup__header-button back\" (click)=\"back()\" [attr.aria-label]=\"'COMMON.BACK' | translate\">\n <i class=\"pi pi-chevron-left\" style=\"font-size: 1.25rem\"></i>\n </button>\n }\n @if (title()) {\n <div class=\"popup-title__area\">\n <h2 [id]=\"titleId\" class=\"popup__title\">{{ title() }}</h2>\n <ng-content select=\"[subTitle]\"></ng-content>\n </div>\n }\n </div>\n @if (showCloseButton()) {\n <button type=\"button\" class=\"popup__header-button\" (click)=\"close()\" [attr.aria-label]=\"'COMMON.CLOSE' | translate\">\n <i class=\"pi pi-times\" style=\"font-size: 1.25rem\"></i>\n </button>\n }\n </div>\n }\n\n <div class=\"popup__body\" [attr.aria-labelledby]=\"showHeader() && title() ? titleId : null\">\n <ng-content></ng-content>\n </div>\n\n <div [class.popup__footer]=\"footerStyle()\" [class.popup__footer--border]=\"footerBorder()\">\n <ng-content select=\"[popupFooter]\"></ng-content>\n </div>\n</p-dialog>\n", styles: ["@charset \"UTF-8\";.sce-popup-dialog.p-dialog{border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);max-height:calc(100vb - var(--space-xl) * 2);display:flex;flex-direction:column}.sce-popup-dialog.p-dialog .p-dialog-content{padding:0;border-radius:var(--radius-lg);display:flex;flex-direction:column;overflow:hidden;flex:1}.sce-popup-dialog--overflow-visible.p-dialog .p-dialog-content,.sce-popup-dialog--overflow-visible .popup__body{overflow:visible}.popup__header{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-lg);padding:var(--space-xl) var(--space-xl) 0;flex-shrink:0}.popup__header--large .popup__header-button{width:var(--size-54, 3.375rem);height:var(--size-54, 3.375rem)}.popup__header-main{display:flex;gap:var(--space-md)}.popup__title{margin:0;font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);color:var(--color-text-display)}.popup__header-button{display:flex;align-items:center;justify-content:center;width:var(--size-32);height:var(--size-32);padding:var(--space-xs);color:var(--color-icon-default);background:var(--landing-modal-close-bg, var(--color-neutral-100));border:none;border-radius:var(--radius-lg);cursor:pointer;transition:color var(--transition-fast),background-color var(--transition-fast)}.popup__header-button:hover{background:var(--color-neutral-50)}.popup__header-button:focus-visible{outline:var(--space-2) solid var(--color-primary);outline-offset:var(--space-2)}[dir=rtl] .popup__header-button.back{transform:rotate(180deg)}.popup__body{flex:1;overflow-y:auto;padding:var(--space-20) var(--space-xl)}.popup__footer{display:flex;gap:var(--space-lg);justify-content:flex-end;padding:var(--space-lg) var(--space-xl);flex-shrink:0}.popup__footer--border{border-block-start:1px solid var(--color-border)}.popup__footer:empty{display:none}\n"] }]
|
|
9692
9828
|
}], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], footerBorder: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerBorder", required: false }] }], footerStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerStyle", required: false }] }], showCloseButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCloseButton", required: false }] }], showBackButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showBackButton", required: false }] }], largeHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "largeHeader", required: false }] }], showHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHeader", required: false }] }], closeOnBackdropClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdropClick", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], bodyScrollable: [{ type: i0.Input, args: [{ isSignal: true, alias: "bodyScrollable", required: false }] }], dismissed: [{ type: i0.Output, args: ["dismissed"] }], backClicked: [{ type: i0.Output, args: ["backClicked"] }] } });
|
|
9693
9829
|
|
|
9830
|
+
/** Abstract base for modal components: holds `isOpen`/`modalData` signals, exposes `openModal(data)`/`closeModal()`, and requires the subclass template to contain a `Popup` whose dismissal closes the modal and re-emits `dismissed`. */
|
|
9694
9831
|
class PopupModalBase {
|
|
9695
9832
|
destroyRef = inject(DestroyRef);
|
|
9696
9833
|
modalData = signal(null, ...(ngDevMode ? [{ debugName: "modalData" }] : /* istanbul ignore next */ []));
|
|
@@ -9846,6 +9983,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
9846
9983
|
}]
|
|
9847
9984
|
}] });
|
|
9848
9985
|
|
|
9986
|
+
/** Tab bar over PrimeNG `p-tabs` that renders `items` and emits `tabChange`, projecting the panel content itself; `activeId` seeds a `linkedSignal` (so the tab strip is uncontrolled after the first click) and a host directive fixes inkbar placement in RTL. */
|
|
9849
9987
|
class Tabs {
|
|
9850
9988
|
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
9851
9989
|
activeId = input('', ...(ngDevMode ? [{ debugName: "activeId" }] : /* istanbul ignore next */ []));
|
|
@@ -9881,6 +10019,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
9881
10019
|
args: [{ host: { class: 'sce-tabs' }, selector: 'sce-tabs', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [TranslatePipe, Tabs$1, TabList, Tab], hostDirectives: [TabsInkbarRtlDirective], template: "<div\n class=\"tabs\"\n [class.tabs--default]=\"variant() === 'default'\"\n [class.tabs--pills]=\"variant() === 'pills'\"\n [class.tabs--underline]=\"variant() === 'underline'\"\n [class.tabs--small]=\"size() === 'small'\"\n [class.tabs--medium]=\"size() === 'medium'\"\n [class.tabs--large]=\"size() === 'large'\"\n [class.tabs--justify-start]=\"justify() === 'start'\"\n [class.tabs--justify-center]=\"justify() === 'center'\"\n [class.tabs--justify-end]=\"justify() === 'end'\"\n [class.tabs--justify-between]=\"justify() === 'between'\"\n [class.tabs--underline-text]=\"underlineStyle() === 'text'\"\n>\n <p-tabs [(value)]=\"activeValue\" (valueChange)=\"onValueChange($event)\">\n <p-tablist>\n @for (tab of items(); track tab.id) {\n <p-tab [value]=\"tab.id\" [disabled]=\"tab.disabled ?? false\">\n @if (tab.icon) {\n <span class=\"tabs__tab-icon\">{{ tab.icon }}</span>\n }\n <span class=\"tabs__tab-label\">{{ tab.label | translate }}</span>\n @if (tab.badge) {\n <span class=\"tabs__tab-badge\">{{ tab.badge }}</span>\n }\n </p-tab>\n }\n </p-tablist>\n </p-tabs>\n\n <div class=\"tabs__content\" role=\"tabpanel\" [attr.id]=\"contentPanelId()\" [attr.aria-labelledby]=\"activeTabId()\">\n <ng-content></ng-content>\n </div>\n</div>\n", styles: [":host{display:block;width:100%}.tabs{width:100%;position:relative;direction:inherit}.tabs :host ::ng-deep .p-tabs,.tabs ::ng-deep .p-tabs{width:100%}.tabs :host ::ng-deep .p-tablist,.tabs ::ng-deep .p-tablist{background:var(--color-background);border-block-end:none;position:relative}.tabs :host ::ng-deep .p-tablist:after,.tabs ::ng-deep .p-tablist:after{content:\"\";position:absolute;inset-block-end:0;inset-inline-start:0;inline-size:100%;block-size:var(--size-3);background:var(--color-neutral-50);border-radius:var(--radius-10);z-index:9}.tabs :host ::ng-deep .p-tablist-tab-list,.tabs ::ng-deep .p-tablist-tab-list{background:transparent;border:none;position:relative;height:100%;display:flex;align-items:center}.tabs :host ::ng-deep .p-tablist-active-bar,.tabs ::ng-deep .p-tablist-active-bar{position:absolute;inset-block-end:0;background:var(--color-primary);block-size:var(--size-3);border-radius:var(--radius-10);z-index:10}[dir=rtl] .tabs :host ::ng-deep .p-tablist-active-bar,[dir=rtl] .tabs ::ng-deep .p-tablist-active-bar{inset-inline-start:unset;inset-inline-end:unset}.tabs :host ::ng-deep .p-tab,.tabs ::ng-deep .p-tab{position:relative;background:none;border:none;padding-block:var(--space-md);padding-inline:var(--space-lg);cursor:pointer;color:var(--color-text-display);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);font-family:inherit;transition:all var(--transition-base);display:flex;align-items:center;white-space:nowrap;border-radius:0}.tabs :host ::ng-deep .p-tab:hover:not(.p-disabled),.tabs ::ng-deep .p-tab:hover:not(.p-disabled){color:var(--color-primary);background:var(--color-background-hover)}.tabs :host ::ng-deep .p-tab.p-tab-active,.tabs ::ng-deep .p-tab.p-tab-active{font-weight:var(--font-weight-bold);color:var(--Text-text-default, var(--color-neutral-900));background:var(--color-background)}.tabs :host ::ng-deep .p-tab.p-disabled,.tabs ::ng-deep .p-tab.p-disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.tabs--underline-text ::ng-deep .p-tablist-active-bar{display:none}.tabs--underline-text ::ng-deep .p-tablist:after{display:none}.tabs--underline-text .tabs__tab-label{position:relative}.tabs--underline-text .tabs__tab-label:after{content:\"\";position:absolute;inset-block-end:calc((var(--space-md) + var(--size-3)) * -1);inset-inline-start:0;inline-size:0;block-size:var(--size-3);background:var(--color-primary);border-radius:0;z-index:10;transition:inline-size var(--transition-base, .2s ease)}.tabs--underline-text ::ng-deep .p-tab-active .tabs__tab-label:after{inline-size:100%}.tabs--underline-text.tabs --small .tabs__tab-label:after{inset-block-end:calc((var(--space-sm) + var(--size-3)) * -1)}.tabs--underline-text.tabs --large .tabs__tab-label:after{inset-block-end:calc((var(--space-lg) + var(--size-3)) * -1)}.tabs--justify-start ::ng-deep .p-tablist-tab-list{justify-content:flex-start}.tabs--justify-center ::ng-deep .p-tablist-tab-list{justify-content:center}.tabs--justify-end ::ng-deep .p-tablist-tab-list{justify-content:flex-end}.tabs--justify-between ::ng-deep .p-tablist-tab-list{justify-content:space-between}.tabs--small ::ng-deep .p-tab{padding-block:var(--space-sm);padding-inline:var(--space-md);font-size:var(--font-size-sm)}.tabs--large ::ng-deep .p-tab{padding-block:var(--space-lg);padding-inline:var(--space-xl);font-size:var(--font-size-lg)}.tabs--pills ::ng-deep .p-tablist-tab-list{border:none}.tabs--pills ::ng-deep .p-tab{flex:1;justify-content:flex-start}.tabs--pills ::ng-deep .p-tab.p-tab-active{color:var(--color-primary)}.tabs--underline ::ng-deep .p-tablist{border:none}.tabs--underline ::ng-deep .p-tablist:after{display:none}.tabs--underline ::ng-deep .p-tab.p-tab-active{border-block-end-color:var(--color-primary)}.tabs__tab-icon{font-size:var(--font-size-lg)}.tabs__tab-label{flex:1}.tabs__tab-badge{background:var(--color-primary);color:var(--color-primary-contrast);border-radius:var(--radius-full);padding-block:var(--space-xs);padding-inline:var(--space-sm);font-size:var(--font-size-xs);font-weight:var(--font-weight-semibold);min-width:var(--size-20);text-align:center}.tabs__content{margin-block:var(--space-lg);margin-inline:0}\n"] }]
|
|
9882
10020
|
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], activeId: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeId", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], justify: [{ type: i0.Input, args: [{ isSignal: true, alias: "justify", required: false }] }], tabChange: [{ type: i0.Output, args: ["tabChange"] }], underlineStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "underlineStyle", required: false }] }], primeTabs: [{ type: i0.ViewChild, args: [i0.forwardRef(() => Tabs$1), { isSignal: true }] }] } });
|
|
9883
10021
|
|
|
10022
|
+
/** Wraps PrimeNG `p-breadcrumb` over `items`, prepending a home entry unless `showHomeIcon` is false; re-translates labels on language change and sets its own `dir` from the `rtl` input (default: current lang is Arabic). */
|
|
9884
10023
|
class Breadcrumb {
|
|
9885
10024
|
destroyRef = inject(DestroyRef);
|
|
9886
10025
|
translateService = inject(TranslateService);
|
|
@@ -9976,6 +10115,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
9976
10115
|
}, template: "<p-breadcrumb [model]=\"menuItems()\" [home]=\"homeMenuItem()\" styleClass=\"breadcrumb\" (onItemClick)=\"onBreadcrumbItemClick($event)\">\n @if (separatorItem()) {\n <ng-template #separator>\n <span class=\"breadcrumb-separator\">{{ separatorItem() }}</span>\n </ng-template>\n }\n</p-breadcrumb>\n", styles: [":host{display:block}.breadcrumb{background:transparent;border:none;padding:0}::ng-deep .breadcrumb .p-breadcrumb-list{align-items:center;gap:var(--space-xs)}::ng-deep .breadcrumb .p-breadcrumb-item-label{color:var(--color-breadcrumb)}::ng-deep .breadcrumb .p-breadcrumb-item-link{font-weight:var(--font-weight-regular);font-size:var(--font-size-xs)}::ng-deep .breadcrumb .p-breadcrumb-item:hover .p-breadcrumb-link{color:var(--primary-color)}::ng-deep .breadcrumb .p-breadcrumb-item.p-disabled{opacity:.6;pointer-events:none}::ng-deep .breadcrumb .p-breadcrumb-item:last-child .p-breadcrumb-link{font-weight:var(--font-weight-semibold);color:var(--text-color);cursor:default}::ng-deep .breadcrumb .p-breadcrumb-item:last-child .p-breadcrumb-link:hover{color:var(--text-color)}::ng-deep .breadcrumb .p-breadcrumb-link{color:var(--color-breadcrumb);text-decoration:none;transition:color .2s ease;display:flex;align-items:center;cursor:pointer;border-radius:var(--radius-md)}::ng-deep .breadcrumb .p-breadcrumb-link:focus-visible{outline:2px solid var(--color-brand-primary-600, var(--color-brand-primary-600));outline-offset:2px}::ng-deep .breadcrumb .p-breadcrumb-link .p-breadcrumb-icon{font-size:var(--font-size-md)}::ng-deep .breadcrumb .p-breadcrumb-separator{margin:var(--space-1);color:var(--color-breadcrumb-separator)}::ng-deep .breadcrumb .breadcrumb-separator{margin:var(--space-1);color:var(--color-breadcrumb-separator);font-size:var(--font-size-2xs)}[dir=rtl] .p-breadcrumb-separator{transform:scaleX(-1)}[dir=rtl] .p-breadcrumb-list{direction:rtl}:host ::ng-deep .p-breadcrumb.p-breadcrumb{background-color:transparent;background:transparent;padding:var(--space-0);gap:var(--space-0);display:inline-flex}:host ::ng-deep .p-breadcrumb .p-breadcrumb-item-link{gap:var(--space-0)}:host ::ng-deep .p-breadcrumb-list .p-breadcrumb-item-link.p-breadcrumb-item-link{cursor:pointer}:host ::ng-deep .p-breadcrumb-list .p-breadcrumb-item-link.p-breadcrumb-item-link .p-menuitem-text{font-weight:700;color:var(--color-neutral-900)}\n"] }]
|
|
9977
10116
|
}], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], home: [{ type: i0.Input, args: [{ isSignal: true, alias: "home", required: false }] }], showHomeIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHomeIcon", required: false }] }], rtl: [{ type: i0.Input, args: [{ isSignal: true, alias: "rtl", required: false }] }], separatorItem: [{ type: i0.Input, args: [{ isSignal: true, alias: "separatorItem", required: false }] }], itemClicked: [{ type: i0.Output, args: ["itemClicked"] }] } });
|
|
9978
10117
|
|
|
10118
|
+
/** Input-free card shell: projects its content into a styled `.card` container (host class `sce-card`). */
|
|
9979
10119
|
class Card {
|
|
9980
10120
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: Card, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9981
10121
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.17", type: Card, isStandalone: true, selector: "sce-card", host: { classAttribute: "sce-card" }, ngImport: i0, template: "<div class=\"card\">\n <ng-content />\n</div>\n", styles: [":host{display:block}.card{padding:var(--space-lg);background:var(--color-white);border-radius:var(--radius-lg)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
@@ -9985,6 +10125,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
9985
10125
|
args: [{ host: { class: 'sce-card' }, selector: 'sce-card', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"card\">\n <ng-content />\n</div>\n", styles: [":host{display:block}.card{padding:var(--space-lg);background:var(--color-white);border-radius:var(--radius-lg)}\n"] }]
|
|
9986
10126
|
}] });
|
|
9987
10127
|
|
|
10128
|
+
/** Renders `steps` as a horizontal/vertical step indicator in a `steps`, `progress` or `pills` `variant`; every step click emits `stepChange`, so `linear` currently gates nothing and the host must decide whether to honour it. */
|
|
9988
10129
|
class Stepper {
|
|
9989
10130
|
steps = input.required(...(ngDevMode ? [{ debugName: "steps" }] : /* istanbul ignore next */ []));
|
|
9990
10131
|
variant = input('steps', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
@@ -10026,6 +10167,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10026
10167
|
}, template: "@if (variant() === 'pills') {\n <div\n class=\"stepper-pills\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"progressPercentage()\"\n [attr.aria-label]=\"progressPercentage() + '%'\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n >\n @for (step of steps(); track step.id) {\n <div\n class=\"stepper-pills__segment\"\n [style.width.px]=\"width()\"\n [class.stepper-pills__segment--active]=\"step.state === 'active'\"\n [class.stepper-pills__segment--completed]=\"step.state === 'completed'\"\n [class.stepper-pills__segment--upcoming]=\"step.state === 'upcoming'\"\n ></div>\n }\n </div>\n} @else if (variant() === 'progress') {\n <div\n class=\"stepper-progress\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"progressPercentage()\"\n [attr.aria-label]=\"progressPercentage() + '%'\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n >\n <div class=\"stepper-progress__fill\" [style.width.%]=\"progressPercentage()\"></div>\n </div>\n} @else {\n <nav\n class=\"stepper\"\n [class.stepper--vertical]=\"orientation() === 'vertical'\"\n role=\"navigation\"\n [attr.aria-label]=\"'ARIA.PROGRESS' | translate\"\n >\n <ol class=\"stepper__list\">\n @for (step of steps(); track step.id; let idx = $index; let last = $last) {\n <li\n class=\"stepper__item\"\n [class.stepper__item--completed]=\"step.state === 'completed'\"\n [class.stepper__item--active]=\"step.state === 'active'\"\n [class.stepper__item--upcoming]=\"step.state === 'upcoming'\"\n [class.stepper__item--disabled]=\"step.state === 'disabled'\"\n >\n <button\n class=\"stepper__circle\"\n type=\"button\"\n [disabled]=\"step.state === 'disabled' || step.state === 'active' || (linear() && step.state === 'upcoming')\"\n [attr.aria-current]=\"step.state === 'active' ? 'step' : null\"\n [attr.aria-label]=\"step.label ? (step.label | translate) : idx + 1\"\n (click)=\"onStepClick(step)\"\n >\n @if (step.state === 'completed') {\n <i class=\"stepper__check pi pi-check\"></i>\n } @else {\n <span class=\"stepper__number\">{{ idx + 1 }}</span>\n }\n </button>\n\n @if (step.label) {\n <div class=\"stepper__container\">\n <span class=\"stepper__label\">{{ step.label | translate }}</span>\n @if (step.subLabel) {\n <span class=\"stepper__sub-label\">{{ step.subLabel | translate }}</span>\n }\n </div>\n }\n\n @if (!last) {\n <div class=\"stepper__connector\" [class.stepper__connector--completed]=\"step.state === 'completed'\"></div>\n }\n </li>\n }\n </ol>\n </nav>\n}\n", styles: [":host{display:block;width:100%}.stepper-pills{display:flex;gap:var(--space-xs);width:100%}.stepper-pills__segment{flex-shrink:0;height:var(--size-8);border-radius:var(--rail-radius);background:var(--Background-background-neutral-200, var(--color-neutral-200));transition:background var(--transition-medium)}.stepper-pills__segment--active,.stepper-pills__segment--completed{background:var(--color-primary)}.stepper-pills__segment--upcoming{background:var(--Background-background-neutral-200, var(--color-neutral-200))}.stepper-progress{width:var(--space-100, var(--size-100));height:var(--size-8);background:var(--color-progress-bar-bg);border-radius:var(--rail-radius);overflow:hidden}.stepper-progress__fill{height:100%;border-radius:var(--rail-radius);background:var(--color-primary);transition:width var(--transition-medium)}.stepper__list{display:flex;align-items:center;list-style:none;padding:0;margin:0}.stepper__item{display:flex;align-items:center;flex:1;position:relative}.stepper__item:last-child{flex:0 0 auto}.stepper__item--completed .stepper__circle{background:var(--color-primary);border-color:var(--color-primary);color:var(--color-white);cursor:pointer}.stepper__item--active .stepper__circle{border-color:var(--color-primary);color:var(--color-primary);background:var(--Background-background-primary-25);cursor:default}.stepper__item--upcoming .stepper__circle{border-color:var(--border-neutral-primary);color:var(--color-text-muted);background:var(--color-white)}.stepper__item--disabled .stepper__circle{opacity:.4;cursor:not-allowed}.stepper__item--completed .stepper__label{color:var(--color-primary)}.stepper__item--active .stepper__label{color:var(--Form-field-text-label);font-weight:var(--font-weight-semibold)}.stepper__item--upcoming .stepper__label,.stepper__item--disabled .stepper__label{color:var(--color-text-muted)}.stepper__circle{width:var(--size-32);height:var(--size-32);border-radius:var(--radius-full);border:2px solid;display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:var(--font-size-sm, var(--font-size-md));font-weight:var(--font-weight-semibold);transition:all var(--transition-base, .2s ease);background:none;padding:0}.stepper__circle:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.stepper__circle:disabled{pointer-events:none}.stepper__check{font-size:var(--font-size-lg)}.stepper__container{display:contents}.stepper__label{display:block;font-size:var(--font-size-xs);white-space:nowrap;position:absolute;top:100%;margin-block-start:var(--space-xs);inset-inline-start:0;width:var(--size-32);text-align:center}.stepper__sub-label{display:none}.stepper__connector{flex:1;height:var(--space-2);background:var(--border-neutral-primary);margin-inline-start:var(--space-sm);margin-inline-end:var(--space-sm);transition:background var(--transition-base)}.stepper__connector--completed{background:var(--color-primary)}.stepper--vertical .stepper__list{flex-direction:column;align-items:stretch}.stepper--vertical .stepper__item{display:grid;grid-template-columns:var(--size-32) 1fr;grid-template-rows:auto 1fr;column-gap:var(--space-md);flex:unset}.stepper--vertical .stepper__item:last-child{grid-template-rows:auto}.stepper--vertical .stepper__circle{grid-column:1;grid-row:1}.stepper--vertical .stepper__container{display:flex;flex-direction:column;justify-content:center;gap:var(--space-2xs);grid-column:2;grid-row:1;align-self:center}.stepper--vertical .stepper__label{position:static;top:auto;inset-inline-start:auto;width:auto;text-align:start;white-space:normal;font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--Form-field-text-label);margin-block-start:0}.stepper--vertical .stepper__sub-label{display:block;font-size:var(--font-size-xs);color:var(--color-text-muted)}.stepper--vertical .stepper__connector{grid-column:1;grid-row:2;width:var(--space-2);height:auto;min-height:var(--sce-stepper-step-gap, var(--space-96));flex:unset;margin-inline-start:auto;margin-inline-end:auto;margin-block:var(--space-xs)}.stepper--vertical .stepper__item--completed .stepper__label{color:var(--color-primary)}.stepper--vertical .stepper__item--active .stepper__label{color:var(--Form-field-text-label)}.stepper--vertical .stepper__item--upcoming .stepper__label,.stepper--vertical .stepper__item--disabled .stepper__label{color:var(--color-text-muted)}\n"] }]
|
|
10027
10168
|
}], propDecorators: { steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], linear: [{ type: i0.Input, args: [{ isSignal: true, alias: "linear", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], stepGap: [{ type: i0.Input, args: [{ isSignal: true, alias: "stepGap", required: false }] }], stepChange: [{ type: i0.Output, args: ["stepChange"] }] } });
|
|
10028
10169
|
|
|
10170
|
+
/** Page title with an optional breadcrumb trail (`breadcrumbItems`, on by default); `breadcrumbFirst` moves the trail above the title and `actionLayout` switches to a split layout with a projected actions slot. */
|
|
10029
10171
|
class ScePageHeaderComponent {
|
|
10030
10172
|
titleKey = input('', ...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
|
|
10031
10173
|
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
@@ -10043,6 +10185,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10043
10185
|
args: [{ host: { class: 'sce-page-header' }, selector: 'sce-page-header', standalone: true, imports: [TranslatePipe, RouterLink], changeDetection: ChangeDetectionStrategy.OnPush, template: "<header\n class=\"sce-page-header\"\n [class.sce-page-header--split]=\"actionLayout()\"\n [class.sce-page-header--breadcrumb-first]=\"breadcrumbFirst()\"\n>\n <div class=\"sce-page-header__lead\">\n @if (breadcrumbFirst() && showBreadcrumb() && breadcrumbItems().length) {\n <nav class=\"sce-page-header__breadcrumb\" [attr.aria-label]=\"'aria.breadcrumb' | translate\">\n <ol class=\"sce-page-header__breadcrumb-list\">\n @for (item of breadcrumbItems(); track item.label; let last = $last) {\n <li class=\"sce-page-header__breadcrumb-item\">\n @if (item.url && !last) {\n <a [routerLink]=\"item.url\" class=\"sce-page-header__breadcrumb-link\">\n {{ item.translationKey ? (item.translationKey | translate) : item.label }}\n </a>\n } @else {\n <span class=\"sce-page-header__breadcrumb-current\" [class.sce-page-header__breadcrumb-current--active]=\"last\">\n {{ item.translationKey ? (item.translationKey | translate) : item.label }}\n </span>\n }\n @if (!last) {\n <span class=\"sce-page-header__breadcrumb-sep\" aria-hidden=\"true\">/</span>\n }\n </li>\n }\n </ol>\n </nav>\n }\n @if (titleKey() || title()) {\n <h1 class=\"sce-page-header__title\">\n @if (titleKey()) {\n {{ titleKey() | translate }}\n } @else {\n {{ title() }}\n }\n </h1>\n }\n @if (!breadcrumbFirst() && showBreadcrumb() && breadcrumbItems().length) {\n <nav class=\"sce-page-header__breadcrumb\" [attr.aria-label]=\"'aria.breadcrumb' | translate\">\n <ol class=\"sce-page-header__breadcrumb-list\">\n @for (item of breadcrumbItems(); track item.label; let last = $last) {\n <li class=\"sce-page-header__breadcrumb-item\">\n @if (item.url && !last) {\n <a [routerLink]=\"item.url\" class=\"sce-page-header__breadcrumb-link\">\n {{ item.translationKey ? (item.translationKey | translate) : item.label }}\n </a>\n } @else {\n <span class=\"sce-page-header__breadcrumb-current\" [class.sce-page-header__breadcrumb-current--active]=\"last\">\n {{ item.translationKey ? (item.translationKey | translate) : item.label }}\n </span>\n }\n @if (!last) {\n <span class=\"sce-page-header__breadcrumb-sep\" aria-hidden=\"true\">/</span>\n }\n </li>\n }\n </ol>\n </nav>\n }\n </div>\n @if (actionLayout()) {\n <div class=\"sce-page-header__actions\" role=\"toolbar\">\n <ng-content select=\"[data-page-header-actions]\" />\n </div>\n }\n</header>\n", styles: [":host{display:block}.sce-page-header{margin-block-end:var(--page-header-margin-bottom, var(--space-24))}.sce-page-header--split{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:var(--space-16)}.sce-page-header__lead{flex:1;min-width:0}.sce-page-header__actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-10);flex-shrink:0}.sce-page-header__breadcrumb{margin-block-end:var(--space-12)}.sce-page-header--breadcrumb-first .sce-page-header__breadcrumb{margin-block-end:var(--space-8)}.sce-page-header__breadcrumb-list{display:flex;align-items:center;gap:var(--space-6);margin:0;padding:0;list-style:none;font-size:var(--font-size-sm);color:var(--color-text-secondary)}.sce-page-header__breadcrumb-item{display:flex;align-items:center;gap:var(--space-6)}.sce-page-header__breadcrumb-link{color:inherit;text-decoration:none;transition:color var(--motion-duration-fast, .15s) ease}.sce-page-header__breadcrumb-link:hover{color:var(--color-text-default)}.sce-page-header__breadcrumb-current{color:inherit}.sce-page-header__breadcrumb-current--active{color:var(--color-text-default);font-weight:var(--font-weight-medium)}.sce-page-header__breadcrumb-sep{color:var(--color-neutral-300, var(--color-border))}.sce-page-header__title{margin:0;font-size:var(--font-size-xl);font-weight:var(--font-weight-bold);color:var(--color-text-default)}\n"] }]
|
|
10044
10186
|
}], propDecorators: { titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], breadcrumbItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "breadcrumbItems", required: false }] }], showBreadcrumb: [{ type: i0.Input, args: [{ isSignal: true, alias: "showBreadcrumb", required: false }] }], breadcrumbFirst: [{ type: i0.Input, args: [{ isSignal: true, alias: "breadcrumbFirst", required: false }] }], actionLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionLayout", required: false }] }] } });
|
|
10045
10187
|
|
|
10188
|
+
/**
|
|
10189
|
+
* In-app access-denied page for consumer apps.
|
|
10190
|
+
*
|
|
10191
|
+
* Wire as the target of `libraryAccessDenyRoute` (see `SCE_LIBRARY_ACCESS_DENIED_PATH` in core).
|
|
10192
|
+
* Bootstrap failures still use the raw DOM screen in core — this component is for routed fallbacks
|
|
10193
|
+
* and partner documentation previews.
|
|
10194
|
+
*/
|
|
10195
|
+
class SceLibraryAccessDeniedComponent {
|
|
10196
|
+
/** Override when previewing; otherwise reads from {@link SceLibraryAccessService} when present. */
|
|
10197
|
+
reason = input(...(ngDevMode ? [undefined, { debugName: "reason" }] : /* istanbul ignore next */ []));
|
|
10198
|
+
access = inject(SceLibraryAccessService, { optional: true });
|
|
10199
|
+
contactEmail = inject(SCE_LIBRARY_ACCESS_CONTACT);
|
|
10200
|
+
effectiveReason = computed(() => this.reason() ?? this.access?.denialReason() ?? 'missing', ...(ngDevMode ? [{ debugName: "effectiveReason" }] : /* istanbul ignore next */ []));
|
|
10201
|
+
mailtoHref = computed(() => `mailto:${this.contactEmail}?subject=${encodeURIComponent('SCE library access token')}`, ...(ngDevMode ? [{ debugName: "mailtoHref" }] : /* istanbul ignore next */ []));
|
|
10202
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SceLibraryAccessDeniedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10203
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SceLibraryAccessDeniedComponent, isStandalone: true, selector: "sce-library-access-denied", inputs: { reason: { classPropertyName: "reason", publicName: "reason", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "sce-library-access-denied" }, ngImport: i0, template: "<section class=\"sce-library-access-denied__panel\" role=\"alert\" aria-live=\"assertive\">\n <p class=\"sce-library-access-denied__badge\">@moatamed-sce</p>\n\n <h1 class=\"sce-library-access-denied__title-ar\">\n @switch (effectiveReason()) {\n @case ('missing') {\n \u0645\u0641\u062A\u0627\u062D \u0627\u0644\u0648\u0635\u0648\u0644 \u063A\u064A\u0631 \u0645\u064F\u0639\u0631\u064E\u0651\u0641\n }\n @case ('invalid') {\n \u0645\u0641\u062A\u0627\u062D \u0627\u0644\u0648\u0635\u0648\u0644 \u063A\u064A\u0631 \u0635\u0627\u0644\u062D\n }\n }\n </h1>\n\n <h2 class=\"sce-library-access-denied__title-en\">\n @switch (effectiveReason()) {\n @case ('missing') {\n Access key not configured\n }\n @case ('invalid') {\n Access key not authorized\n }\n }\n </h2>\n\n <p class=\"sce-library-access-denied__body-ar\">\n @switch (effectiveReason()) {\n @case ('missing') {\n \u0644\u0645 \u064A\u062A\u0645 \u062A\u0645\u0631\u064A\u0631 \u0645\u0641\u062A\u0627\u062D \u0648\u0635\u0648\u0644 \u0644\u0645\u0643\u062A\u0628\u0629 SCE \u0641\u064A \u0647\u0630\u0627 \u0627\u0644\u062A\u0637\u0628\u064A\u0642. \u064A\u0631\u062C\u0649 \u0627\u0644\u062A\u0648\u0627\u0635\u0644 \u0645\u0639 \u0641\u0631\u064A\u0642 SCE \u0645\u0639\u062A\u0645\u062F \u0644\u0644\u062D\u0635\u0648\u0644 \u0639\u0644\u0649 \u0645\u0641\u062A\u0627\u062D \u0648\u062A\u0643\u0648\u064A\u0646\u0647 \u0641\u064A provideSceCore().\n }\n @case ('invalid') {\n \u0645\u0641\u062A\u0627\u062D \u0627\u0644\u0648\u0635\u0648\u0644 \u0627\u0644\u0645\u064F\u0643\u0648\u064E\u0651\u0646 \u0641\u064A \u0647\u0630\u0627 \u0627\u0644\u062A\u0637\u0628\u064A\u0642 \u063A\u064A\u0631 \u0645\u0635\u0631\u062D \u0628\u0647. \u064A\u0631\u062C\u0649 \u0627\u0644\u062A\u0648\u0627\u0635\u0644 \u0645\u0639 \u0641\u0631\u064A\u0642 SCE \u0645\u0639\u062A\u0645\u062F \u0644\u0644\u062A\u062D\u0642\u0642 \u0645\u0646 \u0627\u0644\u0645\u0641\u062A\u0627\u062D \u0623\u0648 \u0637\u0644\u0628 \u0645\u0641\u062A\u0627\u062D \u062C\u062F\u064A\u062F.\n }\n }\n </p>\n\n <p class=\"sce-library-access-denied__body-en\">\n @switch (effectiveReason()) {\n @case ('missing') {\n This app did not pass a libraryAccessToken when bootstrapping @moatamed-sce/core. Contact the SCE Moatamed team to request a\n key.\n }\n @case ('invalid') {\n The libraryAccessToken configured for this app is not authorized. Contact the SCE Moatamed team to verify or renew your key.\n }\n }\n </p>\n\n <p class=\"sce-library-access-denied__dev-hint\">\n @switch (effectiveReason()) {\n @case ('missing') {\n provideSceCore({ libraryAccessToken: environment.sceLibraryAccessToken })\n }\n @case ('invalid') {\n Check environment.sceLibraryAccessToken matches the key SCE Moatamed issued for this app.\n }\n }\n </p>\n\n <p class=\"sce-library-access-denied__contact-label\">SCE Moatamed team \u00B7 \u0641\u0631\u064A\u0642 SCE \u0645\u0639\u062A\u0645\u062F</p>\n\n <sce-button variant=\"primary\" class=\"sce-library-access-denied__contact\" [href]=\"mailtoHref()\">\n {{ contactEmail }}\n </sce-button>\n</section>\n", styles: [":host.sce-library-access-denied{display:flex;align-items:center;justify-content:center;min-height:100dvb;padding:var(--space-24);background:linear-gradient(160deg,var(--color-neutral-950) 0%,var(--color-neutral-900) 55%,var(--color-neutral-950) 100%)}.sce-library-access-denied__panel{display:flex;flex-direction:column;gap:var(--space-16);align-items:center;max-width:35rem;margin-inline:auto;padding:var(--space-32) var(--space-28);border:1px solid color-mix(in srgb,var(--color-white) 12%,transparent);border-radius:var(--radius-2xl);background:color-mix(in srgb,var(--color-white) 4%,transparent);color:var(--color-white);text-align:center}.sce-library-access-denied__badge{margin:0;font-size:var(--font-size-xs);font-weight:var(--font-weight-semibold);letter-spacing:.08em;text-transform:uppercase;opacity:.65}.sce-library-access-denied__title-ar{margin:0;font-size:var(--font-size-2xl);font-weight:var(--font-weight-bold);line-height:1.4}.sce-library-access-denied__title-en{margin:0;font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);opacity:.85}.sce-library-access-denied__body-ar{margin:0;font-size:var(--font-size-base);line-height:1.8;opacity:.92}.sce-library-access-denied__body-en{margin:0;font-size:var(--font-size-sm);line-height:1.7;opacity:.78}.sce-library-access-denied__dev-hint{margin:0;padding:var(--space-10) var(--space-12);border-radius:var(--radius-8);background:color-mix(in srgb,var(--color-neutral-950) 25%,transparent);font-family:var(--font-family-mono, ui-monospace, monospace);font-size:var(--font-size-xs);line-height:1.5;opacity:.85;overflow-wrap:anywhere}.sce-library-access-denied__contact-label{margin:var(--space-8) 0 0;font-size:var(--font-size-sm);opacity:.75}.sce-library-access-denied__contact{margin-block-start:var(--space-4);text-decoration:none}\n"], dependencies: [{ kind: "component", type: SceButton, selector: "sce-button", inputs: ["variant", "type", "fullWidth", "disabled", "loading", "size", "icon", "iconPosition", "iconSize", "ariaLabel", "routerLink", "href"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
10204
|
+
}
|
|
10205
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SceLibraryAccessDeniedComponent, decorators: [{
|
|
10206
|
+
type: Component,
|
|
10207
|
+
args: [{ host: { class: 'sce-library-access-denied' }, selector: 'sce-library-access-denied', standalone: true, imports: [SceButton], changeDetection: ChangeDetectionStrategy.OnPush, template: "<section class=\"sce-library-access-denied__panel\" role=\"alert\" aria-live=\"assertive\">\n <p class=\"sce-library-access-denied__badge\">@moatamed-sce</p>\n\n <h1 class=\"sce-library-access-denied__title-ar\">\n @switch (effectiveReason()) {\n @case ('missing') {\n \u0645\u0641\u062A\u0627\u062D \u0627\u0644\u0648\u0635\u0648\u0644 \u063A\u064A\u0631 \u0645\u064F\u0639\u0631\u064E\u0651\u0641\n }\n @case ('invalid') {\n \u0645\u0641\u062A\u0627\u062D \u0627\u0644\u0648\u0635\u0648\u0644 \u063A\u064A\u0631 \u0635\u0627\u0644\u062D\n }\n }\n </h1>\n\n <h2 class=\"sce-library-access-denied__title-en\">\n @switch (effectiveReason()) {\n @case ('missing') {\n Access key not configured\n }\n @case ('invalid') {\n Access key not authorized\n }\n }\n </h2>\n\n <p class=\"sce-library-access-denied__body-ar\">\n @switch (effectiveReason()) {\n @case ('missing') {\n \u0644\u0645 \u064A\u062A\u0645 \u062A\u0645\u0631\u064A\u0631 \u0645\u0641\u062A\u0627\u062D \u0648\u0635\u0648\u0644 \u0644\u0645\u0643\u062A\u0628\u0629 SCE \u0641\u064A \u0647\u0630\u0627 \u0627\u0644\u062A\u0637\u0628\u064A\u0642. \u064A\u0631\u062C\u0649 \u0627\u0644\u062A\u0648\u0627\u0635\u0644 \u0645\u0639 \u0641\u0631\u064A\u0642 SCE \u0645\u0639\u062A\u0645\u062F \u0644\u0644\u062D\u0635\u0648\u0644 \u0639\u0644\u0649 \u0645\u0641\u062A\u0627\u062D \u0648\u062A\u0643\u0648\u064A\u0646\u0647 \u0641\u064A provideSceCore().\n }\n @case ('invalid') {\n \u0645\u0641\u062A\u0627\u062D \u0627\u0644\u0648\u0635\u0648\u0644 \u0627\u0644\u0645\u064F\u0643\u0648\u064E\u0651\u0646 \u0641\u064A \u0647\u0630\u0627 \u0627\u0644\u062A\u0637\u0628\u064A\u0642 \u063A\u064A\u0631 \u0645\u0635\u0631\u062D \u0628\u0647. \u064A\u0631\u062C\u0649 \u0627\u0644\u062A\u0648\u0627\u0635\u0644 \u0645\u0639 \u0641\u0631\u064A\u0642 SCE \u0645\u0639\u062A\u0645\u062F \u0644\u0644\u062A\u062D\u0642\u0642 \u0645\u0646 \u0627\u0644\u0645\u0641\u062A\u0627\u062D \u0623\u0648 \u0637\u0644\u0628 \u0645\u0641\u062A\u0627\u062D \u062C\u062F\u064A\u062F.\n }\n }\n </p>\n\n <p class=\"sce-library-access-denied__body-en\">\n @switch (effectiveReason()) {\n @case ('missing') {\n This app did not pass a libraryAccessToken when bootstrapping @moatamed-sce/core. Contact the SCE Moatamed team to request a\n key.\n }\n @case ('invalid') {\n The libraryAccessToken configured for this app is not authorized. Contact the SCE Moatamed team to verify or renew your key.\n }\n }\n </p>\n\n <p class=\"sce-library-access-denied__dev-hint\">\n @switch (effectiveReason()) {\n @case ('missing') {\n provideSceCore({ libraryAccessToken: environment.sceLibraryAccessToken })\n }\n @case ('invalid') {\n Check environment.sceLibraryAccessToken matches the key SCE Moatamed issued for this app.\n }\n }\n </p>\n\n <p class=\"sce-library-access-denied__contact-label\">SCE Moatamed team \u00B7 \u0641\u0631\u064A\u0642 SCE \u0645\u0639\u062A\u0645\u062F</p>\n\n <sce-button variant=\"primary\" class=\"sce-library-access-denied__contact\" [href]=\"mailtoHref()\">\n {{ contactEmail }}\n </sce-button>\n</section>\n", styles: [":host.sce-library-access-denied{display:flex;align-items:center;justify-content:center;min-height:100dvb;padding:var(--space-24);background:linear-gradient(160deg,var(--color-neutral-950) 0%,var(--color-neutral-900) 55%,var(--color-neutral-950) 100%)}.sce-library-access-denied__panel{display:flex;flex-direction:column;gap:var(--space-16);align-items:center;max-width:35rem;margin-inline:auto;padding:var(--space-32) var(--space-28);border:1px solid color-mix(in srgb,var(--color-white) 12%,transparent);border-radius:var(--radius-2xl);background:color-mix(in srgb,var(--color-white) 4%,transparent);color:var(--color-white);text-align:center}.sce-library-access-denied__badge{margin:0;font-size:var(--font-size-xs);font-weight:var(--font-weight-semibold);letter-spacing:.08em;text-transform:uppercase;opacity:.65}.sce-library-access-denied__title-ar{margin:0;font-size:var(--font-size-2xl);font-weight:var(--font-weight-bold);line-height:1.4}.sce-library-access-denied__title-en{margin:0;font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);opacity:.85}.sce-library-access-denied__body-ar{margin:0;font-size:var(--font-size-base);line-height:1.8;opacity:.92}.sce-library-access-denied__body-en{margin:0;font-size:var(--font-size-sm);line-height:1.7;opacity:.78}.sce-library-access-denied__dev-hint{margin:0;padding:var(--space-10) var(--space-12);border-radius:var(--radius-8);background:color-mix(in srgb,var(--color-neutral-950) 25%,transparent);font-family:var(--font-family-mono, ui-monospace, monospace);font-size:var(--font-size-xs);line-height:1.5;opacity:.85;overflow-wrap:anywhere}.sce-library-access-denied__contact-label{margin:var(--space-8) 0 0;font-size:var(--font-size-sm);opacity:.75}.sce-library-access-denied__contact{margin-block-start:var(--space-4);text-decoration:none}\n"] }]
|
|
10208
|
+
}], propDecorators: { reason: [{ type: i0.Input, args: [{ isSignal: true, alias: "reason", required: false }] }] } });
|
|
10209
|
+
|
|
10046
10210
|
/**
|
|
10047
10211
|
* @deprecated Use `<sce-result-state>` instead — it covers this component's entire surface with
|
|
10048
10212
|
* preset copy and actions. No production usages exist (design-system demo only); delete once the
|
|
@@ -10067,6 +10231,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10067
10231
|
args: [{ host: { class: 'sce-page-error' }, selector: 'sce-page-error', standalone: true, imports: [TranslatePipe, SceEmptyStateComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-page-error\">\n <sce-empty-state [titleKey]=\"titleKey()\" [subtitleKey]=\"subtitleKey()\" [icon]=\"icon()\" tone=\"error\">\n <button type=\"button\" class=\"sce-page-error__retry-btn\" (click)=\"retry.emit()\">\n {{ retryLabelKey() | translate }}\n </button>\n </sce-empty-state>\n</div>\n", styles: [":host{display:block}.sce-page-error{margin-block-start:var(--space-24);padding:var(--space-12);background:var(--color-white);border:1px solid var(--color-neutral);border-radius:var(--radius-lg)}.sce-page-error__retry-btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-2);padding:var(--space-2) var(--space-24);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-primary);background:transparent;border:1px solid var(--color-primary);border-radius:var(--radius-lg);cursor:pointer;transition:background-color .15s ease,color .15s ease;white-space:nowrap}.sce-page-error__retry-btn:hover{background:var(--color-primary);color:var(--color-white)}.sce-page-error__retry-btn:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}\n"] }]
|
|
10068
10232
|
}], propDecorators: { titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: true }] }], subtitleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitleKey", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], retryLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "retryLabelKey", required: false }] }], retry: [{ type: i0.Output, args: ["retry"] }] } });
|
|
10069
10233
|
|
|
10234
|
+
/** Page layout for authentication screens: a logo, title and subtitle header (each settable as literal text or a translation key) above the projected form, with an optional decorative side panel and footer. */
|
|
10070
10235
|
class SceAuthLayoutComponent {
|
|
10071
10236
|
/** Logo image URL for the auth header */
|
|
10072
10237
|
logoSrc = input('', ...(ngDevMode ? [{ debugName: "logoSrc" }] : /* istanbul ignore next */ []));
|
|
@@ -10141,6 +10306,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10141
10306
|
args: [{ host: { class: 'sce-status-page' }, selector: 'sce-status-page', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div class=\"sce-status-page-layout\">\n <header class=\"sce-status-page-layout__header\">\n <a class=\"sce-status-page-layout__brand\" href=\"/\" [attr.aria-label]=\"'ARIA.HOME' | translate\">\n <!-- `logo.png` is white ink (for dark surfaces); `logo_dark.png` is dark ink (for light ones). -->\n <img class=\"sce-status-page-layout__logo sce-status-page-layout__logo--on-light\" src=\"/logo_dark.png\" alt=\"\" />\n <img class=\"sce-status-page-layout__logo sce-status-page-layout__logo--on-dark\" src=\"/logo.png\" alt=\"\" />\n </a>\n </header>\n\n <main class=\"sce-status-page-layout__main\">\n <div class=\"sce-status-page-layout__card\">\n <section class=\"sce-status-page\" [class]=\"variantClass()\" [attr.aria-labelledby]=\"titleId\">\n <span class=\"sce-status-page__accent\" aria-hidden=\"true\"></span>\n\n @if (code()) {\n <span class=\"sce-status-page__code-badge sce-status-page__stagger-1\">{{ code() }}</span>\n }\n\n @if (imageSrc()) {\n <div class=\"sce-status-page__illustration sce-status-page__stagger-2\">\n <img\n class=\"sce-status-page__image\"\n [src]=\"imageSrc()\"\n [alt]=\"imageAlt()\"\n [attr.aria-hidden]=\"imageDecorative() ? 'true' : null\"\n />\n </div>\n } @else {\n <div class=\"sce-status-page__icon-wrapper sce-status-page__stagger-2\" [class]=\"'sce-status-page__icon-wrapper--' + iconVariant()\">\n <span class=\"sce-status-page__icon-ring\" aria-hidden=\"true\"></span>\n <svg\n class=\"sce-status-page__icon\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.75\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n @switch (iconVariant()) {\n @case ('error') {\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"M12 7.5v5\" />\n <path d=\"M12 16.25h.01\" />\n }\n @case ('warning') {\n <path d=\"M10.3 3.9 2.6 17a2 2 0 0 0 1.7 3h15.4a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z\" />\n <path d=\"M12 9v4\" />\n <path d=\"M12 17h.01\" />\n }\n @case ('info') {\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"M12 16v-4.5\" />\n <path d=\"M12 8h.01\" />\n }\n @case ('success') {\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"m8.5 12.2 2.4 2.4 4.6-5\" />\n }\n @default {\n <path d=\"M3.5 7.5 12 3l8.5 4.5v9L12 21l-8.5-4.5Z\" />\n <path d=\"M3.5 7.5 12 12l8.5-4.5\" />\n <path d=\"M12 12v9\" />\n }\n }\n </svg>\n </div>\n }\n\n <div class=\"sce-status-page__copy sce-status-page__stagger-3\">\n <h1 [id]=\"titleId\" class=\"sce-status-page__title\">\n {{ titleKey() | translate }}\n </h1>\n\n @if (subtitleKey()) {\n <p class=\"sce-status-page__subtitle\">\n {{ subtitleKey() | translate }}\n </p>\n }\n </div>\n\n <span class=\"sce-status-page__divider sce-status-page__stagger-4\" aria-hidden=\"true\"></span>\n\n <div class=\"sce-status-page__actions sce-status-page__stagger-5\">\n <ng-content />\n </div>\n </section>\n </div>\n </main>\n\n <footer class=\"sce-status-page-layout__footer\">\n <img src=\"/logo_dark.png\" alt=\"\" class=\"sce-status-page-layout__footer-logo sce-status-page-layout__logo--on-light\" />\n <img src=\"/logo.png\" alt=\"\" class=\"sce-status-page-layout__footer-logo sce-status-page-layout__logo--on-dark\" />\n </footer>\n</div>\n", styles: ["sce-status-page{display:block;min-height:var(--sce-status-page-min-block-size, 100dvb)}.sce-status-page-layout{--sce-status-card-max-width: 34rem;--sce-status-icon-size: var(--space-96);--sce-status-icon-glyph-size: var(--space-40);--sce-status-glow-size: var(--space-160);--sce-status-decor-size: clamp(18rem, 40vi, 36rem);width:100%;position:relative;display:flex;flex-direction:column;align-items:center;min-height:var(--sce-status-page-min-block-size, 100dvb);overflow:hidden;background:radial-gradient(ellipse at 30% 20%,rgba(39,177,167,.06) 0%,transparent 60%),radial-gradient(ellipse at 70% 80%,rgba(0,52,73,.05) 0%,transparent 60%),var(--surface-section-soft)}.sce-status-page-layout:before,.sce-status-page-layout:after{content:\"\";position:absolute;inset:0;z-index:0;background-image:url(/images/h1_shape%201.png);background-repeat:no-repeat;background-size:var(--sce-status-decor-size);opacity:.07}.sce-status-page-layout:before{background-position:right bottom}.sce-status-page-layout:after{background-position:left bottom;transform:scaleX(-1)}.sce-status-page-layout__header{position:absolute;top:0;inset-inline-start:0;inset-inline-end:0;display:flex;justify-content:flex-start;padding:var(--space-32);z-index:3}.sce-status-page-layout__brand{display:inline-flex;border-radius:var(--radius-md)}.sce-status-page-layout__brand:focus-visible{outline:var(--border-width-2) solid var(--color-brand-secondary-500);outline-offset:var(--space-4)}.sce-status-page-layout__logo{height:var(--space-36);width:auto;object-fit:contain;transition:opacity var(--transition-base)}.sce-status-page-layout__brand:hover .sce-status-page-layout__logo{opacity:.75}.sce-status-page-layout__logo--on-dark{display:none}.sce-status-page-layout__main{position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;justify-content:center;flex:1;width:100%;padding:var(--space-100) var(--space-24) var(--space-40)}.sce-status-page-layout__card{width:100%;max-width:var(--sce-status-card-max-width);animation:sce-status-card-enter var(--motion-duration-slow) var(--motion-ease-emphasized) forwards}.sce-status-page-layout__footer{position:relative;z-index:1;display:flex;align-items:center;justify-content:center;padding:var(--space-16) var(--space-24);opacity:.35;transition:opacity var(--transition-base)}.sce-status-page-layout__footer:hover{opacity:.55}.sce-status-page-layout__footer-logo{height:var(--space-20);width:auto;object-fit:contain}.sce-status-page{position:relative;display:flex;flex-direction:column;align-items:center;gap:0;text-align:center;padding:0 clamp(var(--space-24),4vi,var(--space-40)) clamp(2rem,5vi,var(--space-40));background:var(--surface-glass-light);backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);border:var(--border-width-1) solid var(--border-chip-light);border-radius:var(--radius-brand-lg);box-shadow:var(--shadow-card-lg);overflow:hidden}.sce-status-page__accent{display:block;width:100%;height:var(--space-4);margin-block-end:clamp(var(--space-24),4vi,2rem);background:linear-gradient(90deg,var(--color-brand-primary-800) 0%,var(--color-brand-secondary-500) 100%);flex-shrink:0;position:relative;overflow:hidden}.sce-status-page__accent:after{content:\"\";position:absolute;inset:0;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.4) 50%,transparent 100%);transform:translate(-100%);animation:sce-accent-shimmer 3s ease-in-out 1s infinite}.sce-status-page__code-badge{display:inline-flex;align-items:center;justify-content:center;min-width:var(--space-64);padding:var(--space-8) var(--space-20);background:var(--color-brand-primary-800);border-radius:var(--radius-full);font-family:ui-monospace,SF Mono,monospace;font-size:var(--font-size-sm);font-weight:var(--font-weight-bold);font-variant-numeric:tabular-nums;color:var(--color-white);letter-spacing:.12em;flex-shrink:0;margin-block-end:var(--space-16);box-shadow:var(--shadow-sm)}.sce-status-page__illustration{position:relative;display:flex;align-items:center;justify-content:center;margin-block-end:var(--space-24)}.sce-status-page__illustration:before{content:\"\";position:absolute;width:var(--sce-status-glow-size);height:var(--sce-status-glow-size);border-radius:var(--radius-full);background:radial-gradient(circle,var(--color-brand-secondary-100) 0%,transparent 70%);pointer-events:none}.sce-status-page__image{position:relative;width:auto;height:auto;max-width:min(var(--size-200),60%);max-height:var(--size-180);object-fit:contain;flex-shrink:0;animation:sce-illustration-float 4s ease-in-out .75s infinite}.sce-status-page__icon-wrapper{position:relative;display:flex;align-items:center;justify-content:center;width:var(--sce-status-icon-size);height:var(--sce-status-icon-size);border-radius:var(--radius-full);flex-shrink:0;margin-block-end:var(--space-24)}.sce-status-page__icon-wrapper--error{background:var(--color-red-100);color:var(--color-red-500)}.sce-status-page__icon-wrapper--warning{background:var(--color-yellow-100);color:var(--color-yellow-600)}.sce-status-page__icon-wrapper--info{background:var(--color-blue-100);color:var(--color-blue-500)}.sce-status-page__icon-wrapper--success{background:var(--color-brand-secondary-100);color:var(--color-brand-secondary-600)}.sce-status-page__icon-wrapper--neutral{background:var(--color-neutral-100);color:var(--color-text-muted)}.sce-status-page__icon-ring{position:absolute;inset:0;border-radius:var(--radius-full);border:var(--border-width-1) solid currentColor;opacity:0;animation:sce-icon-ring-pulse 2.8s var(--motion-ease-out) infinite;pointer-events:none}.sce-status-page__icon{position:relative;width:var(--sce-status-icon-glyph-size);height:var(--sce-status-icon-glyph-size);animation:sce-illustration-float 4s ease-in-out .75s infinite}.sce-status-page__copy{display:flex;flex-direction:column;align-items:center;gap:var(--space-8);margin-block-end:var(--space-24)}.sce-status-page__title{font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:clamp(var(--space-20),3vi,1.625rem);font-weight:var(--font-weight-bold);color:var(--text-text-primary-900);margin:0;line-height:1.4;text-wrap:balance;overflow-wrap:break-word}.sce-status-page__subtitle{font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-base);font-weight:var(--font-weight-regular);color:var(--text-text-secondary-700);margin:0;line-height:1.75;text-wrap:pretty;overflow-wrap:break-word;max-width:42ch}.sce-status-page__divider{display:block;width:100%;height:var(--space-1);background:linear-gradient(to right,transparent 0%,var(--border-subtle) 20%,var(--border-subtle) 80%,transparent 100%);margin-block-end:var(--space-24);flex-shrink:0}.sce-status-page__actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:var(--space-12);width:100%}.sce-status-page__stagger-1,.sce-status-page__stagger-2,.sce-status-page__stagger-3,.sce-status-page__stagger-4,.sce-status-page__stagger-5{opacity:0;animation:sce-stagger-in var(--motion-duration-slow) var(--motion-ease-emphasized) forwards}.sce-status-page__stagger-1{animation-delay:.15s}.sce-status-page__stagger-2{animation-delay:.25s}.sce-status-page__stagger-3{animation-delay:.4s}.sce-status-page__stagger-4{animation-delay:.55s}.sce-status-page__stagger-5{animation-delay:.65s}.sce-status-page--error .sce-status-page__illustration:before{background:radial-gradient(circle,var(--color-red-100) 0%,transparent 70%)}.sce-status-page--warning .sce-status-page__illustration:before{background:radial-gradient(circle,var(--color-yellow-100) 0%,transparent 70%)}.sce-status-page--info .sce-status-page__illustration:before{background:radial-gradient(circle,var(--color-blue-100) 0%,transparent 70%)}.sce-status-page--success .sce-status-page__illustration:before{background:radial-gradient(circle,var(--color-brand-secondary-100) 0%,transparent 70%)}.sce-status-page--error .sce-status-page__accent{background:linear-gradient(90deg,var(--color-red-500) 0%,var(--color-red-300) 100%)}.sce-status-page--error .sce-status-page__code-badge{background:var(--color-red-500)}.sce-status-page--warning .sce-status-page__accent{background:linear-gradient(90deg,var(--color-yellow-500) 0%,var(--color-yellow-300) 100%)}.sce-status-page--warning .sce-status-page__code-badge{background:var(--color-yellow-600)}.sce-status-page--info .sce-status-page__accent{background:linear-gradient(90deg,var(--color-blue-500) 0%,var(--color-blue-300) 100%)}.sce-status-page--info .sce-status-page__code-badge{background:var(--color-blue-500)}.sce-status-page--success .sce-status-page__accent{background:linear-gradient(90deg,var(--color-brand-secondary-600) 0%,var(--color-brand-secondary-300) 100%)}.sce-status-page--success .sce-status-page__code-badge{background:var(--color-brand-secondary-600)}.sce-status-page--neutral .sce-status-page__accent{background:linear-gradient(90deg,var(--color-brand-primary-800) 0%,var(--color-brand-secondary-500) 100%)}@keyframes sce-status-card-enter{0%{opacity:0;transform:translateY(var(--motion-distance-lg)) scale(.97)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes sce-stagger-in{0%{opacity:0;transform:translateY(var(--motion-distance-sm))}to{opacity:1;transform:translateY(0)}}@keyframes sce-illustration-float{0%,to{transform:translateY(0)}50%{transform:translateY(-6px)}}@keyframes sce-icon-ring-pulse{0%{transform:scale(1);opacity:.5}70%,to{transform:scale(1.35);opacity:0}}@keyframes sce-accent-shimmer{0%{transform:translate(-100%)}to{transform:translate(100%)}}@media(prefers-reduced-motion:reduce){.sce-status-page-layout__card,.sce-status-page__stagger-1,.sce-status-page__stagger-2,.sce-status-page__stagger-3,.sce-status-page__stagger-4,.sce-status-page__stagger-5{animation:none;opacity:1}.sce-status-page__image,.sce-status-page__icon,.sce-status-page__icon-ring,.sce-status-page__accent:after{animation:none}}html[data-theme=dark] .sce-status-page-layout{background:radial-gradient(ellipse at 30% 20%,rgba(39,177,167,.08) 0%,transparent 60%),radial-gradient(ellipse at 70% 80%,rgba(0,52,73,.1) 0%,transparent 60%),var(--color-bg)}html[data-theme=dark] .sce-status-page-layout:before,html[data-theme=dark] .sce-status-page-layout:after{opacity:.04}html[data-theme=dark] .sce-status-page-layout__logo{opacity:.9}.sce-status-page-layout__brand:hover html[data-theme=dark] .sce-status-page-layout__logo{opacity:.7}html[data-theme=dark] .sce-status-page-layout__logo--on-light{display:none}html[data-theme=dark] .sce-status-page-layout__logo--on-dark{display:block}html[data-theme=dark] .sce-status-page{background:var(--surface-card-frosted);border-color:var(--border-on-brand-faint);box-shadow:var(--shadow-panel-md)}html[data-theme=dark] .sce-status-page__title{color:var(--text-text-primary-900)}html[data-theme=dark] .sce-status-page__subtitle{color:var(--text-text-secondary-700)}html[data-theme=dark] .sce-status-page__divider{background:linear-gradient(to right,transparent 0%,var(--border-on-brand-faint) 20%,var(--border-on-brand-faint) 80%,transparent 100%)}html[data-theme=dark] .sce-status-page__icon-wrapper--error{background:#ef444426}html[data-theme=dark] .sce-status-page__icon-wrapper--warning{background:#f59e0b26}html[data-theme=dark] .sce-status-page__icon-wrapper--info{background:#3b82f626}html[data-theme=dark] .sce-status-page__icon-wrapper--success{background:#27b1a726}html[data-theme=dark] .sce-status-page__icon-wrapper--neutral{background:var(--surface-on-brand-subtle)}@media(max-width:640px){.sce-status-page-layout{--sce-status-icon-size: var(--space-72);--sce-status-icon-glyph-size: var(--space-32);--sce-status-glow-size: var(--space-96);--sce-status-decor-size: 14rem}.sce-status-page-layout__header{padding:var(--space-16)}.sce-status-page-layout__logo{height:var(--space-28)}.sce-status-page-layout__main{padding:var(--space-80) var(--space-16) var(--space-24)}.sce-status-page-layout__footer-logo{height:var(--space-16)}.sce-status-page-layout:before,.sce-status-page-layout:after{opacity:.04}.sce-status-page{padding:0 var(--space-20) var(--space-24);border-radius:var(--radius-brand-sm)}.sce-status-page__accent{margin-block-end:var(--space-20)}.sce-status-page__image{max-width:var(--size-140);max-height:var(--size-140)}.sce-status-page__title{font-size:var(--font-size-xl)}.sce-status-page__subtitle{font-size:var(--font-size-md)}}@media print{.sce-status-page-layout{background:var(--color-base-white);min-height:auto}.sce-status-page-layout:before,.sce-status-page-layout:after{display:none}.sce-status-page-layout__header{position:static;padding:var(--space-16)}.sce-status-page-layout__footer{display:none}.sce-status-page{background:var(--color-base-white);-webkit-backdrop-filter:none;backdrop-filter:none;box-shadow:none;border:var(--border-width-1) solid var(--border-neutral-primary)}.sce-status-page__accent:after,.sce-status-page__image,.sce-status-page__icon,.sce-status-page__icon-ring{animation:none}.sce-status-page__stagger-1,.sce-status-page__stagger-2,.sce-status-page__stagger-3,.sce-status-page__stagger-4,.sce-status-page__stagger-5,.sce-status-page-layout__card{animation:none;opacity:1}}\n"] }]
|
|
10142
10307
|
}], propDecorators: { iconVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconVariant", required: false }] }], imageSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageSrc", required: false }] }], imageAlt: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageAlt", required: false }] }], code: [{ type: i0.Input, args: [{ isSignal: true, alias: "code", required: false }] }], titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: true }] }], subtitleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitleKey", required: false }] }] } });
|
|
10143
10308
|
|
|
10309
|
+
/** Searchable single- or multi-select list (`multiSelect` defaults to true) that filters `items` in-place and emits the full `selectedValues` array; rows can be overridden with a projected `ng-template`, and `loading` swaps in skeletons. */
|
|
10144
10310
|
class SceSelectableListWithSearchComponent {
|
|
10145
10311
|
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
10146
10312
|
items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
@@ -10206,6 +10372,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10206
10372
|
}, template: "<div\n [class.sce-selectable-list--primary]=\"variant() === 'primary'\"\n [class.sce-selectable-list--black]=\"variant() === 'black'\"\n class=\"sce-selectable-list\"\n>\n @if (title()) {\n <h3 class=\"sce-selectable-list__title\">{{ title() }}</h3>\n }\n\n <div class=\"sce-selectable-list__search\">\n <span class=\"sce-selectable-list__search-icon\" aria-hidden=\"true\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <circle cx=\"11\" cy=\"11\" r=\"8\"></circle>\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"></line>\n </svg>\n </span>\n <input\n type=\"text\"\n class=\"sce-selectable-list__search-input\"\n [placeholder]=\"searchPlaceholder() || ('COMMON.SEARCH' | translate)\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n />\n </div>\n\n @if (loading()) {\n <ul class=\"sce-selectable-list__items\" role=\"list\" aria-busy=\"true\">\n @for (i of [1, 2, 3, 4, 5]; track i) {\n <li class=\"sce-selectable-list__item\">\n <sce-skeleton variant=\"rectangular\" height=\"64px\" borderRadius=\"12px\" />\n </li>\n }\n </ul>\n } @else {\n <ul class=\"sce-selectable-list__items\" role=\"list\">\n @for (view of itemViews(); track view.item.value; let i = $index) {\n <li class=\"sce-selectable-list__item\">\n <button\n type=\"button\"\n class=\"sce-selectable-list__item-btn\"\n [class.sce-selectable-list__item-btn--selected]=\"view.selected\"\n [class.sce-selectable-list__item-btn--disabled]=\"view.item.disabled\"\n [disabled]=\"view.item.disabled\"\n (click)=\"toggleItem(view.item)\"\n >\n @if (!rtl()) {\n <span class=\"sce-selectable-list__checkbox\" [class.sce-selectable-list__checkbox--checked]=\"view.selected\">\n @if (view.selected) {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n }\n </span>\n }\n <span class=\"sce-selectable-list__item-content\">\n @if (!itemTemplate()) {\n <span class=\"sce-selectable-list__item-label\">{{ view.item.label }}</span>\n @if (view.item.subLabel) {\n <span class=\"sce-selectable-list__item-sublabel\">{{ view.item.subLabel }}</span>\n }\n } @else {\n <ng-container [ngTemplateOutlet]=\"itemTemplate()!\" [ngTemplateOutletContext]=\"{ $implicit: view.item, index: i }\" />\n }\n </span>\n @if (rtl()) {\n <span class=\"sce-selectable-list__checkbox\" [class.sce-selectable-list__checkbox--checked]=\"view.selected\">\n @if (view.selected) {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n }\n </span>\n }\n </button>\n </li>\n } @empty {\n <li class=\"sce-selectable-list__empty\">{{ 'COMMON.NO_RESULTS' | translate }}</li>\n }\n </ul>\n }\n</div>\n", styles: [":host{display:block}.sce-selectable-list{display:flex;flex-direction:column;gap:var(--space-lg);min-width:var(--size-280)}.sce-selectable-list--primary{--selection-color: var(--color-primary);--selection-background-color: var(--color-accent-success-overlay-20)}.sce-selectable-list--black{--selection-color: var(--background-neutral-950);--selection-background-color: var(--color-neutral-50)}.sce-selectable-list__title{margin:0;font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);color:var(--color-text-display)}.sce-selectable-list__search{position:relative;display:flex;align-items:center}.sce-selectable-list__search-icon{position:absolute;inset-inline-start:var(--space-md);display:flex;align-items:center;justify-content:center;color:var(--color-text-muted-gray);pointer-events:none}.sce-selectable-list__search-input{width:100%;height:var(--size-44);padding-inline-start:calc(var(--space-md) + var(--space-18) + var(--space-xs));padding-inline-end:var(--space-md);font-size:var(--font-size-md);color:var(--color-text-display);background:var(--color-neutral-50);border:1px solid var(--color-border-light);border-radius:var(--radius-lg);font-family:inherit;transition:border-color .15s,box-shadow .15s}.sce-selectable-list__search-input::placeholder{color:var(--Form-field-text-placeholder, var(--color-neutral-500));font-weight:500}.sce-selectable-list__search-input:focus{outline:none;border-color:var(--selection-color);box-shadow:0 0 0 2px var(--selection-background-color)}.sce-selectable-list__items{display:flex;flex-direction:column;gap:var(--space-sm);margin:0;padding:0;list-style:none;overflow-y:auto}.sce-selectable-list__item{margin:0;padding:0;list-style:none}.sce-selectable-list__item-btn{display:flex;align-items:center;gap:var(--space-md);width:100%;padding:var(--space-md) var(--space-lg);text-align:start;background:var(--color-neutral-50);border:1px solid transparent;border-radius:var(--radius-lg);height:var(--space-64);cursor:pointer;font-family:inherit;transition:background-color .15s,border-color .15s}.sce-selectable-list__item-btn:hover:not(:disabled){background:var(--color-neutral-100);border-color:var(--color-border-light)}.sce-selectable-list__item-btn--disabled{opacity:.5;cursor:not-allowed}.sce-selectable-list__item-btn:focus-visible{outline:2px solid var(--selection-color);outline-offset:2px}.sce-selectable-list__checkbox{flex-shrink:0;width:var(--size-20);height:var(--size-20);display:flex;align-items:center;justify-content:center;background:var(--color-white);border:2px solid var(--color-border-light);border-radius:var(--radius-md);color:var(--color-white);transition:all .15s}.sce-selectable-list__checkbox--checked{background:var(--selection-color);border-color:var(--selection-color)}.sce-selectable-list__item-content{display:flex;flex-direction:column;gap:var(--space-2);flex:1;min-width:0}.sce-selectable-list__item-label{font-size:var(--font-size-md);font-weight:var(--font-weight-medium);color:var(--color-text-display)}.sce-selectable-list__item-sublabel{font-size:var(--font-size-sm);color:var(--color-text-muted-gray)}.sce-selectable-list__empty{padding:var(--space-xl);text-align:center;font-size:var(--font-size-sm);color:var(--color-text-muted-gray)}\n"] }]
|
|
10207
10373
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], itemTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => TemplateRef), { isSignal: true }] }], selectedValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedValues", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], multiSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiSelect", required: false }] }], rtl: [{ type: i0.Input, args: [{ isSignal: true, alias: "rtl", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], searchChange: [{ type: i0.Output, args: ["searchChange"] }] } });
|
|
10208
10374
|
|
|
10375
|
+
/** Bar of currently-applied filter tags (`activeFilters`) with an optional counter, "save filter" and "clear all" actions; it only emits clicks and never mutates the tag list itself. */
|
|
10209
10376
|
class SceQuickFilterBarComponent {
|
|
10210
10377
|
activeFilters = input([], ...(ngDevMode ? [{ debugName: "activeFilters" }] : /* istanbul ignore next */ []));
|
|
10211
10378
|
showSaveFilter = input(true, ...(ngDevMode ? [{ debugName: "showSaveFilter" }] : /* istanbul ignore next */ []));
|
|
@@ -10228,6 +10395,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10228
10395
|
}, template: "<div class=\"sce-quick-filter-bar\">\n @if (title()) {\n <div class=\"sce-quick-filter-bar__title\">{{ title() }}</div>\n }\n\n <div class=\"sce-quick-filter-bar__row\" [style.justify-content]=\"rowJustify()\">\n <div class=\"sce-quick-filter-bar__tags\" [style.gap]=\"tagGap() || null\">\n @for (tag of activeFilters(); track tag.key ?? $index) {\n @if (tag.values && tag.values.length > 0) {\n <div class=\"sce-quick-filter-bar__tag-group sce-quick-filter-bar__tag\">\n {{ tag.label | translate }} ({{ tag.count }}):\n @for (val of tag.values; track val) {\n <!-- When the inner remove button renders, the wrapper must NOT be interactive itself\n (axe: nested-interactive) \u2014 the button already emits the same event. -->\n <div\n [attr.role]=\"showRemoveButton() ? null : 'button'\"\n [attr.tabindex]=\"showRemoveButton() ? null : 0\"\n (click)=\"filterTagClick.emit({ key: tag.key, label: tag.label, count: 1, value: val ?? '' })\"\n (keydown.enter)=\"filterTagClick.emit({ key: tag.key, label: tag.label, count: 1, value: val ?? '' })\"\n (keydown.space)=\"\n $event.preventDefault(); filterTagClick.emit({ key: tag.key, label: tag.label, count: 1, value: val ?? '' })\n \"\n [attr.aria-label]=\"showRemoveButton() ? null : tag.label + ': ' + (val ?? '')\"\n >\n <span>\n {{ val ?? '' | translate }}\n @if (showRemoveButton()) {\n <button\n type=\"button\"\n class=\"sce-quick-filter-bar__tag-remove\"\n (click)=\"\n $event.stopPropagation(); filterTagClick.emit({ key: tag.key, label: tag.label, count: 1, value: val ?? '' })\n \"\n [attr.aria-label]=\"'COMMON.REMOVE' | translate\"\n >\n <i class=\"pi pi-times\"></i>\n </button>\n }\n </span>\n </div>\n }\n </div>\n } @else {\n <!-- Same nested-interactive guard as the grouped variant above. -->\n <div\n [attr.role]=\"showRemoveButton() ? null : 'button'\"\n [attr.tabindex]=\"showRemoveButton() ? null : 0\"\n class=\"sce-quick-filter-bar__tag\"\n (click)=\"filterTagClick.emit(tag)\"\n (keydown.enter)=\"filterTagClick.emit(tag)\"\n (keydown.space)=\"$event.preventDefault(); filterTagClick.emit(tag)\"\n [attr.aria-label]=\"showRemoveButton() ? null : tag.label + ': ' + tag.value\"\n >\n {{ tag.label | translate }} ({{ tag.count }}):\n <span>\n {{ tag.value | translate }}\n @if (showRemoveButton()) {\n <button\n type=\"button\"\n class=\"sce-quick-filter-bar__tag-remove\"\n (click)=\"$event.stopPropagation(); filterTagClick.emit(tag)\"\n [attr.aria-label]=\"'COMMON.REMOVE' | translate\"\n >\n <i class=\"pi pi-times\"></i>\n </button>\n }\n </span>\n </div>\n }\n } @empty {\n <div class=\"sce-quick-filter-bar__empty\">\n {{ 'COMMON.NO_ACTIVE_FILTERS' | translate }}\n </div>\n }\n </div>\n\n <div class=\"sce-quick-filter-bar__actions\">\n @if (showSaveFilter()) {\n <p-button\n [text]=\"true\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"pi pi-bookmark\"\n [label]=\"'COMMON.SAVE_FILTER' | translate\"\n (onClick)=\"saveFilterClick.emit()\"\n />\n }\n @if (showClearAll() && activeFilters().length > 0) {\n <p-button\n [text]=\"true\"\n severity=\"danger\"\n size=\"small\"\n icon=\"pi pi-trash\"\n [label]=\"'COMMON.CLEAR_ALL' | translate\"\n (onClick)=\"clearAllClick.emit()\"\n />\n }\n </div>\n </div>\n</div>\n", styles: [":host{display:block}.sce-quick-filter-bar{display:flex;flex-direction:row;align-items:center;flex-wrap:wrap;gap:var(--space-md);margin-block-start:var(--space-lg);margin-block-end:var(--space-lg)}.sce-quick-filter-bar__title{flex-shrink:0;white-space:nowrap;margin:0;font-size:var(--font-size-base);font-weight:var(--font-weight-semibold);color:var(--color-text-display);width:100%}.sce-quick-filter-bar__row{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-md);width:100%}.sce-quick-filter-bar__tags{display:flex;flex-wrap:wrap;gap:var(--space-md)}.sce-quick-filter-bar__empty{font-size:var(--font-size-sm);color:var(--color-text-muted-gray)}.sce-quick-filter-bar__tag{display:inline-flex;align-items:center;gap:var(--space-xs);padding:var(--space-sm) var(--space-md);background:var(--tag-background-neutral-light, var(--color-neutral-100));border-radius:var(--radius-lg);color:var(--color-text-display);font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);cursor:pointer;-webkit-user-select:none;user-select:none;transition:background-color .15s}.sce-quick-filter-bar__tag:hover{background:var(--background-neutral-pressed, var(--color-neutral-200))}.sce-quick-filter-bar__tag:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.sce-quick-filter-bar__tag span{padding:var(--space-4, var(--space-4)) var(--space-8, var(--space-8));color:var(--color-text-display);border-radius:var(--radius-full, var(--radius-full));background:var(--border-neutral-secondary, var(--color-neutral-200));font-size:var(--font-size-xs);font-weight:var(--font-weight-medium);display:flex;justify-content:center;align-items:center;gap:var(--space-xs)}.sce-quick-filter-bar__tag-remove{display:inline-flex;align-items:center;justify-content:center;background:none;border:none;cursor:pointer;padding:0;font-size:var(--font-size-xs);line-height:1;color:var(--color-text-muted-gray);flex-shrink:0}.sce-quick-filter-bar__tag-remove:hover{color:var(--color-text-display)}.sce-quick-filter-bar__tag-group{display:inline-flex;align-items:center;flex-wrap:wrap;gap:var(--space-xs)}.sce-quick-filter-bar__actions{display:flex;align-items:center;gap:var(--space-md);flex-wrap:wrap;flex-shrink:0}\n"] }]
|
|
10229
10396
|
}], propDecorators: { activeFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeFilters", required: false }] }], showSaveFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSaveFilter", required: false }] }], showClearAll: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClearAll", required: false }] }], quickFilterCounter: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickFilterCounter", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], tagGap: [{ type: i0.Input, args: [{ isSignal: true, alias: "tagGap", required: false }] }], showRemoveButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRemoveButton", required: false }] }], rowJustify: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowJustify", required: false }] }], saveFilterClick: [{ type: i0.Output, args: ["saveFilterClick"] }], clearAllClick: [{ type: i0.Output, args: ["clearAllClick"] }], filterTagClick: [{ type: i0.Output, args: ["filterTagClick"] }] } });
|
|
10230
10397
|
|
|
10398
|
+
/** Two-step user-verification panel that first collects a national ID and birth date, then the verified user's roles, contact details and active flag, emitting `verify` and `confirm` payloads. */
|
|
10231
10399
|
class SceUserVerifySectionPanelComponent {
|
|
10232
10400
|
// ── Inputs ──
|
|
10233
10401
|
step = input(1, ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
|
|
@@ -10341,6 +10509,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10341
10509
|
args: [{ selector: 'sce-user-verify-section-panel', standalone: true, imports: [FormsModule, TranslatePipe, MultiSelect, SceSwitchComponent, SceSkeleton], encapsulation: ViewEncapsulation.None, host: { class: 'sce-user-verify-panel' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Step 1: Enter national ID + birth date -->\n@if (step() === 1) {\n <div class=\"sce-user-verify-panel__step\">\n <div class=\"sce-user-verify-panel__fields-grid\">\n <div class=\"sce-user-verify-panel__field\">\n <label class=\"sce-user-verify-panel__field-label\" for=\"uvp-national-id\">\n {{ 'dashboard.accountUsers.dialog.nationalId' | translate }}\n <span aria-hidden=\"true\"> *</span>\n </label>\n <input\n id=\"uvp-national-id\"\n class=\"sce-user-verify-panel__input\"\n [class.sce-user-verify-panel__input--error]=\"nationalIdError()\"\n [placeholder]=\"'dashboard.accountUsers.dialog.nationalIdPlaceholder' | translate\"\n inputmode=\"numeric\"\n maxlength=\"10\"\n [ngModel]=\"nationalId()\"\n (ngModelChange)=\"onNationalIdChange($event)\"\n [attr.aria-describedby]=\"nationalIdError() ? 'uvp-national-id-error' : null\"\n />\n @if (nationalIdError()) {\n <span id=\"uvp-national-id-error\" class=\"sce-user-verify-panel__field-error\" role=\"alert\">\n {{ nationalIdError() | translate }}\n </span>\n }\n </div>\n\n <div class=\"sce-user-verify-panel__field\">\n <label class=\"sce-user-verify-panel__field-label\" for=\"uvp-birth-date\">\n {{ 'dashboard.accountUsers.dialog.birthDate' | translate }}\n <span aria-hidden=\"true\"> *</span>\n </label>\n <input\n id=\"uvp-birth-date\"\n class=\"sce-user-verify-panel__input\"\n [class.sce-user-verify-panel__input--error]=\"birthDateError()\"\n placeholder=\"YYYY-MM-DD\"\n inputmode=\"numeric\"\n maxlength=\"10\"\n [ngModel]=\"birthDate()\"\n (ngModelChange)=\"onBirthDateChange($event)\"\n [attr.aria-describedby]=\"birthDateError() ? 'uvp-birth-date-error' : null\"\n />\n @if (birthDateError()) {\n <span id=\"uvp-birth-date-error\" class=\"sce-user-verify-panel__field-error\" role=\"alert\">\n {{ birthDateError() | translate }}\n </span>\n }\n </div>\n </div>\n\n @if (error()) {\n <p class=\"sce-user-verify-panel__error-msg\" role=\"alert\">{{ error() }}</p>\n }\n\n @if (loading()) {\n <div class=\"sce-user-verify-panel__loading-bar\" aria-hidden=\"true\">\n <sce-skeleton variant=\"rectangular\" animation=\"wave\" height=\"var(--space-1)\" />\n </div>\n }\n\n <div class=\"sce-user-verify-panel__actions\">\n <button class=\"sce-user-verify-panel__btn sce-user-verify-panel__btn--secondary\" type=\"button\" (click)=\"onCancel()\">\n {{ 'dashboard.accountUsers.dialog.cancel' | translate }}\n </button>\n <button\n class=\"sce-user-verify-panel__btn sce-user-verify-panel__btn--primary\"\n type=\"button\"\n [disabled]=\"loading()\"\n (click)=\"onVerify()\"\n >\n {{ 'dashboard.accountUsers.dialog.verify' | translate }}\n </button>\n </div>\n </div>\n}\n\n<!-- Step 2: Show verified data, select roles, confirm -->\n@if (step() === 2) {\n <div class=\"sce-user-verify-panel__step\">\n @if (verifiedData(); as data) {\n <div class=\"sce-user-verify-panel__readonly-grid\">\n <div class=\"sce-user-verify-panel__readonly-field\">\n <p class=\"sce-user-verify-panel__field-label\">\n {{ 'dashboard.accountUsers.dialog.nationalId' | translate }}\n </p>\n <p class=\"sce-user-verify-panel__readonly-value\">{{ data.nationalId || '\u2014' }}</p>\n </div>\n <div class=\"sce-user-verify-panel__readonly-field\">\n <p class=\"sce-user-verify-panel__field-label\">\n {{ 'dashboard.accountUsers.dialog.birthDate' | translate }}\n </p>\n <p class=\"sce-user-verify-panel__readonly-value\">{{ data.birthDate || '\u2014' }}</p>\n </div>\n <div class=\"sce-user-verify-panel__readonly-field\">\n <p class=\"sce-user-verify-panel__field-label\">\n {{ 'dashboard.accountUsers.dialog.fullName' | translate }}\n </p>\n <p class=\"sce-user-verify-panel__readonly-value\">{{ data.name || '\u2014' }}</p>\n </div>\n\n @if (requireEmail()) {\n <div class=\"sce-user-verify-panel__field\">\n <label class=\"sce-user-verify-panel__field-label\" for=\"uvp-email\">\n {{ 'dashboard.accountUsers.dialog.email' | translate }}\n <span aria-hidden=\"true\"> *</span>\n </label>\n <input\n id=\"uvp-email\"\n class=\"sce-user-verify-panel__input\"\n [class.sce-user-verify-panel__input--error]=\"emailError()\"\n [ngModel]=\"email()\"\n (ngModelChange)=\"onEmailChange($event)\"\n inputmode=\"email\"\n [attr.aria-describedby]=\"emailError() ? 'uvp-email-error' : null\"\n />\n @if (emailError()) {\n <span id=\"uvp-email-error\" class=\"sce-user-verify-panel__field-error\" role=\"alert\">\n {{ emailError() | translate }}\n </span>\n }\n </div>\n } @else {\n <div class=\"sce-user-verify-panel__readonly-field\">\n <p class=\"sce-user-verify-panel__field-label\">\n {{ 'dashboard.accountUsers.dialog.email' | translate }}\n </p>\n <p class=\"sce-user-verify-panel__readonly-value\">{{ data.email || '\u2014' }}</p>\n </div>\n }\n\n @if (requireMobile()) {\n <div class=\"sce-user-verify-panel__field\">\n <label class=\"sce-user-verify-panel__field-label\" for=\"uvp-mobile\">\n {{ 'dashboard.accountUsers.dialog.mobile' | translate }}\n <span aria-hidden=\"true\"> *</span>\n </label>\n <input\n id=\"uvp-mobile\"\n class=\"sce-user-verify-panel__input\"\n [class.sce-user-verify-panel__input--error]=\"mobileError()\"\n [ngModel]=\"mobile()\"\n (ngModelChange)=\"onMobileChange($event)\"\n inputmode=\"numeric\"\n maxlength=\"15\"\n [attr.aria-describedby]=\"mobileError() ? 'uvp-mobile-error' : null\"\n />\n @if (mobileError()) {\n <span id=\"uvp-mobile-error\" class=\"sce-user-verify-panel__field-error\" role=\"alert\">\n {{ mobileError() | translate }}\n </span>\n }\n </div>\n } @else {\n <div class=\"sce-user-verify-panel__readonly-field\">\n <p class=\"sce-user-verify-panel__field-label\">\n {{ 'dashboard.accountUsers.dialog.mobile' | translate }}\n </p>\n <p class=\"sce-user-verify-panel__readonly-value\">{{ data.mobile || '\u2014' }}</p>\n </div>\n }\n </div>\n }\n\n <div class=\"sce-user-verify-panel__group\">\n <h4 class=\"sce-user-verify-panel__group-title\">\n {{ 'dashboard.accountUsers.dialog.permissions' | translate }}\n </h4>\n <div class=\"sce-user-verify-panel__multi-select\">\n @if (rolesLoading()) {\n <sce-skeleton variant=\"input\" animation=\"wave\" aria-hidden=\"true\" />\n } @else {\n <p-multiSelect\n [options]=\"roleOptions()\"\n [ngModel]=\"roleIds()\"\n (ngModelChange)=\"onRoleIdsChange($event)\"\n [ariaLabel]=\"'dashboard.accountUsers.dialog.permissions' | translate\"\n display=\"chip\"\n [selectedItemsLabel]=\"'dashboard.accountUsers.dialog.selectedItems' | translate\"\n [placeholder]=\"'dashboard.accountUsers.dialog.selectPermissions' | translate\"\n optionLabel=\"label\"\n optionValue=\"value\"\n appendTo=\"body\"\n />\n }\n </div>\n @if (rolesError()) {\n <span class=\"sce-user-verify-panel__field-error\" role=\"alert\">\n {{ rolesError() | translate }}\n </span>\n }\n\n <div class=\"sce-user-verify-panel__status-row\">\n <h4 class=\"sce-user-verify-panel__group-title\">\n {{ 'dashboard.accountUsers.dialog.userStatus' | translate }}\n </h4>\n <sce-switch\n [checked]=\"isActive()\"\n [showLabel]=\"true\"\n [activeLabel]=\"'dashboard.accountUsers.dialog.active' | translate\"\n [inactiveLabel]=\"'dashboard.accountUsers.dialog.inactive' | translate\"\n (checkedChange)=\"onIsActiveChange($event)\"\n />\n </div>\n </div>\n\n @if (error()) {\n <p class=\"sce-user-verify-panel__error-msg\" role=\"alert\">{{ error() }}</p>\n }\n\n @if (loading()) {\n <div class=\"sce-user-verify-panel__loading-bar\" aria-hidden=\"true\">\n <sce-skeleton variant=\"rectangular\" animation=\"wave\" height=\"var(--space-1)\" />\n </div>\n }\n\n <div class=\"sce-user-verify-panel__actions\">\n <button class=\"sce-user-verify-panel__btn sce-user-verify-panel__btn--secondary\" type=\"button\" (click)=\"onCancel()\">\n {{ 'dashboard.accountUsers.dialog.cancel' | translate }}\n </button>\n <button\n class=\"sce-user-verify-panel__btn sce-user-verify-panel__btn--primary\"\n type=\"button\"\n [disabled]=\"loading()\"\n (click)=\"onConfirm()\"\n >\n @if (submitLabel()) {\n {{ submitLabel() }}\n } @else {\n {{ 'dashboard.accountUsers.dialog.addUser' | translate }}\n }\n </button>\n </div>\n </div>\n}\n", styles: ["sce-user-verify-section-panel{display:block;width:100%;max-width:100%;box-sizing:border-box;border:1px solid var(--color-primary-100);border-radius:var(--radius-2xl, var(--radius-2xl));padding:var(--space-24);background:var(--color-surface);margin-block-end:var(--space-20)}.sce-user-verify-panel__step{display:flex;flex-direction:column;gap:var(--space-16)}.sce-user-verify-panel__fields-grid{display:grid;grid-template-columns:1fr;gap:var(--space-16);align-items:start;width:100%}.sce-user-verify-panel__fields-grid>*{min-width:0;width:100%}@media(min-width:768px){.sce-user-verify-panel__fields-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}.sce-user-verify-panel__field{display:flex;flex-direction:column;gap:var(--space-24)}.sce-user-verify-panel__field-label{font-family:var(--font-family-arabic-primary);font-size:var(--font-size-md);font-weight:500;color:var(--text-text-primary-900);margin:0}.sce-user-verify-panel__input{width:100%;box-sizing:border-box;height:var(--space-48);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl);background:var(--color-surface);padding-block:var(--space-12);padding-inline:var(--space-16);font-family:var(--font-family-arabic-primary);font-size:var(--font-size-md);font-weight:var(--font-weight-normal);color:var(--color-neutral-500);outline:none;transition:border-color .15s ease}.sce-user-verify-panel__input::placeholder{color:var(--color-neutral-500)}.sce-user-verify-panel__input:focus{border-color:var(--button-background-primary-bg-primary)}.sce-user-verify-panel__input:disabled{background:var(--app-surface-hover);color:var(--details-value-color);cursor:not-allowed}.sce-user-verify-panel__input--error{border:1.5px solid var(--text-text-error-primary)}.sce-user-verify-panel__input--error:focus{border-color:var(--text-text-error-primary)}.sce-user-verify-panel__field-error{font-size:var(--font-size-xs);color:var(--text-text-error-primary);margin:0}.sce-user-verify-panel__readonly-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12)}.sce-user-verify-panel__readonly-field{background:var(--app-surface-hover);border-radius:var(--radius-xl);padding:var(--space-16);display:grid;align-content:center;gap:var(--space-8)}.sce-user-verify-panel__readonly-value{color:var(--details-value-color);font-size:var(--details-value-size);font-weight:var(--details-value-weight);margin:0}.sce-user-verify-panel__group{display:flex;flex-direction:column;gap:var(--space-12);padding-block-start:var(--space-16);border-block-start:1px solid var(--color-primary-100)}.sce-user-verify-panel__group-title{margin:0;font-family:var(--font-family-arabic-primary);font-size:var(--font-size-md);font-weight:600;color:var(--text-text-primary-900)}.sce-user-verify-panel__multi-select{width:100%}.sce-user-verify-panel__status-row{display:flex;align-items:center;gap:var(--space-12);flex-wrap:wrap}.sce-user-verify-panel__actions{display:grid;grid-template-columns:1fr;gap:var(--space-12);width:100%;padding-block-start:var(--space-16);border-block-start:1px solid var(--color-primary-100)}@media(min-width:480px){.sce-user-verify-panel__actions{grid-template-columns:repeat(2,minmax(0,1fr))}}.sce-user-verify-panel__loading-bar{border-radius:var(--radius-full);overflow:hidden}.sce-user-verify-panel__error-msg{font-family:var(--font-family-arabic-primary);font-size:var(--font-size-md);color:var(--text-text-error-primary);margin:0}.sce-user-verify-panel__btn{display:inline-flex;align-items:center;justify-content:center;width:100%;min-height:var(--space-48);padding-block:var(--space-14);padding-inline:var(--space-24);border-radius:var(--radius-xl);font-family:var(--font-family-arabic-primary);font-weight:600;font-size:var(--font-size-lg);cursor:pointer;transition:opacity .15s ease,background .15s ease,box-shadow .15s ease,transform .1s ease}.sce-user-verify-panel__btn:disabled{opacity:.5;cursor:not-allowed}.sce-user-verify-panel__btn--primary{border:0;background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand);box-shadow:var(--shadow-brand-button)}.sce-user-verify-panel__btn--primary:hover:not(:disabled){background:var(--color-primary-700);box-shadow:var(--shadow-brand-button-hover)}.sce-user-verify-panel__btn--primary:active:not(:disabled){transform:translateY(1px)}.sce-user-verify-panel__btn--primary:disabled{box-shadow:none}.sce-user-verify-panel__btn--secondary{border:1px solid var(--button-background-primary-bg-disabled);background:var(--color-surface);color:var(--text-text-primary-900)}.sce-user-verify-panel__btn--secondary:hover:not(:disabled){background:var(--app-surface-hover)}\n"] }]
|
|
10342
10510
|
}], ctorParameters: () => [], propDecorators: { step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], verifiedData: [{ type: i0.Input, args: [{ isSignal: true, alias: "verifiedData", required: false }] }], roleOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "roleOptions", required: false }] }], rolesLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "rolesLoading", required: false }] }], requireEmail: [{ type: i0.Input, args: [{ isSignal: true, alias: "requireEmail", required: false }] }], requireMobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "requireMobile", required: false }] }], submitLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitLabel", required: false }] }], verify: [{ type: i0.Output, args: ["verify"] }], confirm: [{ type: i0.Output, args: ["confirm"] }], dismissed: [{ type: i0.Output, args: ["dismissed"] }] } });
|
|
10343
10511
|
|
|
10512
|
+
/** Renderer the file viewer picks for a file; `Unsupported` shows a download-only fallback. */
|
|
10344
10513
|
var FileType;
|
|
10345
10514
|
(function (FileType) {
|
|
10346
10515
|
FileType["Image"] = "image";
|
|
@@ -10681,6 +10850,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10681
10850
|
args: [{ selector: 'sce-timeline', standalone: true, imports: [DatePipe, TooltipModule, SceEmptyStateComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-timeline' }, template: "@if (items().length) {\n <ol class=\"sce-timeline__list\">\n @for (item of items(); track item.label) {\n <li class=\"sce-timeline__item\" [class.sce-timeline__item--active]=\"item.active\">\n <button type=\"button\" class=\"sce-timeline__row\" (click)=\"itemClick.emit(item)\">\n <span class=\"sce-timeline__marker\" aria-hidden=\"true\">\n @if (item.icon) {\n <i [class]=\"item.icon\"></i>\n }\n </span>\n <span class=\"sce-timeline__content\">\n <span class=\"sce-timeline__label\">{{ item.label }}</span>\n @if (item.dateDisplay || item.date) {\n <span class=\"sce-timeline__date\">{{ item.dateDisplay || (item.date | date: 'mediumDate') }}</span>\n }\n @if (item.segments?.length) {\n <span class=\"sce-timeline__segments\">\n @for (segment of item.segments; track segment.text) {\n <span class=\"sce-timeline__segment\" [pTooltip]=\"segment.tooltip || ''\">{{ segment.text }}</span>\n }\n </span>\n }\n </span>\n </button>\n </li>\n }\n </ol>\n} @else {\n <sce-empty-state [title]=\"emptyText()\" [compact]=\"true\" imageSrc=\"\" icon=\"clock\" />\n}\n", styles: [":host{display:block}.sce-timeline__list{margin:0;padding:0;list-style:none}.sce-timeline__item{position:relative;padding-inline-start:var(--space-8)}.sce-timeline__item:before{content:\"\";position:absolute;inset-block-start:var(--space-6);inset-inline-start:var(--space-8);inline-size:1px;block-size:calc(100% - var(--space-4));background:var(--color-border-light)}.sce-timeline__item:last-child:before{display:none}.sce-timeline__row{display:flex;align-items:flex-start;gap:var(--space-3);inline-size:100%;padding-block:var(--space-3);padding-inline:0;border:0;background:transparent;text-align:start;cursor:pointer}.sce-timeline__marker{position:absolute;inset-inline-start:0;display:flex;align-items:center;justify-content:center;inline-size:var(--space-16);block-size:var(--space-16);border:2px solid var(--color-border-light);border-radius:var(--radius-full);background:var(--color-surface);font-size:var(--font-size-sm);color:var(--color-text-muted)}.sce-timeline__item--active .sce-timeline__marker{border-color:var(--color-brand-secondary-600);background:var(--color-brand-secondary-600);color:var(--color-base-white, var(--background-bg-primary))}.sce-timeline__content{display:flex;flex-direction:column;gap:var(--space-2);padding-inline-start:var(--space-16)}.sce-timeline__label{font-size:var(--font-size-base);font-weight:600;color:var(--color-text-display)}.sce-timeline__date{font-size:var(--font-size-sm);color:var(--color-text-muted)}.sce-timeline__segments{display:flex;flex-wrap:wrap;gap:var(--space-2)}.sce-timeline__segment{padding-block:var(--space-2);padding-inline:var(--space-3);border-radius:var(--radius-sm);background:var(--color-background);font-size:var(--font-size-sm);color:var(--color-text-secondary)}\n"] }]
|
|
10682
10851
|
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }] } });
|
|
10683
10852
|
|
|
10853
|
+
/** User list with a client-side name search box; filtering happens internally and only `deleteUser` is emitted to the host. */
|
|
10684
10854
|
class SceSearchableUsersListComponent {
|
|
10685
10855
|
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
10686
10856
|
users = input([], ...(ngDevMode ? [{ debugName: "users" }] : /* istanbul ignore next */ []));
|
|
@@ -10709,6 +10879,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10709
10879
|
args: [{ selector: 'sce-searchable-users-list', standalone: true, imports: [SceIcon, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-searchable-users-list' }, template: "@if (title()) {\n <h3 class=\"sce-searchable-users-list__title\">{{ title() }}</h3>\n}\n\n<input type=\"search\" class=\"sce-searchable-users-list__search\" [placeholder]=\"searchPlaceholder()\" (input)=\"onSearchInput($event)\" />\n\n<ul class=\"sce-searchable-users-list__items\">\n @for (user of filteredUsers(); track user.id) {\n <li class=\"sce-searchable-users-list__item\">\n <div class=\"sce-searchable-users-list__meta\">\n <span class=\"sce-searchable-users-list__name\">{{ user.name }}</span>\n @if (user.subtitle) {\n <span class=\"sce-searchable-users-list__subtitle\">{{ user.subtitle }}</span>\n }\n </div>\n <button\n type=\"button\"\n class=\"sce-searchable-users-list__delete\"\n [attr.aria-label]=\"'COMMON.DELETE' | translate\"\n (click)=\"onDeleteClick(user)\"\n >\n <sce-icon name=\"trash-icon\" [size]=\"16\" />\n </button>\n </li>\n }\n</ul>\n", styles: [":host.sce-searchable-users-list{display:block}.sce-searchable-users-list{display:flex;flex-direction:column;gap:var(--space-3)}.sce-searchable-users-list__items{display:flex;flex-direction:column;gap:var(--space-2);margin:0;padding:0;list-style:none}.sce-searchable-users-list__item{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3)}\n"] }]
|
|
10710
10880
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], users: [{ type: i0.Input, args: [{ isSignal: true, alias: "users", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], deleteUser: [{ type: i0.Output, args: ["deleteUser"] }] } });
|
|
10711
10881
|
|
|
10882
|
+
/** Page header for detail screens with a title, breadcrumb trail and a row of action buttons that emit `actionClick` carrying the action's key. */
|
|
10712
10883
|
class SceDetailHeaderComponent {
|
|
10713
10884
|
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
10714
10885
|
breadcrumbs = input([], ...(ngDevMode ? [{ debugName: "breadcrumbs" }] : /* istanbul ignore next */ []));
|
|
@@ -10769,6 +10940,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10769
10940
|
args: [{ selector: 'sce-copy-button', standalone: true, imports: [TranslatePipe, SceBidiIsolate], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-copy-button' }, template: "<button\n type=\"button\"\n class=\"sce-copy-button__btn\"\n [class.sce-copy-button__btn--copied]=\"copied()\"\n [attr.aria-label]=\"(copied() ? 'COPY_BUTTON.COPIED' : 'COPY_BUTTON.COPY') | translate\"\n (click)=\"copy()\"\n>\n @if (showValue()) {\n <span class=\"sce-copy-button__value\">\n <!-- A value worth a copy button is almost always an identifier \u2014 isolate it. -->\n <sce-bidi-isolate [value]=\"value()\" />\n </span>\n } @else if (label()) {\n <span class=\"sce-copy-button__label\">{{ label() }}</span>\n }\n <i class=\"sce-copy-button__icon\" [class.pi]=\"true\" [class.pi-copy]=\"!copied()\" [class.pi-check]=\"copied()\" aria-hidden=\"true\"></i>\n</button>\n", styles: [":host{display:block;display:inline-flex}.sce-copy-button__btn{display:inline-flex;align-items:center;gap:var(--space-2);padding-block:var(--space-2);padding-inline:var(--space-3);border:1px solid var(--color-border-light);border-radius:var(--radius-md);background:var(--color-surface);font-size:var(--font-size-sm);color:var(--color-text-secondary);cursor:pointer}.sce-copy-button__btn--copied{border-color:var(--color-brand-secondary-600);color:var(--color-brand-secondary-600)}.sce-copy-button__value{font-variant-numeric:tabular-nums;letter-spacing:.02em}.sce-copy-button__icon{font-size:var(--font-size-sm)}\n"] }]
|
|
10770
10941
|
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }] } });
|
|
10771
10942
|
|
|
10943
|
+
/** Header for a request page: `title`, a copyable `requestId`, a coloured `status` tag, and a row of `metaItems` (date items are run through `LocalizedDatePipe`). */
|
|
10772
10944
|
class SceRequestHeaderComponent {
|
|
10773
10945
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
10774
10946
|
requestId = input.required(...(ngDevMode ? [{ debugName: "requestId" }] : /* istanbul ignore next */ []));
|
|
@@ -10784,6 +10956,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10784
10956
|
args: [{ selector: 'sce-request-header', standalone: true, imports: [TranslatePipe, LocalizedDatePipe, SceCopyButtonComponent, SceIcon, SceBidiIsolate], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-request-header' }, template: "<div class=\"sce-request-header__main\">\n <div class=\"sce-request-header__title-row\">\n <h3 class=\"sce-request-header__title\">{{ title() | translate }}</h3>\n <span class=\"sce-request-header__status sce-request-header__status--{{ status().color }}\">\n {{ status().label | translate }}\n </span>\n </div>\n\n @if (data()) {\n <div class=\"sce-request-header__date\">\n <span class=\"sce-request-header__date-label\">{{ dateLabelKey() | translate }}</span>\n <span class=\"sce-request-header__date-value\">{{ data() }}</span>\n </div>\n }\n\n <div class=\"sce-request-header__id\">\n <span\n ><sce-bidi-isolate>#{{ requestId() }}</sce-bidi-isolate></span\n >\n <sce-copy-button [value]=\"requestId()\" />\n </div>\n</div>\n\n@if (metaItems().length) {\n <div class=\"sce-request-header__meta\">\n @for (item of metaItems(); track item.label) {\n <div class=\"sce-request-header__meta-item\">\n <div class=\"sce-request-header__meta-label\">\n <sce-icon [name]=\"item.icon\" [size]=\"18\" />\n <span>{{ item.label | translate }}</span>\n </div>\n <span class=\"sce-request-header__meta-value\">\n @if (item.isDate) {\n {{ item.value | localizedDate }}\n } @else {\n {{ item.value }}\n }\n </span>\n </div>\n }\n </div>\n}\n", styles: [":host{display:block}.sce-request-header__main{display:flex;flex-direction:column;gap:var(--space-3)}.sce-request-header__title-row{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3)}.sce-request-header__title{margin:0;font-size:var(--font-size-lg);font-weight:600}.sce-request-header__status{padding:var(--space-1) var(--space-3);border-radius:var(--radius-full);font-size:var(--font-size-xs);font-weight:500}.sce-request-header__status--warning{background:var(--color-status-warning-bg);color:var(--color-status-warning-text)}.sce-request-header__status--success{background:var(--color-status-success-bg);color:var(--color-status-success-text)}.sce-request-header__status--danger{background:var(--color-status-danger-bg);color:var(--color-status-danger-text)}.sce-request-header__status--neutral{background:var(--color-surface-secondary);color:var(--color-text-secondary)}.sce-request-header__id{display:inline-flex;align-items:center;gap:var(--space-2);font-size:var(--font-size-sm);color:var(--color-text-secondary)}.sce-request-header__meta{display:grid;grid-template-columns:repeat(auto-fit,minmax(12rem,1fr));gap:var(--space-4);margin-block-start:var(--space-4);padding-block-start:var(--space-4);border-block-start:1px solid var(--color-border-subtle)}.sce-request-header__meta-label{display:flex;align-items:center;gap:var(--space-2);font-size:var(--font-size-sm);color:var(--color-text-secondary)}.sce-request-header__meta-value{display:block;margin-block-start:var(--space-1);font-size:var(--font-size-md);color:var(--color-text-primary)}\n"] }]
|
|
10785
10957
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], requestId: [{ type: i0.Input, args: [{ isSignal: true, alias: "requestId", required: true }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: true }] }], metaItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "metaItems", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], dateLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateLabelKey", required: false }] }] } });
|
|
10786
10958
|
|
|
10959
|
+
/** Card wrapper around `sce-request-header` that adds a body slot for request details; takes the same `title`, `requestId`, `status`, and `metaItems` inputs. */
|
|
10787
10960
|
class SceRequestDetailsCardComponent {
|
|
10788
10961
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
10789
10962
|
requestId = input.required(...(ngDevMode ? [{ debugName: "requestId" }] : /* istanbul ignore next */ []));
|
|
@@ -10806,6 +10979,7 @@ function resolveAttachmentType(attachment) {
|
|
|
10806
10979
|
const ext = attachment.name.split('.').pop()?.toLowerCase() ?? '';
|
|
10807
10980
|
return ext === 'pdf' || ext === 'doc' || ext === 'docx' ? 'pdf' : 'image';
|
|
10808
10981
|
}
|
|
10982
|
+
/** List of file attachments with a per-row pdf/image icon inferred from the file extension and an empty state; in `download` mode it emits `downloadFile`, in `show` mode it opens the file in a new tab itself. */
|
|
10809
10983
|
class SceAttachmentsListComponent {
|
|
10810
10984
|
attachments = input([], ...(ngDevMode ? [{ debugName: "attachments" }] : /* istanbul ignore next */ []));
|
|
10811
10985
|
titleKey = input('common.attachments', ...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
|
|
@@ -10833,6 +11007,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10833
11007
|
args: [{ selector: 'sce-attachments-list', standalone: true, imports: [TranslatePipe, SceIcon, SceEmptyStateComponent, ImgFallbackDirective], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-attachments-list' }, template: "@if (showSectionTitle()) {\n <h3 class=\"sce-attachments-list__title\">{{ titleKey() | translate }}</h3>\n}\n\n@if (attachments().length > 0) {\n <ul class=\"sce-attachments-list__grid\" role=\"list\">\n @for (row of attachmentRows(); track row.file.id) {\n <li class=\"sce-attachments-list__item\">\n @if (row.type === 'image') {\n <img class=\"sce-attachments-list__preview\" [src]=\"row.file.url\" [alt]=\"row.file.name\" sceImgFallback />\n } @else {\n <span class=\"sce-attachments-list__pdf-icon\" aria-hidden=\"true\">\n <sce-icon name=\"stack\" [size]=\"28\" />\n </span>\n }\n <span class=\"sce-attachments-list__name\">{{ row.file.name }}</span>\n @if (row.file.sizeLabel) {\n <span class=\"sce-attachments-list__size\">{{ row.file.sizeLabel }}</span>\n }\n <div class=\"sce-attachments-list__actions\">\n <button\n type=\"button\"\n class=\"sce-attachments-list__action\"\n [attr.aria-label]=\"(mode() === 'show' ? 'COMMON.VIEW' : 'COMMON.DOWNLOAD') | translate\"\n (click)=\"onAction(row.file)\"\n >\n <sce-icon [name]=\"mode() === 'show' ? 'eye' : 'download2'\" [size]=\"18\" />\n </button>\n @if (row.file.deletable) {\n <button\n type=\"button\"\n class=\"sce-attachments-list__action sce-attachments-list__action--delete\"\n (click)=\"deleteFile.emit(row.file.id)\"\n [attr.aria-label]=\"'common.delete' | translate\"\n >\n <sce-icon name=\"trash\" [size]=\"18\" />\n </button>\n }\n </div>\n </li>\n }\n </ul>\n} @else {\n <sce-empty-state titleKey=\"common.noAttachments\" icon=\"file-o\" [compact]=\"true\" />\n}\n", styles: [":host{display:block}.sce-attachments-list__title{margin:0 0 var(--space-4);font-size:var(--font-size-md);font-weight:600}.sce-attachments-list__grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(14rem,1fr));gap:var(--space-3);margin:0;padding:0;list-style:none}.sce-attachments-list__item{display:flex;flex-direction:column;gap:var(--space-2);padding:var(--space-3);border:1px solid var(--color-border-subtle);border-radius:var(--radius-lg)}.sce-attachments-list__preview{inline-size:100%;block-size:var(--space-20);object-fit:cover;border-radius:var(--radius-md)}.sce-attachments-list__pdf-icon{display:flex;align-items:center;justify-content:center;block-size:var(--space-20);background:var(--color-surface-secondary);border-radius:var(--radius-md)}.sce-attachments-list__name{font-size:var(--font-size-sm);overflow-wrap:anywhere}.sce-attachments-list__size{font-size:var(--font-size-xs);color:var(--color-text-secondary)}.sce-attachments-list__actions{display:flex;gap:var(--space-2)}.sce-attachments-list__action{align-self:flex-end;border:0;background:transparent;cursor:pointer;color:var(--color-brand-primary)}.sce-attachments-list__action--delete{color:var(--color-status-danger-text, var(--color-danger-default))}\n"] }]
|
|
10834
11008
|
}], propDecorators: { attachments: [{ type: i0.Input, args: [{ isSignal: true, alias: "attachments", required: false }] }], titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: false }] }], showSectionTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSectionTitle", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], downloadFile: [{ type: i0.Output, args: ["downloadFile"] }], deleteFile: [{ type: i0.Output, args: ["deleteFile"] }] } });
|
|
10835
11009
|
|
|
11010
|
+
/** Profile banner showing an avatar (`avatarUrl`, falling back to a person icon), `name`, and `role`. */
|
|
10836
11011
|
class SceProfileHeroComponent {
|
|
10837
11012
|
name = input('', ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
10838
11013
|
role = input('', ...(ngDevMode ? [{ debugName: "role" }] : /* istanbul ignore next */ []));
|
|
@@ -10845,6 +11020,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10845
11020
|
args: [{ selector: 'sce-profile-hero', standalone: true, imports: [SceIcon], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-profile-hero' }, template: "<div class=\"sce-profile-hero__center\">\n <div class=\"sce-profile-hero__avatar-ring\">\n <div class=\"sce-profile-hero__avatar\" [style.background-image]=\"avatarUrl() ? 'url(' + avatarUrl() + ')' : null\">\n @if (!avatarUrl()) {\n <sce-icon name=\"user\" [size]=\"40\" />\n }\n </div>\n </div>\n @if (name()) {\n <span class=\"sce-profile-hero__name\">{{ name() }}</span>\n }\n @if (role()) {\n <span class=\"sce-profile-hero__role\">{{ role() }}</span>\n }\n</div>\n", styles: [":host{display:block}.sce-profile-hero__center{display:flex;flex-direction:column;align-items:center;gap:var(--space-3);text-align:center}.sce-profile-hero__avatar-ring{padding:var(--space-1);border-radius:var(--radius-full);background:var(--color-border-subtle)}.sce-profile-hero__avatar{display:flex;align-items:center;justify-content:center;inline-size:var(--space-20);block-size:var(--space-20);border-radius:var(--radius-full);background-color:var(--color-surface-secondary);background-size:cover;background-position:center;overflow:hidden}.sce-profile-hero__name{font-size:var(--font-size-lg);font-weight:600;color:var(--color-text-primary)}.sce-profile-hero__role{font-size:var(--font-size-sm);color:var(--color-text-secondary)}\n"] }]
|
|
10846
11021
|
}], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], role: [{ type: i0.Input, args: [{ isSignal: true, alias: "role", required: false }] }], avatarUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarUrl", required: false }] }] } });
|
|
10847
11022
|
|
|
11023
|
+
/** Titled list of downloadable/linked resources from `items`; `titleKey` defaults to the knowledge-centre resources heading. */
|
|
10848
11024
|
class SceResourcesListComponent {
|
|
10849
11025
|
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
10850
11026
|
titleKey = input('knowledgeCenter.resources', ...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
|
|
@@ -10856,6 +11032,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10856
11032
|
args: [{ selector: 'sce-resources-list', standalone: true, imports: [TranslatePipe, SceIcon], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-resources-list' }, template: "<h4 class=\"sce-resources-list__title\">{{ titleKey() | translate }}</h4>\n<ul class=\"sce-resources-list__list\">\n @for (item of items(); track item.url) {\n <li>\n <a [href]=\"item.url\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"sce-resources-list__link\">\n <sce-icon [name]=\"item.icon || 'pdf'\" [size]=\"20\" />\n <span class=\"sce-resources-list__label\">\n {{ item.labelKey ? (item.labelKey | translate) : (item.label ?? '') }}\n </span>\n <sce-icon name=\"download-small\" [size]=\"20\" />\n </a>\n </li>\n }\n</ul>\n", styles: [":host{display:block}.sce-resources-list__title{margin:0 0 var(--space-4);font-size:var(--font-size-md);font-weight:600}.sce-resources-list__list{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:var(--space-2)}.sce-resources-list__link{display:flex;align-items:center;gap:var(--space-3);padding:var(--space-3);border:1px solid var(--color-border-subtle);border-radius:var(--radius-lg);color:var(--color-text-primary);text-decoration:none}.sce-resources-list__label{flex:1;min-width:0}\n"] }]
|
|
10857
11033
|
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: false }] }] } });
|
|
10858
11034
|
|
|
11035
|
+
/** "Was this helpful?" yes/no prompt (all labels are overridable i18n keys) that emits `feedback` once and then locks itself into a thank-you state. */
|
|
10859
11036
|
class SceFeedbackSectionComponent {
|
|
10860
11037
|
questionKey = input('knowledge.helpful', ...(ngDevMode ? [{ debugName: "questionKey" }] : /* istanbul ignore next */ []));
|
|
10861
11038
|
yesKey = input('common.YES', ...(ngDevMode ? [{ debugName: "yesKey" }] : /* istanbul ignore next */ []));
|
|
@@ -10887,6 +11064,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10887
11064
|
args: [{ selector: 'sce-feedback-section', standalone: true, imports: [TranslatePipe, SceIcon], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-feedback-section' }, template: "<div class=\"sce-feedback-section__panel\" role=\"group\" [attr.aria-label]=\"questionKey() | translate\">\n @if (!isComplete()) {\n <p class=\"sce-feedback-section__question\" id=\"sce-feedback-question\">{{ questionKey() | translate }}</p>\n <div class=\"sce-feedback-section__actions\" role=\"group\" aria-labelledby=\"sce-feedback-question\">\n <button type=\"button\" class=\"sce-feedback-section__btn sce-feedback-section__btn--yes\" [disabled]=\"isComplete()\" (click)=\"onYes()\">\n <sce-icon name=\"checkmark-badge\" [size]=\"16\" />\n {{ yesKey() | translate }}\n </button>\n <button type=\"button\" class=\"sce-feedback-section__btn sce-feedback-section__btn--no\" [disabled]=\"isComplete()\" (click)=\"onNo()\">\n <sce-icon name=\"x-badge\" [size]=\"16\" />\n {{ noKey() | translate }}\n </button>\n </div>\n } @else {\n <div class=\"sce-feedback-section__thanks-wrap\" role=\"status\" aria-live=\"polite\">\n <sce-icon class=\"sce-feedback-section__thanks-icon\" name=\"success-icon\" [size]=\"20\" />\n <p class=\"sce-feedback-section__thanks\">{{ thanksKey() | translate }}</p>\n </div>\n }\n</div>\n", styles: [":host{display:block}.sce-feedback-section__panel{padding:var(--space-24);border:1px solid var(--color-border-subtle);border-radius:var(--radius-xl);background:linear-gradient(180deg,var(--color-surface-primary) 0%,var(--color-surface-secondary) 100%);box-shadow:var(--shadow-sm, 0 1px 2px rgba(2, 6, 23, .06))}.sce-feedback-section__question{margin:0 0 var(--space-5);font-family:var(--font-family-arabic-primary);font-size:var(--font-size-lg);font-weight:600;letter-spacing:-.01em;color:var(--color-text-primary)}.sce-feedback-section__actions{display:flex;flex-wrap:wrap;gap:var(--space-3)}.sce-feedback-section__btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-2);min-inline-size:6.5rem;padding:var(--space-3) var(--space-5);border:1px solid var(--color-border-default);border-radius:var(--radius-lg);background:var(--color-surface-primary);color:var(--color-text-primary);font:inherit;font-size:var(--font-size-sm);font-weight:600;cursor:pointer;transition:background-color .15s ease,border-color .15s ease,color .15s ease,transform .15s ease,box-shadow .15s ease}.sce-feedback-section__btn:hover:not(:disabled){transform:translateY(calc(var(--space-1) * -.25));box-shadow:var(--shadow-sm, 0 2px 8px rgba(2, 6, 23, .08))}.sce-feedback-section__btn:focus-visible{outline:2px solid var(--color-brand-primary);outline-offset:2px}.sce-feedback-section__btn--yes:hover:not(:disabled){border-color:var(--color-status-success-text, var(--color-brand-primary));background:var(--color-status-success-bg, var(--app-surface-hover));color:var(--color-status-success-text, var(--color-text-primary))}.sce-feedback-section__btn--no:hover:not(:disabled){border-color:var(--color-status-danger-text, var(--color-border-default));background:var(--color-status-danger-bg, var(--app-surface-hover));color:var(--color-status-danger-text, var(--color-text-primary))}.sce-feedback-section__btn:disabled{opacity:.55;cursor:not-allowed;transform:none}.sce-feedback-section__thanks-wrap{display:flex;align-items:center;gap:var(--space-3)}.sce-feedback-section__thanks-icon{flex-shrink:0;color:var(--color-status-success-text, var(--color-brand-primary))}.sce-feedback-section__thanks{margin:0;font-size:var(--font-size-md);font-weight:600;color:var(--color-status-success-text, var(--color-brand-primary))}@media(prefers-reduced-motion:reduce){.sce-feedback-section__btn:hover:not(:disabled){transform:none}}\n"] }]
|
|
10888
11065
|
}], propDecorators: { questionKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "questionKey", required: false }] }], yesKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "yesKey", required: false }] }], noKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "noKey", required: false }] }], thanksKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "thanksKey", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], feedback: [{ type: i0.Output, args: ["feedback"] }] } });
|
|
10889
11066
|
|
|
11067
|
+
/** Renders a titled grid of related-content cards from `items`, each optionally linking to its own `route`. */
|
|
10890
11068
|
class SceRelatedCardsListComponent {
|
|
10891
11069
|
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
10892
11070
|
titleKey = input('', ...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
|
|
@@ -10906,6 +11084,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10906
11084
|
args: [{ selector: 'sce-related-cards-list', standalone: true, imports: [TranslatePipe, RouterLink], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-related-cards-list' }, template: "@if (titleKey()) {\n <h3 class=\"sce-related-cards-list__title\">{{ titleKey() | translate }}</h3>\n}\n\n<div class=\"sce-related-cards-list__grid\">\n <!-- track $index: SceRelatedCardItem has no required field; list is a static per-page config -->\n @for (item of itemViews(); track $index) {\n @if (item.resolvedRoute; as route) {\n <a class=\"sce-related-cards-list__card\" [routerLink]=\"route\">\n @if (item.thumbnailSrc) {\n <img class=\"sce-related-cards-list__thumb\" [src]=\"item.thumbnailSrc\" alt=\"\" loading=\"lazy\" />\n }\n <h4 class=\"sce-related-cards-list__card-title\">\n {{ item.titleKey ? (item.titleKey | translate) : (item.title ?? '') }}\n </h4>\n @if (item.descriptionKey || item.description) {\n <p class=\"sce-related-cards-list__card-desc\">\n {{ item.descriptionKey ? (item.descriptionKey | translate) : (item.description ?? '') }}\n </p>\n }\n </a>\n } @else {\n <article class=\"sce-related-cards-list__card sce-related-cards-list__card--static\">\n @if (item.thumbnailSrc) {\n <img class=\"sce-related-cards-list__thumb\" [src]=\"item.thumbnailSrc\" alt=\"\" loading=\"lazy\" />\n }\n <h4 class=\"sce-related-cards-list__card-title\">\n {{ item.titleKey ? (item.titleKey | translate) : (item.title ?? '') }}\n </h4>\n @if (item.descriptionKey || item.description) {\n <p class=\"sce-related-cards-list__card-desc\">\n {{ item.descriptionKey ? (item.descriptionKey | translate) : (item.description ?? '') }}\n </p>\n }\n </article>\n }\n }\n</div>\n", styles: [":host{display:block}.sce-related-cards-list__title{margin:0 0 var(--space-4);font-size:var(--font-size-md);font-weight:600}.sce-related-cards-list__grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(14rem,1fr));gap:var(--space-4)}.sce-related-cards-list__card{display:flex;flex-direction:column;gap:var(--space-2);padding:var(--space-4);border:1px solid var(--color-border-subtle);border-radius:var(--radius-lg);background:var(--color-surface-primary);color:inherit;text-decoration:none}.sce-related-cards-list__thumb{inline-size:100%;block-size:var(--space-20);object-fit:cover;border-radius:var(--radius-lg)}.sce-related-cards-list__card-title{margin:0;font-size:var(--font-size-sm);font-weight:600}.sce-related-cards-list__card-desc{margin:0;font-size:var(--font-size-xs);color:var(--color-text-secondary)}\n"] }]
|
|
10907
11085
|
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: false }] }] } });
|
|
10908
11086
|
|
|
11087
|
+
/** Loading placeholder for the office-detail page, rendering the hero header plus a skeleton body matching the currently active tab. */
|
|
10909
11088
|
class SceOfficeDetailLoadingStateComponent {
|
|
10910
11089
|
activeTab = input('overview', ...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
|
|
10911
11090
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SceOfficeDetailLoadingStateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -10916,6 +11095,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10916
11095
|
args: [{ selector: 'sce-office-detail-loading-state', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [SceLandingHeroHeaderComponent], host: { class: 'sce-office-detail-loading-state' }, template: "<sce-landing-hero-header [breadcrumbs]=\"[]\" title=\"\" aria-busy=\"true\">\n <div class=\"heroBody\">\n <div class=\"heroTopRow\">\n <div class=\"officeInfoColumn\">\n <div class=\"titleBlock\">\n <div class=\"shimmerBlock heroTitleSkeleton\"></div>\n <div class=\"shimmerBlock heroLocationSkeleton\"></div>\n </div>\n <div class=\"ratingRow\">\n <div class=\"reviewerSkeletonGroup\">\n @for (i of [0, 1, 2]; track i) {\n <span class=\"shimmerBlock reviewerSkeleton\"></span>\n }\n </div>\n <div class=\"ratingSkeletonGroup\">\n <div class=\"shimmerBlock starsSkeleton\"></div>\n <div class=\"shimmerBlock ratingLineSkeleton\"></div>\n </div>\n </div>\n </div>\n <div class=\"actionsRow\">\n <div class=\"shimmerBlock primaryActionSkeleton\"></div>\n <div class=\"shimmerBlock iconActionSkeleton\"></div>\n <div class=\"shimmerBlock iconActionSkeleton\"></div>\n </div>\n </div>\n </div>\n</sce-landing-hero-header>\n\n<main aria-busy=\"true\">\n <div class=\"tabsSurface\">\n <div class=\"tabsViewport\">\n <div class=\"relative w-[64px] sm:w-[130px]\">\n <div class=\"logoBadge logoBadgeSkeletonWrap\">\n <div class=\"shimmerBlock logoBadgeSkeleton\"></div>\n </div>\n </div>\n <div class=\"tabsRow\">\n <span class=\"shimmerBlock tabSkeleton\"></span>\n <span class=\"shimmerBlock tabSkeleton\"></span>\n <span class=\"shimmerBlock tabSkeleton\"></span>\n </div>\n </div>\n </div>\n\n <section class=\"contentSection\">\n @switch (activeTab()) {\n @case ('overview') {\n <div class=\"contentSkeletonLayout\">\n <div class=\"contentSkeletonColumn\">\n <div class=\"panelSkeleton shimmerPanel\">\n <div class=\"shimmerBlock panelTitleSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n </div>\n <div class=\"panelSkeleton shimmerPanel\">\n <div class=\"shimmerBlock panelTitleSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n <div class=\"metricSkeletonRow\">\n <div class=\"shimmerBlock metricSkeleton\"></div>\n <div class=\"shimmerBlock metricSkeleton\"></div>\n </div>\n </div>\n </div>\n <div class=\"panelSkeleton shimmerPanel mapPanelSkeleton\">\n <div class=\"shimmerBlock panelTitleSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n <div class=\"shimmerBlock mapSkeleton\"></div>\n </div>\n </div>\n }\n @case ('projects') {\n <div class=\"contentSkeletonLayout projectsSkeletonStack\">\n @for (item of [1, 2]; track item) {\n <div class=\"panelSkeleton shimmerPanel projectPanelSkeleton\">\n <div class=\"shimmerBlock panelTitleSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n <div class=\"shimmerBlock projectHeroSkeleton\"></div>\n <div class=\"projectThumbsSkeletonRow\">\n <div class=\"shimmerBlock projectThumbSkeleton\"></div>\n <div class=\"shimmerBlock projectThumbSkeleton\"></div>\n <div class=\"shimmerBlock projectThumbSkeleton\"></div>\n </div>\n </div>\n }\n </div>\n }\n @case ('reviews') {\n <div class=\"contentSkeletonLayout\">\n <div class=\"contentSkeletonColumn\">\n <div class=\"panelSkeleton shimmerPanel\">\n <div class=\"shimmerBlock panelTitleSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n </div>\n <div class=\"panelSkeleton shimmerPanel\">\n <div class=\"shimmerBlock panelTitleSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n </div>\n </div>\n </div>\n }\n }\n </section>\n</main>\n", styles: ["@charset \"UTF-8\";sce-office-detail-loading-state{display:block}.heroTitleSkeleton{width:min(28rem,72vi);height:var(--space-44);border-radius:var(--space-12)}.heroLocationSkeleton{width:10rem;height:var(--space-20)}.reviewerSkeletonGroup{display:flex;gap:.35rem}.reviewerSkeleton{width:var(--space-32);height:var(--space-32);border-radius:var(--radius-full)}.ratingSkeletonGroup{display:grid;gap:var(--space-8)}.starsSkeleton{width:6.5rem;height:var(--space-16)}.ratingLineSkeleton{width:9rem;height:.9rem}.primaryActionSkeleton{width:8.5rem;height:3.125rem;border-radius:var(--radius-md)}.iconActionSkeleton{width:var(--space-44);height:var(--space-44);border-radius:var(--radius-md)}.logoBadgeSkeletonWrap{display:flex;align-items:center;justify-content:center;overflow:hidden}.logoBadgeSkeleton{width:72%;height:72%;border-radius:var(--radius-full)}.tabSkeleton{width:var(--space-88, var(--size-88));height:var(--space-20);border-radius:.4rem}\n", "@charset \"UTF-8\";.shimmerBlock,.shimmerPanel{position:relative;overflow:hidden;background:#ffffff2e;border-radius:var(--space-8)}.shimmerPanel{background:var(--public-surface, var(--background-bg-primary));border-radius:var(--space-16);padding:var(--space-16) var(--space-20)}.shimmerBlock:after,.shimmerPanel:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.42) 45%,transparent 100%);animation:office-detail-shimmer 1.35s ease-in-out infinite}.shimmerPanel:after{background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.65) 45%,transparent 100%)}@keyframes office-detail-shimmer{to{transform:translate(100%)}}.contentSkeletonLayout{display:flex;width:100%;max-width:var(--size-1220);flex-direction:column;gap:var(--space-24);padding-inline:var(--space-16)}.contentSkeletonColumn{display:flex;flex:1;flex-direction:column;gap:var(--space-24)}.panelSkeleton{display:grid;gap:var(--space-12)}.panelTitleSkeleton{width:8rem;height:1.35rem}.panelLineSkeleton{width:100%;height:var(--space-16)}.panelLineSkeleton:last-child{width:82%}.metricSkeletonRow{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-16);margin-block-start:var(--space-8)}.metricSkeleton{height:var(--space-88, var(--size-88));border-radius:var(--space-16)}.mapPanelSkeleton{min-height:var(--size-280)}.mapSkeleton{width:100%;height:var(--size-220);border-radius:var(--space-16);margin-block-start:var(--space-8)}.projectsSkeletonStack{flex-direction:column;gap:var(--space-24)}.projectPanelSkeleton{width:100%}.projectHeroSkeleton{width:100%;height:var(--size-220);border-radius:var(--space-16);margin-block-start:var(--space-8)}.projectThumbsSkeletonRow{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-16);margin-block-start:var(--space-16)}.projectThumbSkeleton{width:100%;aspect-ratio:379/213;border-radius:var(--space-16)}@media(min-width:1024px){.contentSkeletonLayout{flex-direction:row;align-items:flex-start;padding-inline:0}.mapPanelSkeleton{width:min(596.5px,42%);flex-shrink:0}}\n"] }]
|
|
10917
11096
|
}], propDecorators: { activeTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTab", required: false }] }] } });
|
|
10918
11097
|
|
|
11098
|
+
/** Not-found state for the office-detail page, rendering the hero header above a result state whose preset back action is suppressed in favour of the page's own links. */
|
|
10919
11099
|
class SceOfficeDetailNotFoundComponent {
|
|
10920
11100
|
breadcrumbs = input([], ...(ngDevMode ? [{ debugName: "breadcrumbs" }] : /* istanbul ignore next */ []));
|
|
10921
11101
|
/** The page owns its own navigation links, so the preset's `back` button is suppressed. */
|
|
@@ -10928,6 +11108,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10928
11108
|
args: [{ selector: 'sce-office-detail-not-found', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [SceLandingHeroHeaderComponent, SceResultStateComponent, RouterLink, TranslatePipe], host: { class: 'sce-office-detail-not-found' }, template: "<sce-landing-hero-header [breadcrumbs]=\"breadcrumbs()\" [title]=\"'offices.notFound' | translate\" />\n<main class=\"sce-office-detail-not-found__main\">\n <sce-result-state status=\"not-found\" titleKey=\"offices.notFound\" subtitleKey=\"engineeringOffices.empty.subtitle\" [actions]=\"noActions\">\n <div class=\"sce-office-detail-not-found__actions\">\n <a class=\"sce-office-detail-not-found__action sce-office-detail-not-found__action--primary\" routerLink=\"/engineering-offices\">\n {{ 'offices.browseOffices' | translate }}\n </a>\n <a class=\"sce-office-detail-not-found__action sce-office-detail-not-found__action--secondary\" routerLink=\"/\">\n {{ 'STATUS_PAGES.BACK_HOME' | translate }}\n </a>\n </div>\n </sce-result-state>\n</main>\n", styles: ["@charset \"UTF-8\";:host.sce-office-detail-not-found{display:block}.sce-office-detail-not-found__main{display:flex;flex-direction:column;align-items:center;justify-content:center;padding-block:var(--space-32);padding-inline:var(--space-24);text-align:center}.sce-office-detail-not-found__actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:var(--space-12)}.sce-office-detail-not-found__action{display:inline-flex;align-items:center;justify-content:center;min-height:var(--space-40);padding-inline:var(--space-16);border:var(--border-width-hairline) solid transparent;border-radius:var(--radius-brand-sm);font-weight:var(--font-weight-semibold);text-decoration:none;transition:background-color var(--transition-base),box-shadow var(--transition-base)}.sce-office-detail-not-found__action--primary{background-color:var(--color-brand-primary-800);color:var(--color-white);box-shadow:var(--shadow-brand-button)}.sce-office-detail-not-found__action--primary:hover{background-color:var(--color-brand-primary-700);box-shadow:var(--shadow-brand-button-hover)}.sce-office-detail-not-found__action--secondary{border-color:var(--color-brand-primary-200);color:var(--color-brand-primary-800)}.sce-office-detail-not-found__action--secondary:hover{border-color:var(--color-brand-primary-800);background-color:var(--color-neutral-100)}@media(prefers-reduced-motion:reduce){.sce-office-detail-not-found__action{transition:none}}\n"] }]
|
|
10929
11109
|
}], propDecorators: { breadcrumbs: [{ type: i0.Input, args: [{ isSignal: true, alias: "breadcrumbs", required: false }] }] } });
|
|
10930
11110
|
|
|
11111
|
+
/** Hero content of the public office-detail page: office name with verification badge, location, star-rating summary, reviewer avatars and an optional request-contract button. */
|
|
10931
11112
|
class SceOfficeDetailHeroBodyComponent {
|
|
10932
11113
|
officeName = input.required(...(ngDevMode ? [{ debugName: "officeName" }] : /* istanbul ignore next */ []));
|
|
10933
11114
|
verificationStatus = input(null, ...(ngDevMode ? [{ debugName: "verificationStatus" }] : /* istanbul ignore next */ []));
|
|
@@ -10946,6 +11127,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10946
11127
|
args: [{ selector: 'sce-office-detail-hero-body', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [SceEngineeringOfficeVerificationBadgeComponent, TranslatePipe], host: { class: 'sce-office-detail-hero-body' }, template: "<div class=\"heroBody\">\n <div class=\"heroTopRow\">\n <div class=\"officeInfoColumn\">\n <div class=\"titleBlock\">\n <div class=\"titleRow\">\n <h1 class=\"officeTitle\">{{ officeName() }}</h1>\n <sce-engineering-office-verification-badge [status]=\"verificationStatus()\" [size]=\"24\" />\n </div>\n <div class=\"locationRow\">\n <img src=\"/assets/icons/location-05-alt.svg\" width=\"20\" height=\"20\" class=\"locationIcon\" alt=\"\" aria-hidden=\"true\" />\n <span class=\"locationText\">{{ locationText() }}</span>\n </div>\n </div>\n\n <div class=\"ratingRow\">\n <div class=\"ratingInfo\">\n <div class=\"starRow\">\n @for (star of [1, 2, 3, 4, 5]; track star) {\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n [class]=\"star <= filledStars() ? 'starIconActive' : 'starIconInactive'\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z\" />\n </svg>\n }\n </div>\n <span class=\"ratingSummary\">{{ ratingValue().toFixed(1) }} \u2014 {{ ratingSummary() }}</span>\n @if (reviewerAvatars().length > 0) {\n <div class=\"reviewerList\" aria-hidden=\"true\">\n @for (avatar of reviewerAvatars(); track avatar) {\n <img [src]=\"avatar\" alt=\"\" class=\"reviewerAvatar\" width=\"32\" height=\"32\" />\n }\n </div>\n }\n </div>\n </div>\n\n @if (canRequestContract()) {\n <div class=\"actionsRow\">\n <button type=\"button\" class=\"primaryAction\" (click)=\"requestContract.emit()\">\n {{ 'engineeringOffices.detail.requestContract' | translate }}\n </button>\n </div>\n }\n </div>\n </div>\n</div>\n", styles: [":host{display:block}\n"] }]
|
|
10947
11128
|
}], propDecorators: { officeName: [{ type: i0.Input, args: [{ isSignal: true, alias: "officeName", required: true }] }], verificationStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "verificationStatus", required: false }] }], locationText: [{ type: i0.Input, args: [{ isSignal: true, alias: "locationText", required: false }] }], filledStars: [{ type: i0.Input, args: [{ isSignal: true, alias: "filledStars", required: false }] }], ratingValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "ratingValue", required: false }] }], ratingSummary: [{ type: i0.Input, args: [{ isSignal: true, alias: "ratingSummary", required: false }] }], reviewerAvatars: [{ type: i0.Input, args: [{ isSignal: true, alias: "reviewerAvatars", required: false }] }], canRequestContract: [{ type: i0.Input, args: [{ isSignal: true, alias: "canRequestContract", required: false }] }], requestContract: [{ type: i0.Output, args: ["requestContract"] }] } });
|
|
10948
11129
|
|
|
11130
|
+
/** Tab bar of the office-detail page, showing the office's brand logo and name beside the tab buttons and emitting `tabChange` on selection. */
|
|
10949
11131
|
class SceOfficeDetailTabsBarComponent {
|
|
10950
11132
|
tabItems = input.required(...(ngDevMode ? [{ debugName: "tabItems" }] : /* istanbul ignore next */ []));
|
|
10951
11133
|
activeTab = input.required(...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
|
|
@@ -10960,6 +11142,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10960
11142
|
args: [{ selector: 'sce-office-detail-tabs-bar', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [SceOfficeBrandLogoComponent], host: { class: 'sce-office-detail-tabs-bar' }, template: "<div class=\"tabsSurface\">\n <div class=\"tabsViewport\">\n <div class=\"relative w-[64px] sm:w-[130px]\">\n <div class=\"logoBadge\">\n <div class=\"logoBadgeInner\">\n <sce-office-brand-logo\n [src]=\"logoObjectUrl()\"\n [alt]=\"officeName()\"\n className=\"logoBadgePhoto\"\n iconClassName=\"logoBadgeIcon\"\n size=\"7rem\"\n />\n </div>\n </div>\n </div>\n <div class=\"tabsRow\">\n @for (tab of tabItems(); track tab.key) {\n <button\n type=\"button\"\n class=\"tabLink\"\n [class.tabLinkActive]=\"activeTab() === tab.key\"\n [class.tabLinkInactive]=\"activeTab() !== tab.key\"\n (click)=\"tabChange.emit(tab.key)\"\n >\n {{ tab.label }}\n </button>\n }\n </div>\n </div>\n</div>\n", styles: [":host{display:block}\n"] }]
|
|
10961
11143
|
}], propDecorators: { tabItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabItems", required: true }] }], activeTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTab", required: true }] }], logoObjectUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "logoObjectUrl", required: false }] }], officeName: [{ type: i0.Input, args: [{ isSignal: true, alias: "officeName", required: false }] }], tabChange: [{ type: i0.Output, args: ["tabChange"] }] } });
|
|
10962
11144
|
|
|
11145
|
+
/** Overview tab of the office-detail page, showing the office bio, an OSM map of its location and rows of experience and compatibility metric cards. */
|
|
10963
11146
|
class SceOfficeDetailOverviewPanelComponent {
|
|
10964
11147
|
officeBio = input('', ...(ngDevMode ? [{ debugName: "officeBio" }] : /* istanbul ignore next */ []));
|
|
10965
11148
|
locationText = input('', ...(ngDevMode ? [{ debugName: "locationText" }] : /* istanbul ignore next */ []));
|
|
@@ -10974,6 +11157,7 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "21.2.17", n
|
|
|
10974
11157
|
args: [{ selector: 'sce-office-detail-overview-panel', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [SceOfficeMetricCardsRowComponent, SceOsmOfficesMapComponent, TranslatePipe], host: { class: 'sce-office-detail-overview-panel' }, template: "<div class=\"overviewPanel\">\n <div class=\"overviewMain\">\n <div class=\"overviewCard\">\n <h2 class=\"overviewCardTitle\">{{ 'engineeringOffices.overview.about' | translate }}</h2>\n <p class=\"overviewCardBody\">\n @if (officeBio()) {\n {{ officeBio() }}\n } @else {\n {{ 'engineeringOffices.overview.defaultBio' | translate }}\n }\n </p>\n </div>\n\n <div class=\"overviewCard\">\n <div class=\"overviewCardInner\">\n <h2 class=\"overviewCardTitle\">{{ 'engineeringOffices.overview.experience' | translate }}</h2>\n <p class=\"overviewCardBody\">{{ officeBio() }}</p>\n </div>\n <sce-office-metric-cards-row [items]=\"experienceMetricItems()\" variant=\"accent\" [columns]=\"3\" />\n </div>\n </div>\n\n <aside class=\"overviewSidebar\">\n <div class=\"overviewCard\">\n <h2 class=\"overviewCardTitle\">{{ 'engineeringOffices.overview.location' | translate }}</h2>\n <span class=\"overviewLocationRow\">\n <img src=\"/assets/icons/location-05-alt.svg\" width=\"20\" height=\"20\" class=\"overviewLocationIcon\" alt=\"\" aria-hidden=\"true\" />\n <p class=\"overviewCardBody\">{{ locationText() }}</p>\n </span>\n @defer (on viewport) {\n <sce-osm-offices-map [offices]=\"mapPoints()\" [showTooltip]=\"false\" class=\"detailSidebarMap\" />\n } @placeholder {\n <div class=\"detailSidebarMap\" aria-hidden=\"true\"></div>\n }\n </div>\n </aside>\n</div>\n", styles: [":host{display:block}\n"] }]
|
|
10975
11158
|
}], ctorParameters: null, propDecorators: { officeBio: [{ type: i0.Input, args: [{ isSignal: true, alias: "officeBio", required: false }] }], locationText: [{ type: i0.Input, args: [{ isSignal: true, alias: "locationText", required: false }] }], mapPoints: [{ type: i0.Input, args: [{ isSignal: true, alias: "mapPoints", required: false }] }], experienceMetricItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "experienceMetricItems", required: false }] }], compatibilityMetricItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "compatibilityMetricItems", required: false }] }] } }) });
|
|
10976
11159
|
|
|
11160
|
+
/** Projects tab of the office-detail page, rendering each of the office's projects alongside its image gallery. */
|
|
10977
11161
|
class SceOfficeDetailProjectsPanelComponent {
|
|
10978
11162
|
projects = input([], ...(ngDevMode ? [{ debugName: "projects" }] : /* istanbul ignore next */ []));
|
|
10979
11163
|
projectGalleryImages = input([], ...(ngDevMode ? [{ debugName: "projectGalleryImages" }] : /* istanbul ignore next */ []));
|
|
@@ -10986,6 +11170,7 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "21.2.17", n
|
|
|
10986
11170
|
args: [{ selector: 'sce-office-detail-projects-panel', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [SceOfficeProjectGalleryComponent, TranslatePipe], host: { class: 'sce-office-detail-projects-panel' }, template: "<div class=\"projectsPanel\">\n @if (projects().length === 0) {\n <p class=\"projectsEmpty\">{{ 'engineeringOffices.detail.emptyProjects' | translate }}</p>\n } @else {\n @for (project of projects(); track project.title; let idx = $index) {\n <article class=\"projectCard\">\n <header class=\"projectContent\">\n <h3 class=\"projectTitle\">{{ project.title }}</h3>\n @if (project.description) {\n <p class=\"projectDesc\">{{ project.description }}</p>\n }\n <div class=\"projectBadges\">\n @if (project.status === 'completed') {\n <span class=\"projectBadge projectBadgeCompleted\">\n {{ 'engineeringOffices.detail.projectStatusCompleted' | translate }}\n </span>\n } @else if (project.status === 'inProgress') {\n <span class=\"projectBadge projectBadgeInProgress\">\n {{ 'engineeringOffices.detail.projectStatusInProgress' | translate }}\n </span>\n } @else if (project.status === 'new') {\n <span class=\"projectBadge projectBadgeNew\">\n {{ 'engineeringOffices.detail.projectStatusNew' | translate }}\n </span>\n }\n @if (project.typeLabel) {\n <span class=\"projectBadge projectBadgeCategory\">\n {{ project.typeLabel }}\n </span>\n }\n </div>\n </header>\n @defer (on viewport) {\n <sce-office-project-gallery\n [imageUrls]=\"projectGalleryImages()[idx].urls\"\n [title]=\"project.title\"\n [locale]=\"locale() === 'ar' ? 'ar' : 'en'\"\n />\n } @placeholder {\n <div class=\"projectGalleryPlaceholder\" aria-hidden=\"true\"></div>\n }\n </article>\n }\n }\n</div>\n", styles: [":host{display:block}\n"] }]
|
|
10987
11171
|
}], ctorParameters: null, propDecorators: { projects: [{ type: i0.Input, args: [{ isSignal: true, alias: "projects", required: false }] }], projectGalleryImages: [{ type: i0.Input, args: [{ isSignal: true, alias: "projectGalleryImages", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }] } }) });
|
|
10988
11172
|
|
|
11173
|
+
/** Reviews tab of the office-detail page, showing the overall rating, the per-star rating distribution and the individual reviews. */
|
|
10989
11174
|
class SceOfficeDetailReviewsPanelComponent {
|
|
10990
11175
|
reviews = input([], ...(ngDevMode ? [{ debugName: "reviews" }] : /* istanbul ignore next */ []));
|
|
10991
11176
|
totalReviews = input(0, ...(ngDevMode ? [{ debugName: "totalReviews" }] : /* istanbul ignore next */ []));
|
|
@@ -11050,6 +11235,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11050
11235
|
args: [{ selector: 'sce-form-rich-text', standalone: true, imports: [ReactiveFormsModule, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-form-rich-text' }, template: "<label class=\"sce-form-rich-text__label\" [for]=\"fieldId\">{{ labelTranslateKey() | translate }}</label>\n<textarea\n [id]=\"fieldId\"\n class=\"sce-form-rich-text__area\"\n [formControl]=\"inner\"\n [style.min-height]=\"editorHeight()\"\n (blur)=\"onBlur()\"\n></textarea>\n", styles: [":host{display:block}.sce-form-rich-text__label{display:block;margin-block-end:var(--space-8);font-size:var(--font-size-sm);color:var(--color-text-secondary)}.sce-form-rich-text__area{inline-size:100%;padding:var(--space-12);border:var(--border-width-1) solid var(--color-border-default);border-radius:var(--radius-lg);font:inherit;resize:block}\n"] }]
|
|
11051
11236
|
}], ctorParameters: () => [], propDecorators: { labelTranslateKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelTranslateKey", required: false }] }], editorHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "editorHeight", required: false }] }] } });
|
|
11052
11237
|
|
|
11238
|
+
/** Picks the `<key>Ar`/`<key>En` property of an object matching the active language (falling back to the other language, then to the bare `key`, then to ''); pure, so it does not re-run on a language switch unless the object reference changes. */
|
|
11053
11239
|
class LocalizedValuePipe {
|
|
11054
11240
|
translate = inject(TranslateService);
|
|
11055
11241
|
transform(obj, key, options) {
|
|
@@ -11078,6 +11264,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11078
11264
|
}]
|
|
11079
11265
|
}] });
|
|
11080
11266
|
|
|
11267
|
+
/** Displays a phone number with an optional leading icon and a copy-to-clipboard button (shown by default). */
|
|
11081
11268
|
class ScePhoneNumberComponent {
|
|
11082
11269
|
value = input.required(...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
11083
11270
|
showCopy = input(true, ...(ngDevMode ? [{ debugName: "showCopy" }] : /* istanbul ignore next */ []));
|
|
@@ -11091,6 +11278,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11091
11278
|
args: [{ selector: 'sce-phone-number', standalone: true, imports: [SceCopyButtonComponent, SceIcon], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-phone-number' }, template: "<div class=\"sce-phone-number__row\">\n @if (showIcon()) {\n <sce-icon class=\"sce-phone-number__icon\" name=\"phone\" [size]=\"iconSize()\" />\n }\n @if (showCopy()) {\n <sce-copy-button class=\"sce-phone-number__copy\" [value]=\"value()\" [showValue]=\"true\" />\n } @else {\n <span class=\"sce-phone-number__value\" dir=\"ltr\">{{ value() }}</span>\n }\n</div>\n", styles: [":host{display:block;display:inline-flex;align-items:center;gap:var(--space-8)}.sce-phone-number__value{direction:ltr}\n"] }]
|
|
11092
11279
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], showCopy: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCopy", required: false }] }], showIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "showIcon", required: false }] }], iconSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconSize", required: false }] }] } });
|
|
11093
11280
|
|
|
11281
|
+
/** Title-and-description row with a trailing edit button (shown by default, labelled from the translated "edit" key unless overridden). */
|
|
11094
11282
|
class SceInfoRowComponent {
|
|
11095
11283
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
11096
11284
|
description = input.required(...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
|
|
@@ -11108,6 +11296,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11108
11296
|
args: [{ selector: 'sce-info-row', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-info-row' }, template: "<div class=\"sce-info-row__content\">\n <span class=\"sce-info-row__title\">{{ title() }}</span>\n <span class=\"sce-info-row__description\" [attr.dir]=\"ltr() ? 'ltr' : null\">{{ description() }}</span>\n</div>\n\n@if (showEdit()) {\n <button type=\"button\" class=\"sce-info-row__edit\" (click)=\"editClick.emit()\">\n {{ resolvedEditLabel() }}\n </button>\n}\n", styles: [":host{display:block}\n"] }]
|
|
11109
11297
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: true }] }], editLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "editLabel", required: false }] }], showEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "showEdit", required: false }] }], ltr: [{ type: i0.Input, args: [{ isSignal: true, alias: "ltr", required: false }] }], editClick: [{ type: i0.Output, args: ["editClick"] }] } });
|
|
11110
11298
|
|
|
11299
|
+
/** Compact summary tile pairing an icon with a label, a primary value and an optional secondary value. */
|
|
11111
11300
|
class SceSummaryCardComponent {
|
|
11112
11301
|
icon = input.required(...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
11113
11302
|
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
@@ -11121,6 +11310,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11121
11310
|
args: [{ selector: 'sce-summary-card', standalone: true, imports: [SceIcon], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-summary-card' }, template: "<div class=\"sce-summary-card__icon\" aria-hidden=\"true\">\n <sce-icon [name]=\"icon()\" [size]=\"30\" />\n</div>\n<div class=\"sce-summary-card__info\">\n <span class=\"sce-summary-card__label\">{{ label() }}</span>\n <div class=\"sce-summary-card__value\">\n <span>{{ value() }}</span>\n @if (subValue()) {\n <span class=\"sce-summary-card__sub-value\">{{ subValue() }}</span>\n }\n </div>\n</div>\n", styles: [":host{display:block;display:flex;align-items:center;gap:var(--space-4);padding:var(--space-4);border:1px solid var(--color-neutral-200, var(--color-border-subtle));border-radius:var(--radius-lg, .75rem);background:var(--color-surface, var(--app-surface));box-shadow:var(--shadow-xs, none)}.sce-summary-card__icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;inline-size:var(--space-12);block-size:var(--space-12);border-radius:var(--radius-lg);background:var(--app-surface-hover, var(--color-surface-secondary));color:var(--color-brand-primary)}.sce-summary-card__info{display:flex;flex-direction:column;gap:var(--space-1);min-width:0}.sce-summary-card__label{font-family:var(--font-family-arabic-primary);font-size:var(--details-label-size, var(--font-size-sm));font-weight:var(--details-label-weight, 500);color:var(--details-label-color, var(--color-text-secondary))}.sce-summary-card__value{display:flex;align-items:baseline;flex-wrap:wrap;gap:var(--space-2);font-family:var(--font-family-arabic-primary);font-size:var(--font-size-xl);font-weight:700;line-height:1.2;color:var(--details-value-color, var(--color-text-primary))}.sce-summary-card__sub-value{font-size:var(--font-size-sm);font-weight:500;color:var(--color-text-secondary)}\n"] }]
|
|
11122
11311
|
}], propDecorators: { icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], subValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "subValue", required: false }] }] } });
|
|
11123
11312
|
|
|
11313
|
+
/** Card identifying an entity by logo (or fallback icon), name, subtitle and ID, with a tone-coloured badge label that defaults to the success tone. */
|
|
11124
11314
|
class SceEntityInfoCardComponent {
|
|
11125
11315
|
labelKey = input.required(...(ngDevMode ? [{ debugName: "labelKey" }] : /* istanbul ignore next */ []));
|
|
11126
11316
|
nameKey = input('', ...(ngDevMode ? [{ debugName: "nameKey" }] : /* istanbul ignore next */ []));
|
|
@@ -11147,6 +11337,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11147
11337
|
}, template: "<span class=\"sce-entity-info-card__badge\">{{ labelKey() | translate }}</span>\n\n<div class=\"sce-entity-info-card__main\">\n <div class=\"sce-entity-info-card__logo\">\n @if (logoSrc()) {\n <img class=\"sce-entity-info-card__logo-img\" [src]=\"logoSrc()!\" [alt]=\"logoAlt()\" width=\"64\" height=\"64\" loading=\"lazy\" />\n } @else {\n <sce-icon [name]=\"iconName()\" [size]=\"iconSize()\" />\n }\n </div>\n\n <div class=\"sce-entity-info-card__copy\">\n <h3 class=\"sce-entity-info-card__name\">\n @if (nameText()) {\n {{ nameText() }}\n } @else {\n {{ nameKey() | translate }}\n }\n </h3>\n @if (subtitleText()) {\n <p class=\"sce-entity-info-card__subtitle\">{{ subtitleText() }}</p>\n }\n @if (idLabelKey() && idValue()) {\n <p class=\"sce-entity-info-card__id\">\n <span class=\"sce-entity-info-card__id-label\">{{ idLabelKey() | translate }}</span>\n <span class=\"sce-entity-info-card__id-value\" dir=\"ltr\">{{ idValue() }}</span>\n </p>\n }\n </div>\n</div>\n", styles: [":host{display:block;padding:var(--space-5);border:1px solid var(--color-neutral-200, var(--color-border-subtle));border-radius:var(--radius-lg, .75rem);background:var(--color-surface, var(--app-surface))}.sce-entity-info-card__badge{display:inline-block;margin-block-end:var(--space-4);padding:var(--space-1) var(--space-3);border-radius:var(--radius-full);font-size:var(--font-size-xs);font-weight:600;letter-spacing:.01em;background:var(--color-status-success-bg);color:var(--color-status-success-text)}:host(.sce-entity-info-card--badge-info) .sce-entity-info-card__badge{background:var(--color-status-info-bg, var(--color-surface-secondary));color:var(--color-status-info-text, var(--color-text-primary))}:host(.sce-entity-info-card--badge-warning) .sce-entity-info-card__badge{background:var(--color-status-warning-bg);color:var(--color-status-warning-text)}:host(.sce-entity-info-card--badge-error) .sce-entity-info-card__badge{background:var(--color-status-danger-bg);color:var(--color-status-danger-text)}:host(.sce-entity-info-card--badge-neutral) .sce-entity-info-card__badge{background:var(--color-neutral-100);color:var(--color-neutral-700)}.sce-entity-info-card__main{display:flex;align-items:center;gap:var(--space-4)}.sce-entity-info-card__logo{display:flex;align-items:center;justify-content:center;flex-shrink:0;inline-size:var(--space-16);block-size:var(--space-16);border:1px solid var(--color-neutral-200, var(--color-border-subtle));border-radius:var(--radius-lg);background:var(--app-surface-hover, var(--color-surface-secondary));overflow:hidden}.sce-entity-info-card__logo-img{inline-size:100%;block-size:100%;object-fit:cover}.sce-entity-info-card__name{margin:0 0 var(--space-1);font-family:var(--font-family-arabic-primary);font-size:var(--font-size-md);font-weight:600;color:var(--color-text-primary)}.sce-entity-info-card__subtitle{margin:0 0 var(--space-2);font-size:var(--font-size-sm);color:var(--color-text-secondary)}.sce-entity-info-card__id{margin:0;font-size:var(--font-size-sm);color:var(--color-text-secondary)}.sce-entity-info-card__id-value{margin-inline-start:var(--space-1);font-weight:600;color:var(--color-text-primary)}\n"] }]
|
|
11148
11338
|
}], propDecorators: { labelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelKey", required: true }] }], nameKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "nameKey", required: false }] }], nameText: [{ type: i0.Input, args: [{ isSignal: true, alias: "nameText", required: false }] }], subtitleText: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitleText", required: false }] }], idLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "idLabelKey", required: false }] }], idValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "idValue", required: false }] }], logoSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "logoSrc", required: false }] }], logoAlt: [{ type: i0.Input, args: [{ isSignal: true, alias: "logoAlt", required: false }] }], iconName: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconName", required: false }] }], iconSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconSize", required: false }] }], badgeTone: [{ type: i0.Input, args: [{ isSignal: true, alias: "badgeTone", required: false }] }] } });
|
|
11149
11339
|
|
|
11340
|
+
/** Card that either shows a completion progress bar or, in `cta` mode, an illustrated call-to-action button emitting `nextStep`. */
|
|
11150
11341
|
class SceProgressCardComponent {
|
|
11151
11342
|
mode = input('progress', ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
11152
11343
|
titleKey = input('', ...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
|
|
@@ -11168,6 +11359,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11168
11359
|
}, template: "@if (titleText() || titleKey()) {\n <h4 class=\"sce-progress-card__title\">{{ titleText() || (titleKey() | translate) }}</h4>\n}\n@if (illustrationSrc()) {\n <div class=\"sce-progress-card__illustration\">\n <img [src]=\"illustrationSrc()\" alt=\"\" loading=\"lazy\" />\n </div>\n}\n@if (descriptionText() || descriptionKey()) {\n <p class=\"sce-progress-card__desc\">{{ descriptionText() || (descriptionKey() | translate) }}</p>\n}\n@if (mode() === 'progress') {\n <sce-progress-bar [progress]=\"progress()\" [max]=\"100\" [showLabel]=\"true\" />\n}\n<ng-content select=\"[data-actions]\" />\n@if (buttonKey()) {\n <button type=\"button\" class=\"sce-progress-card__action\" (click)=\"nextStep.emit()\">\n {{ buttonKey() | translate }}\n </button>\n}\n", styles: [":host{display:block;display:grid;gap:var(--space-5);padding:var(--space-24);border:1px solid var(--color-primary-100, var(--card-border-subtle));border-radius:var(--radius-xl, var(--space-4));background:var(--color-surface, var(--app-surface))}:host(.sce-progress-card--cta){gap:var(--space-4)}.sce-progress-card__title{margin:0;color:var(--text-text-primary-900, var(--color-text-primary));font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold)}.sce-progress-card__desc{margin:0;color:var(--text-text-secondary-700, var(--color-text-secondary));font-size:var(--font-size-md);font-weight:var(--font-weight-regular)}.sce-progress-card__illustration{display:flex;justify-content:center}.sce-progress-card__illustration img{max-inline-size:100%;block-size:auto}.sce-progress-card__action{inline-size:100%;border:0;border-radius:var(--radius-lg, var(--space-3));padding:var(--space-3-5, var(--space-3)) var(--space-24);background:var(--button-background-primary-bg-primary, var(--color-brand-primary));color:var(--text-text-primaryon-brand, var(--color-on-primary));font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);cursor:pointer}\n"] }]
|
|
11169
11360
|
}], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: false }] }], descriptionKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "descriptionKey", required: false }] }], titleText: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleText", required: false }] }], descriptionText: [{ type: i0.Input, args: [{ isSignal: true, alias: "descriptionText", required: false }] }], buttonKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonKey", required: false }] }], progress: [{ type: i0.Input, args: [{ isSignal: true, alias: "progress", required: false }] }], illustrationSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "illustrationSrc", required: false }] }], nextStep: [{ type: i0.Output, args: ["nextStep"] }] } });
|
|
11170
11361
|
|
|
11362
|
+
/** Prose block that renders the translated `contentKey` as a paragraph, unless `contentHtml` is supplied, in which case that raw HTML is rendered instead. */
|
|
11171
11363
|
class SceContentBlockComponent {
|
|
11172
11364
|
contentKey = input.required(...(ngDevMode ? [{ debugName: "contentKey" }] : /* istanbul ignore next */ []));
|
|
11173
11365
|
contentHtml = input(null, ...(ngDevMode ? [{ debugName: "contentHtml" }] : /* istanbul ignore next */ []));
|
|
@@ -11179,6 +11371,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11179
11371
|
args: [{ selector: 'sce-content-block', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-content-block' }, template: "@if (contentHtml()) {\n <div class=\"sce-content-block__body sce-content-block__body--rich\" [innerHTML]=\"contentHtml()\"></div>\n} @else {\n <p class=\"sce-content-block__body\">{{ contentKey() | translate }}</p>\n}\n", styles: [":host{display:block}\n"] }]
|
|
11180
11372
|
}], propDecorators: { contentKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentKey", required: true }] }], contentHtml: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentHtml", required: false }] }] } });
|
|
11181
11373
|
|
|
11374
|
+
/** Renders `items` (translation keys) as an icon-bulleted list, laid out across `maxColumns` columns (default 1). */
|
|
11182
11375
|
class SceBulletListComponent {
|
|
11183
11376
|
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
11184
11377
|
maxColumns = input(1, ...(ngDevMode ? [{ debugName: "maxColumns" }] : /* istanbul ignore next */ []));
|
|
@@ -11190,6 +11383,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11190
11383
|
args: [{ selector: 'sce-bullet-list', standalone: true, imports: [TranslatePipe, SceIcon], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-bullet-list' }, template: "<ul class=\"sce-bullet-list__grid\" [style.grid-template-columns]=\"'repeat(' + maxColumns() + ', minmax(0, 1fr))'\">\n <!-- track $index: static bullet text list, fully replaced per input change -->\n @for (item of items(); track $index) {\n <li class=\"sce-bullet-list__item\">\n <sce-icon name=\"checked\" [size]=\"15\" class=\"sce-bullet-list__icon\" />\n <span>{{ item | translate }}</span>\n </li>\n }\n</ul>\n", styles: [":host{display:block}.sce-bullet-list__grid{display:grid;gap:var(--space-3);margin:0;padding:0;list-style:none}.sce-bullet-list__item{display:flex;align-items:flex-start;gap:var(--space-2);font-size:var(--font-size-sm);color:var(--color-text-primary)}.sce-bullet-list__icon{flex-shrink:0;margin-block-start:var(--space-1);color:var(--color-brand-primary)}\n"] }]
|
|
11191
11384
|
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], maxColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxColumns", required: false }] }] } });
|
|
11192
11385
|
|
|
11386
|
+
/** Dashboard KPI card showing a headline value, an up/down trend percentage and an optional sparkline chart. */
|
|
11193
11387
|
class SceStatsAnalyticsCardComponent {
|
|
11194
11388
|
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
11195
11389
|
titleLinkText = input('', ...(ngDevMode ? [{ debugName: "titleLinkText" }] : /* istanbul ignore next */ []));
|
|
@@ -11210,6 +11404,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11210
11404
|
args: [{ selector: 'sce-stats-analytics-card', standalone: true, imports: [SceIcon, SceOverviewStatSparklineComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-stats-analytics-card' }, template: "<article class=\"sce-stats-analytics-card__surface\">\n <div class=\"sce-stats-analytics-card__header\">\n @if (titleLinkText()) {\n <a\n class=\"sce-stats-analytics-card__link\"\n [href]=\"titleLinkUrl() || '#'\"\n [attr.target]=\"titleLinkUrl() ? '_blank' : null\"\n [attr.rel]=\"titleLinkUrl() ? 'noopener noreferrer' : null\"\n >\n {{ titleLinkText() }}\n </a>\n }\n <h3 class=\"sce-stats-analytics-card__title\">{{ title() }}</h3>\n </div>\n\n <div class=\"sce-stats-analytics-card__body\">\n @if (showChart()) {\n <div class=\"sce-stats-analytics-card__chart\" aria-hidden=\"true\">\n <sce-overview-stat-sparkline [color]=\"chartColor()\" />\n </div>\n }\n\n <div class=\"sce-stats-analytics-card__metric\">\n @if (percentage() != null) {\n <div class=\"sce-stats-analytics-card__trend\">\n @if (trendLabel()) {\n <span class=\"sce-stats-analytics-card__trend-label\">{{ trendLabel() }}</span>\n }\n <span class=\"sce-stats-analytics-card__trend-percent\">{{ percentage() }}%</span>\n </div>\n }\n <div class=\"sce-stats-analytics-card__value-row\">\n <span class=\"sce-stats-analytics-card__value\">{{ value() }}</span>\n @if (showTrendIcon()) {\n <sce-icon [name]=\"trendIcon()\" [size]=\"24\" />\n }\n </div>\n </div>\n </div>\n</article>\n", styles: [":host{display:block}.sce-stats-analytics-card__surface{padding:var(--space-4);border:1px solid var(--color-border-subtle);border-radius:var(--radius-lg);background:var(--color-surface-primary)}.sce-stats-analytics-card__header{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);margin-block-end:var(--space-3)}.sce-stats-analytics-card__title{margin:0;font-size:var(--font-size-sm);font-weight:500;color:var(--color-text-secondary)}.sce-stats-analytics-card__link{font-size:var(--font-size-sm);color:var(--color-brand-primary);text-decoration:none}.sce-stats-analytics-card__body{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--space-4)}.sce-stats-analytics-card__value-row{display:flex;align-items:center;gap:var(--space-2)}.sce-stats-analytics-card__value{font-size:var(--font-size-2xl);font-weight:700;color:var(--color-text-primary)}.sce-stats-analytics-card__trend{margin-block-end:var(--space-1);font-size:var(--font-size-xs);color:var(--color-text-secondary)}\n"] }]
|
|
11211
11405
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], titleLinkText: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleLinkText", required: false }] }], titleLinkUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleLinkUrl", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], percentage: [{ type: i0.Input, args: [{ isSignal: true, alias: "percentage", required: false }] }], trend: [{ type: i0.Input, args: [{ isSignal: true, alias: "trend", required: false }] }], trendLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "trendLabel", required: false }] }], showTrendIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTrendIcon", required: false }] }], showChart: [{ type: i0.Input, args: [{ isSignal: true, alias: "showChart", required: false }] }], chartColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "chartColor", required: false }] }] } });
|
|
11212
11406
|
|
|
11407
|
+
/** Result screen shown after office-profile changes are submitted, rendering either the success or the pending-review outcome with links to the profile and the requests list. */
|
|
11213
11408
|
class SceOfficeProfileSubmitResultComponent {
|
|
11214
11409
|
result = input.required(...(ngDevMode ? [{ debugName: "result" }] : /* istanbul ignore next */ []));
|
|
11215
11410
|
viewProfile = output();
|
|
@@ -11222,6 +11417,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11222
11417
|
args: [{ selector: 'sce-office-profile-submit-result', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-office-profile-submit-result' }, imports: [TranslatePipe], template: "<div class=\"submitResultPage\">\n <section class=\"submitResultCard\">\n <div class=\"submitResultIconWrap\" aria-hidden=\"true\">\n @if (result() === 'success') {\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"96\" height=\"96\" viewBox=\"0 0 96 96\" fill=\"none\" aria-hidden=\"true\">\n <circle cx=\"48\" cy=\"48\" r=\"48\" fill=\"var(--color-kiwi-200)\" />\n <path d=\"M28 50l13 13 27-27\" stroke=\"var(--color-jade-700)\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n } @else {\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"88\" height=\"88\" viewBox=\"0 0 88 88\" fill=\"none\" aria-hidden=\"true\">\n <circle cx=\"44\" cy=\"44\" r=\"44\" fill=\"var(--color-yellow-100)\" />\n <path d=\"M44 26v22M44 60v2\" stroke=\"var(--color-warning-700)\" stroke-width=\"5\" stroke-linecap=\"round\" />\n </svg>\n }\n </div>\n\n @if (result() === 'success') {\n <h2 class=\"submitResultTitle\">\n {{ 'dashboard.officeProfileEdit.success.title' | translate }}\n </h2>\n <p class=\"submitResultSubtitle\">\n {{ 'dashboard.officeProfileEdit.success.subtitle' | translate }}\n </p>\n <p class=\"submitResultNotice\">\n {{ 'dashboard.officeProfileEdit.success.notice' | translate }}\n </p>\n <div class=\"submitResultActions\">\n <button type=\"button\" class=\"primaryButton\" (click)=\"viewProfile.emit()\">\n {{ 'dashboard.officeProfileEdit.success.viewProfile' | translate }}\n </button>\n <button type=\"button\" class=\"cancelButton\" (click)=\"viewProfile.emit()\">\n {{ 'dashboard.officeProfileEdit.success.backHome' | translate }}\n </button>\n </div>\n } @else {\n <h2 class=\"submitResultTitle\">\n {{ 'dashboard.officeProfileEdit.pending.title' | translate }}\n </h2>\n <p class=\"submitResultSubtitle\">\n {{ 'dashboard.officeProfileEdit.pending.subtitle' | translate }}\n </p>\n <p class=\"submitResultNotice\">\n {{ 'dashboard.officeProfileEdit.pending.notice' | translate }}\n </p>\n <div class=\"submitResultActions\">\n <button type=\"button\" class=\"primaryButton\" (click)=\"viewRequests.emit()\">\n {{ 'dashboard.officeProfileEdit.pending.viewRequests' | translate }}\n </button>\n <button type=\"button\" class=\"cancelButton\" (click)=\"viewProfile.emit()\">\n {{ 'dashboard.officeProfileEdit.pending.backHome' | translate }}\n </button>\n </div>\n }\n </section>\n</div>\n", styles: [":host{display:block}\n"] }]
|
|
11223
11418
|
}], propDecorators: { result: [{ type: i0.Input, args: [{ isSignal: true, alias: "result", required: true }] }], viewProfile: [{ type: i0.Output, args: ["viewProfile"] }], viewRequests: [{ type: i0.Output, args: ["viewRequests"] }] } });
|
|
11224
11419
|
|
|
11420
|
+
/** Static banner telling the user their office-profile update is awaiting review, with a link to the requests page; it takes no inputs. */
|
|
11225
11421
|
class ScePendingUpdateBannerComponent {
|
|
11226
11422
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ScePendingUpdateBannerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
11227
11423
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.17", type: ScePendingUpdateBannerComponent, isStandalone: true, selector: "sce-pending-update-banner", host: { classAttribute: "sce-pending-update-banner" }, ngImport: i0, template: "<div class=\"pendingBanner\" role=\"alert\">\n <div class=\"pendingBannerIcon\" aria-hidden=\"true\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <circle cx=\"10\" cy=\"10\" r=\"10\" fill=\"var(--color-yellow-100)\" />\n <path d=\"M10 6v5M10 13v1\" stroke=\"var(--color-warning-700)\" stroke-width=\"2\" stroke-linecap=\"round\" />\n </svg>\n </div>\n <div class=\"pendingBannerBody\">\n <p class=\"pendingBannerTitle\">\n {{ 'dashboard.officeProfileEdit.pendingBannerTitle' | translate }}\n </p>\n <p class=\"pendingBannerText\">\n {{ 'dashboard.officeProfileEdit.pendingBannerBody' | translate }}\n </p>\n </div>\n <a routerLink=\"/dashboard/data-requests\" class=\"pendingBannerLink\">\n {{ 'dashboard.officeProfileEdit.pendingBannerViewRequest' | translate }}\n </a>\n</div>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
@@ -11231,6 +11427,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11231
11427
|
args: [{ selector: 'sce-pending-update-banner', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-pending-update-banner' }, imports: [TranslatePipe, RouterLink], template: "<div class=\"pendingBanner\" role=\"alert\">\n <div class=\"pendingBannerIcon\" aria-hidden=\"true\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <circle cx=\"10\" cy=\"10\" r=\"10\" fill=\"var(--color-yellow-100)\" />\n <path d=\"M10 6v5M10 13v1\" stroke=\"var(--color-warning-700)\" stroke-width=\"2\" stroke-linecap=\"round\" />\n </svg>\n </div>\n <div class=\"pendingBannerBody\">\n <p class=\"pendingBannerTitle\">\n {{ 'dashboard.officeProfileEdit.pendingBannerTitle' | translate }}\n </p>\n <p class=\"pendingBannerText\">\n {{ 'dashboard.officeProfileEdit.pendingBannerBody' | translate }}\n </p>\n </div>\n <a routerLink=\"/dashboard/data-requests\" class=\"pendingBannerLink\">\n {{ 'dashboard.officeProfileEdit.pendingBannerViewRequest' | translate }}\n </a>\n</div>\n", styles: [":host{display:block}\n"] }]
|
|
11232
11428
|
}] });
|
|
11233
11429
|
|
|
11430
|
+
/** Bio section of the office-profile edit form, binding the parent's `FormGroup` to the summary field, the services multi-select and the availability select. */
|
|
11234
11431
|
class SceOfficeProfileEditBioSectionComponent {
|
|
11235
11432
|
form = input.required(...(ngDevMode ? [{ debugName: "form" }] : /* istanbul ignore next */ []));
|
|
11236
11433
|
serviceOptions = input.required(...(ngDevMode ? [{ debugName: "serviceOptions" }] : /* istanbul ignore next */ []));
|
|
@@ -11244,6 +11441,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11244
11441
|
args: [{ selector: 'sce-office-profile-edit-bio-section', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-office-profile-edit-bio-section' }, imports: [TranslatePipe, ReactiveFormsModule, SceMultiSelectFieldComponent, SceSelectFieldComponent], template: "<section class=\"editFormSection\" [formGroup]=\"form()\">\n <h3 class=\"editFormSectionTitle\">\n {{ 'dashboard.officeProfileEdit.bioAndServices' | translate }}\n </h3>\n\n <div class=\"editFormFields\">\n <div class=\"editFormControl\">\n <label class=\"editFormLabel\" for=\"office-summary\">\n {{ 'dashboard.officeProfileEdit.officeSummary' | translate }}\n <span class=\"editFormRequired\" aria-hidden=\"true\">*</span>\n </label>\n <textarea\n id=\"office-summary\"\n class=\"editFormTextarea\"\n formControlName=\"summary\"\n rows=\"4\"\n [placeholder]=\"'dashboard.officeProfileEdit.summaryPlaceholder' | translate\"\n ></textarea>\n @if (form().controls['summary'].errors?.['maxlength'] && form().controls['summary'].touched) {\n <span class=\"formError\" role=\"alert\">\n {{ 'VALIDATION.MAX_LENGTH' | translate: { max: 2000 } }}\n </span>\n }\n @if (form().controls['summary'].errors?.['required'] && form().controls['summary'].touched) {\n <span class=\"formError\" role=\"alert\">\n {{ 'VALIDATION.REQUIRED' | translate }}\n </span>\n }\n </div>\n\n <sce-multi-select-field\n id=\"serviceIds\"\n labelClassName=\"editFormLabel\"\n fieldClassName=\"editFormFieldWrap\"\n [label]=\"('dashboard.officeProfileEdit.services' | translate) + ' ' + ('dashboard.officeProfileEdit.servicesHint' | translate)\"\n [options]=\"serviceOptions()\"\n [value]=\"form().controls['serviceIds'].value\"\n [dir]=\"dir()\"\n [filter]=\"true\"\n [showClear]=\"false\"\n [required]=\"true\"\n [minSelected]=\"1\"\n [maxSelected]=\"10\"\n [placeholder]=\"'COMMON.CHOOSE' | translate\"\n (valueChange)=\"form().controls['serviceIds'].setValue($event)\"\n [containerClassName]=\"''\"\n />\n\n <sce-select-field\n id=\"availabilityStatus\"\n labelClassName=\"editFormLabel\"\n fieldClassName=\"editFormFieldWrap\"\n [label]=\"'dashboard.officeProfileEdit.availabilityStatus' | translate\"\n [options]=\"availabilityOptions()\"\n [value]=\"form().controls['availabilityStatus'].value\"\n [dir]=\"dir()\"\n [required]=\"true\"\n [showClear]=\"true\"\n [placeholder]=\"'COMMON.CHOOSE' | translate\"\n (valueChange)=\"form().controls['availabilityStatus'].setValue($event ?? '')\"\n [containerClassName]=\"''\"\n />\n </div>\n</section>\n", styles: [":host{display:block}\n"] }]
|
|
11245
11442
|
}], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], serviceOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "serviceOptions", required: true }] }], availabilityOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "availabilityOptions", required: true }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }] } });
|
|
11246
11443
|
|
|
11444
|
+
/** Media section of the office-profile edit form, with file-upload zones for the cover image and logo; the busy and error states come from the parent's save request rather than from an upload of its own. */
|
|
11247
11445
|
class SceOfficeProfileEditMediaSectionComponent {
|
|
11248
11446
|
locale = input('ar', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
|
|
11249
11447
|
coverExistingUrl = input('', ...(ngDevMode ? [{ debugName: "coverExistingUrl" }] : /* istanbul ignore next */ []));
|
|
@@ -11264,6 +11462,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11264
11462
|
args: [{ selector: 'sce-office-profile-edit-media-section', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-office-profile-edit-media-section' }, imports: [TranslatePipe, SceFileUploadZoneComponent], template: "<section class=\"card\">\n <div class=\"section withDivider\">\n <h3 class=\"sectionTitle editFormSectionTitle\">\n {{ 'dashboard.officeProfileEdit.logoAndCover' | translate }}\n </h3>\n <div class=\"uploadGrid\">\n <div class=\"formField\">\n <sce-file-upload-zone\n [locale]=\"locale()\"\n [accept]=\"'.pdf,.png,.jpg,.jpeg'\"\n [label]=\"'dashboard.officeProfileEdit.cover' | translate\"\n [description]=\"'dashboard.officeProfileEdit.uploadCoverHint' | translate\"\n [uploading]=\"uploading()\"\n [uploadError]=\"uploadError()\"\n [existingItems]=\"\n coverExistingUrl() && !coverFile()\n ? [{ id: 'cover', url: coverExistingUrl(), alt: ('dashboard.officeProfileEdit.cover' | translate) }]\n : []\n \"\n (fileChange)=\"coverChange.emit($event)\"\n />\n </div>\n\n <div class=\"formField\">\n <sce-file-upload-zone\n [locale]=\"locale()\"\n [accept]=\"'.pdf,.png,.jpg,.jpeg'\"\n [label]=\"'dashboard.officeProfileEdit.logo' | translate\"\n [description]=\"'dashboard.officeProfileEdit.uploadBrandHint' | translate\"\n [uploading]=\"uploading()\"\n [uploadError]=\"uploadError()\"\n [existingItems]=\"\n logoExistingUrl() && !logoFile()\n ? [{ id: 'logo', url: logoExistingUrl(), alt: ('dashboard.officeProfileEdit.logo' | translate) }]\n : []\n \"\n (fileChange)=\"logoChange.emit($event)\"\n />\n </div>\n </div>\n </div>\n</section>\n", styles: [":host{display:block}\n"] }]
|
|
11265
11463
|
}], propDecorators: { locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], coverExistingUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "coverExistingUrl", required: false }] }], coverFile: [{ type: i0.Input, args: [{ isSignal: true, alias: "coverFile", required: false }] }], logoExistingUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "logoExistingUrl", required: false }] }], logoFile: [{ type: i0.Input, args: [{ isSignal: true, alias: "logoFile", required: false }] }], uploading: [{ type: i0.Input, args: [{ isSignal: true, alias: "uploading", required: false }] }], uploadError: [{ type: i0.Input, args: [{ isSignal: true, alias: "uploadError", required: false }] }], coverChange: [{ type: i0.Output, args: ["coverChange"] }], logoChange: [{ type: i0.Output, args: ["logoChange"] }] } });
|
|
11266
11464
|
|
|
11465
|
+
/** Official-data section of the office-profile edit form, binding the parent's `FormGroup` to the bank, city and preferred-project-size selects plus the geo-location picker. */
|
|
11267
11466
|
class SceOfficeProfileEditOfficialSectionComponent {
|
|
11268
11467
|
form = input.required(...(ngDevMode ? [{ debugName: "form" }] : /* istanbul ignore next */ []));
|
|
11269
11468
|
bankOptions = input.required(...(ngDevMode ? [{ debugName: "bankOptions" }] : /* istanbul ignore next */ []));
|
|
@@ -11288,6 +11487,7 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "21.2.17", n
|
|
|
11288
11487
|
], template: "<section class=\"editFormSection\" [formGroup]=\"form()\">\n <h3 class=\"editFormSectionTitle\">\n {{ 'dashboard.officeProfileEdit.officialData' | translate }}\n </h3>\n\n <div class=\"editFormGrid\">\n <div class=\"editFormControl\">\n <label class=\"editFormLabel\" for=\"office-vat\">\n {{ 'dashboard.officeProfileEdit.taxRegNo' | translate }}\n <span class=\"editFormRequired\" aria-hidden=\"true\">*</span>\n </label>\n <input\n id=\"office-vat\"\n type=\"text\"\n dir=\"ltr\"\n class=\"editFormInput\"\n formControlName=\"vatRegistrationNumber\"\n inputmode=\"numeric\"\n maxlength=\"15\"\n [placeholder]=\"'dashboard.officeProfileEdit.taxRegPlaceholder' | translate\"\n />\n </div>\n\n <div class=\"editFormControl\">\n <label class=\"editFormLabel\" for=\"office-cr\">\n {{ 'dashboard.officeProfileEdit.unifiedNumber' | translate }}\n <span class=\"editFormRequired\" aria-hidden=\"true\">*</span>\n </label>\n <input\n id=\"office-cr\"\n type=\"text\"\n dir=\"ltr\"\n class=\"editFormInput\"\n formControlName=\"crNationalNumber\"\n inputmode=\"numeric\"\n [placeholder]=\"'dashboard.officeProfileEdit.unifiedNoPlaceholder' | translate\"\n />\n </div>\n\n <sce-select-field\n id=\"bankName\"\n labelClassName=\"editFormLabel\"\n fieldClassName=\"editFormFieldWrap\"\n [label]=\"'dashboard.officeProfileEdit.bank' | translate\"\n [options]=\"bankOptions()\"\n [value]=\"form().controls['bankName'].value\"\n [dir]=\"dir()\"\n [filter]=\"true\"\n [required]=\"true\"\n [showClear]=\"false\"\n [placeholder]=\"'dashboard.officeProfileEdit.selectBank' | translate\"\n (valueChange)=\"form().controls['bankName'].setValue($event ?? '')\"\n />\n\n <div class=\"editFormControl\">\n <label class=\"editFormLabel\" for=\"office-short-address\">\n {{ 'dashboard.officeProfileEdit.shortNationalAddress' | translate }}\n <span class=\"editFormRequired\" aria-hidden=\"true\">*</span>\n </label>\n <input\n id=\"office-short-address\"\n type=\"text\"\n dir=\"ltr\"\n class=\"editFormInput\"\n formControlName=\"shortNationalAddress\"\n maxlength=\"8\"\n [placeholder]=\"'dashboard.officeProfileEdit.shortAddressPlaceholder' | translate\"\n />\n </div>\n\n <div class=\"editFormControl editFormControl--full\">\n <label class=\"editFormLabel\" for=\"office-iban\">\n {{ 'dashboard.officeProfileEdit.iban' | translate }}\n <span class=\"editFormRequired\" aria-hidden=\"true\">*</span>\n </label>\n <!-- IBANs always read left-to-right: \"SA\" prefix then digits \u2014 keep the whole row LTR. -->\n <div class=\"editFormInputWithPrefix\" dir=\"ltr\">\n <span class=\"editFormInputPrefix\" aria-hidden=\"true\">SA</span>\n <input\n id=\"office-iban\"\n type=\"text\"\n dir=\"ltr\"\n class=\"editFormInput editFormInput--prefixed\"\n formControlName=\"iban\"\n maxlength=\"22\"\n [placeholder]=\"'dashboard.officeProfileEdit.ibanPlaceholder' | translate\"\n (input)=\"ibanInput.emit($event)\"\n />\n </div>\n </div>\n\n <div class=\"editFormControl editFormControl--full\">\n @defer (on idle) {\n <sce-geo-location-field\n [label]=\"'dashboard.officeProfileEdit.geoLocation'\"\n [value]=\"geoLocation()\"\n [locale]=\"locale()\"\n (valueChange)=\"locationSelect.emit($event)\"\n />\n } @placeholder {\n <div class=\"editFormInput editFormInput--skeleton\" aria-hidden=\"true\"></div>\n }\n </div>\n\n <div class=\"editFormControl editFormControl--full\">\n <label class=\"editFormLabel\" for=\"office-address\">\n {{ 'dashboard.officeProfileEdit.officeAddress' | translate }}\n <span class=\"editFormRequired\" aria-hidden=\"true\">*</span>\n </label>\n <input id=\"office-address\" type=\"text\" class=\"editFormInput\" formControlName=\"address\" />\n </div>\n\n <sce-select-field\n id=\"cityID\"\n labelClassName=\"editFormLabel\"\n fieldClassName=\"editFormFieldWrap\"\n [label]=\"'dashboard.officeProfileEdit.city' | translate\"\n [options]=\"cityOptions()\"\n [value]=\"form().controls['cityID'].value\"\n [dir]=\"dir()\"\n [filter]=\"true\"\n [required]=\"true\"\n [showClear]=\"false\"\n [placeholder]=\"'dashboard.officeProfileEdit.selectCity' | translate\"\n (valueChange)=\"form().controls['cityID'].setValue($event ?? '')\"\n />\n\n <sce-multi-select-field\n id=\"preferredProjectSizes\"\n labelClassName=\"editFormLabel\"\n fieldClassName=\"editFormFieldWrap\"\n [label]=\"'dashboard.officeProfileEdit.preferredProjectSizes' | translate\"\n [options]=\"preferredSizeOptions()\"\n [value]=\"form().controls['preferredProjectSizes'].value\"\n [dir]=\"dir()\"\n [required]=\"true\"\n [maxSelected]=\"3\"\n [showClear]=\"false\"\n [placeholder]=\"'COMMON.CHOOSE' | translate\"\n (valueChange)=\"form().controls['preferredProjectSizes'].setValue($event)\"\n [containerClassName]=\"''\"\n />\n </div>\n</section>\n", styles: [":host{display:block}\n"] }]
|
|
11289
11488
|
}], ctorParameters: null, propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], bankOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "bankOptions", required: true }] }], cityOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "cityOptions", required: true }] }], preferredSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "preferredSizeOptions", required: true }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], geoLocation: [{ type: i0.Input, args: [{ isSignal: true, alias: "geoLocation", required: false }] }], locationSelect: [{ type: i0.Output, args: ["locationSelect"] }], ibanInput: [{ type: i0.Output, args: ["ibanInput"] }] } }) });
|
|
11290
11489
|
|
|
11490
|
+
/** Contact section of the office-profile edit form, binding the parent's `FormGroup` to the contact detail inputs. */
|
|
11291
11491
|
class SceOfficeProfileEditContactSectionComponent {
|
|
11292
11492
|
form = input.required(...(ngDevMode ? [{ debugName: "form" }] : /* istanbul ignore next */ []));
|
|
11293
11493
|
dir = input('rtl', ...(ngDevMode ? [{ debugName: "dir" }] : /* istanbul ignore next */ []));
|
|
@@ -11299,6 +11499,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11299
11499
|
args: [{ selector: 'sce-office-profile-edit-contact-section', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-office-profile-edit-contact-section' }, imports: [TranslatePipe, ReactiveFormsModule], template: "<section class=\"editFormSection\" [formGroup]=\"form()\">\n <h3 class=\"editFormSectionTitle\">\n {{ 'dashboard.officeProfileEdit.contactInfo' | translate }}\n </h3>\n\n <div class=\"editFormGrid\">\n <div class=\"editFormControl\">\n <label class=\"editFormLabel\" for=\"office-phone\">\n {{ 'dashboard.officeProfileEdit.phone' | translate }}\n <span class=\"editFormRequired\" aria-hidden=\"true\">*</span>\n </label>\n <input\n id=\"office-phone\"\n type=\"tel\"\n class=\"editFormInput\"\n formControlName=\"phone\"\n inputmode=\"tel\"\n [placeholder]=\"'dashboard.officeProfileEdit.phonePlaceholder' | translate\"\n />\n @if (form().controls['phone'].invalid && form().controls['phone'].touched) {\n <span class=\"formError\" role=\"alert\">\n {{ 'VALIDATION.REQUIRED' | translate }}\n </span>\n }\n </div>\n\n <div class=\"editFormControl\">\n <label class=\"editFormLabel\" for=\"office-email\">\n {{ 'dashboard.officeProfileEdit.email' | translate }}\n <span class=\"editFormRequired\" aria-hidden=\"true\">*</span>\n </label>\n <input\n id=\"office-email\"\n type=\"email\"\n class=\"editFormInput\"\n formControlName=\"email\"\n inputmode=\"email\"\n [placeholder]=\"'dashboard.officeProfileEdit.emailPlaceholder' | translate\"\n />\n @if (form().controls['email'].invalid && form().controls['email'].touched) {\n <span class=\"formError\" role=\"alert\">\n @if (form().controls['email'].errors?.['required']) {\n {{ 'VALIDATION.REQUIRED' | translate }}\n } @else if (form().controls['email'].errors?.['email']) {\n {{ 'VALIDATION.EMAIL' | translate }}\n }\n </span>\n }\n </div>\n </div>\n</section>\n", styles: [":host{display:block}\n"] }]
|
|
11300
11500
|
}], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }] } });
|
|
11301
11501
|
|
|
11502
|
+
/** Projects section of the office-profile edit form, listing each project as a hero image with up to two thumbnails and emitting add, edit and delete requests by list index. */
|
|
11302
11503
|
class SceOfficeProfileEditProjectsSectionComponent {
|
|
11303
11504
|
projects = input.required(...(ngDevMode ? [{ debugName: "projects" }] : /* istanbul ignore next */ []));
|
|
11304
11505
|
addProject = output();
|
|
@@ -11317,6 +11518,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11317
11518
|
args: [{ selector: 'sce-office-profile-edit-projects-section', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-office-profile-edit-projects-section' }, imports: [TranslatePipe], template: "<section class=\"card\">\n <div class=\"section withDivider\">\n <div class=\"projectsEditHeader\">\n <h3 class=\"sectionTitle\">\n {{ 'dashboard.officeProfileEdit.projectsManagement' | translate }}\n </h3>\n <button type=\"button\" class=\"addProjectBtn\" (click)=\"addProject.emit()\">\n <span aria-hidden=\"true\">+</span>\n {{ 'dashboard.officeProfileEdit.addProject' | translate }}\n </button>\n </div>\n\n <div class=\"editProjectList\">\n @for (project of projectsView(); track project.id) {\n <div class=\"editProjectRow\">\n <div class=\"editProjectGallery\" dir=\"ltr\" aria-hidden=\"true\">\n <div class=\"editProjectGalleryMain\">\n @if (project.heroUrl) {\n <img [src]=\"project.heroUrl\" alt=\"\" class=\"editProjectGalleryMainImg\" loading=\"lazy\" />\n }\n </div>\n @if (project.thumbUrls.length > 0) {\n <div class=\"editProjectGalleryStack\">\n @for (thumb of project.thumbUrls; track thumb) {\n <img [src]=\"thumb\" alt=\"\" class=\"editProjectGalleryThumb\" loading=\"lazy\" />\n }\n </div>\n }\n </div>\n\n <div class=\"editProjectInfo\">\n <p class=\"editProjectCardTitle\">{{ project.titleAr }}</p>\n <div class=\"editProjectMeta\">\n <span\n class=\"projectBadge\"\n [class.projectBadgeCompleted]=\"project.isCompleted\"\n [class.projectBadgeInProgress]=\"!project.isCompleted\"\n >\n @if (project.isCompleted) {\n {{ 'dashboard.officeProfileEdit.completed' | translate }}\n } @else {\n {{ 'dashboard.officeProfileEdit.inProgress' | translate }}\n }\n </span>\n @if (project.typeLabel) {\n <span class=\"editProjectMetaSep\" aria-hidden=\"true\">\u00B7</span>\n <span class=\"editProjectCategory\">{{ project.typeLabel }}</span>\n }\n </div>\n </div>\n\n <div class=\"editProjectActions\" dir=\"ltr\">\n <button\n type=\"button\"\n class=\"editProjectIconBtn\"\n [attr.aria-label]=\"'dashboard.officeProfileEdit.editProjectAction' | translate\"\n (click)=\"editProject.emit(project.id)\"\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\" />\n <path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\" />\n </svg>\n </button>\n <button\n type=\"button\"\n class=\"editProjectIconBtn\"\n [attr.aria-label]=\"'dashboard.officeProfileEdit.deleteProjectAction' | translate\"\n (click)=\"deleteProject.emit(project.id)\"\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"3 6 5 6 21 6\" />\n <path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\" />\n <path d=\"M10 11v6M14 11v6\" />\n <path d=\"M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2\" />\n </svg>\n </button>\n </div>\n </div>\n } @empty {\n <p class=\"editProjectEmptyMsg\">\n {{ 'dashboard.officeProfileEdit.noProjects' | translate }}\n </p>\n }\n </div>\n </div>\n</section>\n", styles: [":host{display:block}\n"] }]
|
|
11318
11519
|
}], propDecorators: { projects: [{ type: i0.Input, args: [{ isSignal: true, alias: "projects", required: true }] }], addProject: [{ type: i0.Output, args: ["addProject"] }], editProject: [{ type: i0.Output, args: ["editProject"] }], deleteProject: [{ type: i0.Output, args: ["deleteProject"] }] } });
|
|
11319
11520
|
|
|
11521
|
+
/** Dialog for adding or editing an office project, binding the parent's project `FormGroup` alongside an image upload zone whose minimum image count defaults to three. */
|
|
11320
11522
|
class SceOfficeProfileProjectEditorDialogComponent {
|
|
11321
11523
|
visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
11322
11524
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
@@ -11340,6 +11542,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11340
11542
|
args: [{ selector: 'sce-office-profile-project-editor-dialog', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-office-profile-project-editor-dialog' }, imports: [TranslatePipe, ReactiveFormsModule, Dialog, Button, SceSelectFieldComponent, SceFileUploadZoneComponent], template: "<p-dialog\n [visible]=\"visible()\"\n (visibleChange)=\"!$event && closeDialog.emit()\"\n [modal]=\"true\"\n [draggable]=\"false\"\n [resizable]=\"false\"\n [style]=\"{ width: '580px', maxWidth: '95vw' }\"\n [header]=\"title()\"\n [closeAriaLabel]=\"'COMMON.CLOSE' | translate\"\n appendTo=\"body\"\n styleClass=\"sce-project-dialog\"\n>\n <ng-template #content>\n <p class=\"projectDialogSubtitle\">{{ subtitle() }}</p>\n\n <form [formGroup]=\"projectForm()\">\n <div class=\"formField\" style=\"margin-block-end: var(--space-16)\">\n <label class=\"formLabel\" for=\"proj-name\">\n {{ 'dashboard.officeProfileEdit.projectName' | translate }}\n <span aria-hidden=\"true\"> *</span>\n </label>\n <input\n id=\"proj-name\"\n type=\"text\"\n class=\"formInput\"\n formControlName=\"name\"\n maxlength=\"200\"\n [placeholder]=\"'dashboard.officeProfileEdit.projectNamePlaceholder' | translate\"\n />\n @if (projectForm().controls['name'].invalid && projectForm().controls['name'].touched) {\n <span class=\"formError\" role=\"alert\">\n {{ 'VALIDATION.REQUIRED' | translate }}\n </span>\n }\n </div>\n\n @if (projectCategoryOptions().length > 0) {\n <div class=\"formField\" style=\"margin-block-end: var(--space-16)\">\n <sce-select-field\n id=\"proj-category\"\n [label]=\"'dashboard.officeProfileEdit.projectCategory' | translate\"\n [options]=\"projectCategoryOptions()\"\n [value]=\"projectForm().controls['category'].value\"\n [dir]=\"dir()\"\n [filter]=\"true\"\n [showClear]=\"true\"\n [placeholder]=\"'dashboard.officeProfileEdit.projectCategoryPlaceholder' | translate\"\n (valueChange)=\"projectForm().controls['category'].setValue($event ?? '')\"\n />\n </div>\n }\n\n <div class=\"formField\" style=\"margin-block-end: var(--space-16)\">\n <sce-select-field\n id=\"proj-status\"\n [label]=\"'dashboard.officeProfileEdit.projectStatus' | translate\"\n [options]=\"projectStatusOptions()\"\n [value]=\"projectForm().controls['status'].value\"\n [dir]=\"dir()\"\n [showClear]=\"false\"\n (valueChange)=\"projectForm().controls['status'].setValue($event === 'completed' ? 'completed' : 'inprogress')\"\n />\n </div>\n\n <div class=\"formField\" style=\"margin-block-end: var(--space-16)\">\n <label class=\"formLabel\" for=\"proj-desc\">\n {{ 'dashboard.officeProfileEdit.projectDescription' | translate }}\n <span aria-hidden=\"true\"> *</span>\n </label>\n <textarea\n id=\"proj-desc\"\n class=\"formTextarea\"\n formControlName=\"description\"\n rows=\"4\"\n maxlength=\"2000\"\n [placeholder]=\"'dashboard.officeProfileEdit.projectDescriptionPlaceholder' | translate\"\n ></textarea>\n @if (projectForm().controls['description'].invalid && projectForm().controls['description'].touched) {\n <span class=\"formError\" role=\"alert\">\n {{ 'VALIDATION.REQUIRED' | translate }}\n </span>\n }\n </div>\n\n <div class=\"formField\">\n <span class=\"formLabel\">\n {{ 'dashboard.officeProfileEdit.projectImages' | translate }}\n <span aria-hidden=\"true\"> *</span>\n </span>\n <sce-file-upload-zone\n [locale]=\"locale()\"\n [multiple]=\"true\"\n [maxFiles]=\"10\"\n [accept]=\"'.png,.jpg,.jpeg'\"\n [label]=\"'dashboard.officeProfileEdit.projectImagesRequired' | translate\"\n [description]=\"'dashboard.officeProfileEdit.projectImagesHint' | translate: { count: projectMinImageCount() }\"\n [showPreviews]=\"true\"\n [variant]=\"'dialog'\"\n (filesChange)=\"filesChange.emit($event)\"\n />\n @if (projectError()) {\n <span class=\"formError\" role=\"alert\">{{ projectError() }}</span>\n }\n </div>\n </form>\n </ng-template>\n\n <ng-template #footer>\n <p-button [label]=\"'dashboard.officeProfileEdit.cancel' | translate\" severity=\"secondary\" (onClick)=\"closeDialog.emit()\" />\n <!-- severity=\"contrast\": the raw preset primary (#10b981) fails AA contrast at 2.53:1\n with white label text. -->\n <p-button [label]=\"saveLabel()\" severity=\"contrast\" (onClick)=\"saveProject.emit()\" />\n </ng-template>\n</p-dialog>\n", styles: [":host{display:block}\n"] }]
|
|
11341
11543
|
}], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: true }] }], projectForm: [{ type: i0.Input, args: [{ isSignal: true, alias: "projectForm", required: true }] }], projectCategoryOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "projectCategoryOptions", required: false }] }], projectStatusOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "projectStatusOptions", required: false }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], projectError: [{ type: i0.Input, args: [{ isSignal: true, alias: "projectError", required: false }] }], saveLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "saveLabel", required: true }] }], projectMinImageCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "projectMinImageCount", required: false }] }], closeDialog: [{ type: i0.Output, args: ["closeDialog"] }], saveProject: [{ type: i0.Output, args: ["saveProject"] }], filesChange: [{ type: i0.Output, args: ["filesChange"] }] } });
|
|
11342
11544
|
|
|
11545
|
+
/** Confirmation dialog asking the user to confirm deleting an office project. */
|
|
11343
11546
|
class SceOfficeProfileProjectDeleteDialogComponent {
|
|
11344
11547
|
visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
11345
11548
|
closeDialog = output();
|
|
@@ -11352,6 +11555,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11352
11555
|
args: [{ selector: 'sce-office-profile-project-delete-dialog', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-office-profile-project-delete-dialog' }, imports: [TranslatePipe, Dialog, Button], template: "<p-dialog\n [visible]=\"visible()\"\n (visibleChange)=\"!$event && closeDialog.emit()\"\n [modal]=\"true\"\n [draggable]=\"false\"\n [resizable]=\"false\"\n [style]=\"{ width: '440px', maxWidth: '95vw' }\"\n [header]=\"'dashboard.officeProfileEdit.deleteProjectConfirmTitle' | translate\"\n [closeAriaLabel]=\"'COMMON.CLOSE' | translate\"\n styleClass=\"sce-project-dialog\"\n>\n <ng-template #content>\n <p style=\"margin: 0; color: var(--text-text-secondary-700); line-height: 1.6\">\n {{ 'dashboard.officeProfileEdit.deleteProjectConfirmBody' | translate }}\n </p>\n </ng-template>\n\n <ng-template #footer>\n <p-button [label]=\"'dashboard.officeProfileEdit.cancel' | translate\" severity=\"secondary\" (onClick)=\"closeDialog.emit()\" />\n <p-button [label]=\"'dashboard.officeProfileEdit.deleteProject' | translate\" severity=\"danger\" (onClick)=\"confirmDelete.emit()\" />\n </ng-template>\n</p-dialog>\n", styles: [":host{display:block}\n"] }]
|
|
11353
11556
|
}], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], closeDialog: [{ type: i0.Output, args: ["closeDialog"] }], confirmDelete: [{ type: i0.Output, args: ["confirmDelete"] }] } });
|
|
11354
11557
|
|
|
11558
|
+
/** Hero header of the office profile view — banner, logo, name, city, rating and verification badge — plus the profile's tab bar and an optional active/inactive status switch. */
|
|
11355
11559
|
class SceOfficeProfileHeroComponent {
|
|
11356
11560
|
bannerUrl = input(null, ...(ngDevMode ? [{ debugName: "bannerUrl" }] : /* istanbul ignore next */ []));
|
|
11357
11561
|
logoUrl = input(null, ...(ngDevMode ? [{ debugName: "logoUrl" }] : /* istanbul ignore next */ []));
|
|
@@ -11384,6 +11588,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11384
11588
|
args: [{ selector: 'sce-office-profile-hero', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: { class: 'sce-office-profile-hero' }, imports: [TranslatePipe, SceEngineeringOfficeVerificationBadgeComponent, SceSwitchComponent], template: "<section class=\"card\">\n <!-- Hero + Logo -->\n <div class=\"heroWrap\">\n <div class=\"heroCoverPlaceholder\" aria-hidden=\"true\">\n @if (bannerUrl()) {\n <img [src]=\"bannerUrl()\" alt=\"\" class=\"heroCoverImage\" loading=\"lazy\" />\n } @else {\n <img src=\"/assets/icons/building-03.svg\" width=\"48\" height=\"48\" alt=\"\" />\n }\n </div>\n <div class=\"heroLogo\">\n <div class=\"logoPlaceholder\" aria-hidden=\"true\">\n @if (logoUrl()) {\n <img [src]=\"logoUrl()\" alt=\"\" class=\"logoImage\" loading=\"lazy\" />\n } @else {\n <img src=\"/assets/icons/office1.svg\" width=\"56\" height=\"56\" alt=\"\" aria-hidden=\"true\" />\n }\n </div>\n </div>\n </div>\n\n <!-- Update data button / system-user status switch -->\n <div class=\"updateDataRow\">\n @if (showOfficeStatusSwitch()) {\n <sce-switch\n [checked]=\"officeIsActive()\"\n [disabled]=\"officeStatusSaving()\"\n [showLabel]=\"true\"\n [activeLabel]=\"'dashboard.individualUsers.status.active' | translate\"\n [inactiveLabel]=\"'dashboard.individualUsers.status.inactive' | translate\"\n (checkedChange)=\"statusChange.emit($event)\"\n />\n } @else {\n <button type=\"button\" class=\"updateDataBtn\" (click)=\"updateDataClick.emit()\" [disabled]=\"updateDataChecking()\">\n @if (updateDataChecking()) {\n {{ 'dashboard.officeProfile.incompleteAlert.checking' | translate }}\n } @else {\n {{ 'dashboard.officeProfile.actions.updateData' | translate }}\n }\n </button>\n }\n </div>\n\n <!-- Office name & badges -->\n <div class=\"officeIdentity\">\n <div class=\"officeNameRow\">\n <sce-engineering-office-verification-badge [status]=\"verificationStatus()\" [size]=\"22\" />\n <h2 class=\"officeName\">{{ officeName() || '\u2014' }}</h2>\n </div>\n <div class=\"officeBadgesRow\">\n <span class=\"badgeLocation\">\uD83D\uDCCD{{ cityName() || '\u2014' }}</span>\n <span class=\"badgeRating\">\uD83C\uDFC6 {{ 'dashboard.officeProfile.verified' | translate }}</span>\n <span class=\"badgeRating\"> \u2B50{{ rating() }} ({{ ratingCount() }}) {{ 'dashboard.officeProfile.rating' | translate }} </span>\n @if (isAvailable()) {\n <span class=\"badgeAvailable\">\n <span class=\"availableDot\" aria-hidden=\"true\"></span>\n {{ 'dashboard.officeProfile.available' | translate }}\n </span>\n }\n </div>\n </div>\n\n <!-- Tab bar -->\n <div class=\"tabs\">\n @for (tab of tabKeys(); track tab) {\n <button type=\"button\" class=\"tab\" [class.tabActive]=\"activeTab() === tab\" (click)=\"tabChange.emit(tab)\">\n {{ tabLabels()[tab] }}\n </button>\n }\n </div>\n <div class=\"tabsContentDivider\"></div>\n</section>\n", styles: [":host{display:block}\n"] }]
|
|
11385
11589
|
}], propDecorators: { bannerUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "bannerUrl", required: false }] }], logoUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "logoUrl", required: false }] }], officeName: [{ type: i0.Input, args: [{ isSignal: true, alias: "officeName", required: false }] }], cityName: [{ type: i0.Input, args: [{ isSignal: true, alias: "cityName", required: false }] }], rating: [{ type: i0.Input, args: [{ isSignal: true, alias: "rating", required: false }] }], ratingCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "ratingCount", required: false }] }], isAvailable: [{ type: i0.Input, args: [{ isSignal: true, alias: "isAvailable", required: false }] }], verificationStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "verificationStatus", required: false }] }], showOfficeStatusSwitch: [{ type: i0.Input, args: [{ isSignal: true, alias: "showOfficeStatusSwitch", required: false }] }], officeIsActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "officeIsActive", required: false }] }], officeStatusSaving: [{ type: i0.Input, args: [{ isSignal: true, alias: "officeStatusSaving", required: false }] }], updateDataChecking: [{ type: i0.Input, args: [{ isSignal: true, alias: "updateDataChecking", required: false }] }], activeTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTab", required: false }] }], tabKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabKeys", required: false }] }], tabLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabLabels", required: false }] }], updateDataClick: [{ type: i0.Output, args: ["updateDataClick"] }], statusChange: [{ type: i0.Output, args: ["statusChange"] }], tabChange: [{ type: i0.Output, args: ["tabChange"] }] } });
|
|
11386
11590
|
|
|
11591
|
+
/** Row of headline office statistics: years of experience, project count and service count. */
|
|
11387
11592
|
class SceOfficeProfileStatsRowComponent {
|
|
11388
11593
|
yearsOfExperience = input('—', ...(ngDevMode ? [{ debugName: "yearsOfExperience" }] : /* istanbul ignore next */ []));
|
|
11389
11594
|
projectsCount = input(0, ...(ngDevMode ? [{ debugName: "projectsCount" }] : /* istanbul ignore next */ []));
|
|
@@ -11396,6 +11601,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11396
11601
|
args: [{ selector: 'sce-office-profile-stats-row', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: { class: 'sce-office-profile-stats-row' }, imports: [TranslatePipe], template: "<div class=\"statsRow\">\n <div class=\"metricCard\">\n <div class=\"metricIcon\">\n <img src=\"/assets/icons/audit-01-alt.svg\" width=\"28\" height=\"28\" alt=\"\" />\n </div>\n <div class=\"metricText\">\n <p class=\"metricValue\">{{ yearsOfExperience() }}</p>\n <p class=\"metricLabel\">{{ 'dashboard.officeProfile.yearsExperience' | translate }}</p>\n </div>\n </div>\n <div class=\"metricCard\">\n <div class=\"metricIcon\">\n <img src=\"/assets/icons/building-03.svg\" width=\"28\" height=\"28\" alt=\"\" />\n </div>\n <div class=\"metricText\">\n <p class=\"metricValue\">{{ projectsCount() }}</p>\n <p class=\"metricLabel\">{{ 'dashboard.officeProfile.projectsMetric' | translate }}</p>\n </div>\n </div>\n <div class=\"metricCard\">\n <div class=\"metricIcon\">\n <img src=\"/assets/icons/calendar-04-alt.svg\" width=\"28\" height=\"28\" alt=\"\" aria-hidden=\"true\" />\n </div>\n <div class=\"metricText\">\n <p class=\"metricValue\">{{ servicesCount() }}</p>\n <p class=\"metricLabel\">{{ 'dashboard.officeProfile.servicesMetric' | translate }}</p>\n </div>\n </div>\n</div>\n", styles: [":host{display:block}\n"] }]
|
|
11397
11602
|
}], propDecorators: { yearsOfExperience: [{ type: i0.Input, args: [{ isSignal: true, alias: "yearsOfExperience", required: false }] }], projectsCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "projectsCount", required: false }] }], servicesCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "servicesCount", required: false }] }] } });
|
|
11398
11603
|
|
|
11604
|
+
/** Overview tab of the office profile view, showing the summary, services, license number, expiry and status, and office type as info-field cards. */
|
|
11399
11605
|
class SceOfficeProfileOverviewTabComponent {
|
|
11400
11606
|
summary = input('', ...(ngDevMode ? [{ debugName: "summary" }] : /* istanbul ignore next */ []));
|
|
11401
11607
|
servicesDisplay = input([], ...(ngDevMode ? [{ debugName: "servicesDisplay" }] : /* istanbul ignore next */ []));
|
|
@@ -11411,6 +11617,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11411
11617
|
args: [{ selector: 'sce-office-profile-overview-tab', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: { class: 'sce-office-profile-overview-tab' }, imports: [TranslatePipe, SceInfoFieldCardComponent, SceInfoFieldsGridComponent], template: "<section class=\"card overviewCard\">\n <div class=\"overviewSection\">\n <h3 class=\"overviewSectionTitle\">{{ 'dashboard.officeProfile.aboutOffice' | translate }}</h3>\n <p class=\"overviewSummaryText\">{{ summary() || '\u2014' }}</p>\n </div>\n <div class=\"overviewSectionDivider\"></div>\n <div class=\"overviewSection\">\n <h3 class=\"overviewSectionTitle\">{{ 'dashboard.officeProfile.servicesProvided' | translate }}</h3>\n @if (servicesDisplay().length > 0) {\n <div class=\"overviewServicesChips\">\n @for (service of servicesDisplay(); track service) {\n <span class=\"overviewServiceChip\">{{ service }}</span>\n }\n </div>\n }\n </div>\n</section>\n\n<section class=\"card overviewCard\">\n <div class=\"section withDivider overviewSection\">\n <h3 class=\"sectionTitle overviewSectionTitle\">{{ 'dashboard.officeProfile.licenseInfo' | translate }}</h3>\n <sce-info-fields-grid gap=\"sm\" class=\"overviewInfoFieldsGrid\">\n <sce-info-field-card [label]=\"'dashboard.officeProfile.licenseNumber' | translate\" [value]=\"licenseNumber() || '\u2014'\" />\n <sce-info-field-card [label]=\"'dashboard.officeProfile.licenseExpiry' | translate\" [value]=\"licenseExpiryFormatted()\" />\n <sce-info-field-card [label]=\"'dashboard.officeProfile.licenseStatus' | translate\" [value]=\"licenseStatus()\" />\n @if (officeTypeDisplay()) {\n <sce-info-field-card [label]=\"'dashboard.officeProfile.officeType' | translate\" [value]=\"officeTypeDisplay()\" [fullWidth]=\"true\" />\n }\n </sce-info-fields-grid>\n </div>\n</section>\n", styles: [":host{display:contents}\n"] }]
|
|
11412
11618
|
}], propDecorators: { summary: [{ type: i0.Input, args: [{ isSignal: true, alias: "summary", required: false }] }], servicesDisplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "servicesDisplay", required: false }] }], licenseNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "licenseNumber", required: false }] }], licenseExpiryFormatted: [{ type: i0.Input, args: [{ isSignal: true, alias: "licenseExpiryFormatted", required: false }] }], licenseStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "licenseStatus", required: false }] }], officeTypeDisplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "officeTypeDisplay", required: false }] }] } });
|
|
11413
11619
|
|
|
11620
|
+
/** Projects tab of the office profile view, rendering each project with its image gallery and showing skeletons while the project images load. */
|
|
11414
11621
|
class SceOfficeProfileProjectsTabComponent {
|
|
11415
11622
|
displayProjects = input([], ...(ngDevMode ? [{ debugName: "displayProjects" }] : /* istanbul ignore next */ []));
|
|
11416
11623
|
projectImagesLoading = input(false, ...(ngDevMode ? [{ debugName: "projectImagesLoading" }] : /* istanbul ignore next */ []));
|
|
@@ -11423,6 +11630,7 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "21.2.17", n
|
|
|
11423
11630
|
args: [{ selector: 'sce-office-profile-projects-tab', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: { class: 'sce-office-profile-projects-tab' }, imports: [TranslatePipe, SceSkeleton, SceOfficeProjectGalleryComponent], template: "<section class=\"card\">\n <div class=\"section\">\n <h3 class=\"sectionTitle\">{{ 'dashboard.officeProfile.projectsList' | translate }}</h3>\n <div class=\"projectList\">\n @if (displayProjects().length === 0) {\n <p class=\"emptyText\">{{ 'dashboard.officeProfile.noProjects' | translate }}</p>\n }\n @for (proj of displayProjects(); track proj.id) {\n <article class=\"projectCard\">\n <div class=\"projectCardTop\">\n <div class=\"projectCardHeader\">\n @if (proj.typeLabel) {\n <span class=\"projectCategoryBadge\">{{ proj.typeLabel }}</span>\n }\n <h4 class=\"projectCardTitle\">{{ proj.title || '\u2014' }}</h4>\n </div>\n <span\n class=\"projectStatusBadge\"\n [class.projectStatusCompleted]=\"proj.isCompleted\"\n [class.projectStatusInProgress]=\"!proj.isCompleted\"\n >\n @if (proj.isCompleted) {\n {{ 'dashboard.officeProfile.projectStatusCompleted' | translate }}\n } @else {\n {{ 'dashboard.officeProfile.projectStatusInProgress' | translate }}\n }\n </span>\n </div>\n\n <div class=\"projectCardBody\" [class.projectCardBodySingle]=\"proj.imageUrls.length === 0 && !projectImagesLoading()\">\n @if (proj.imageUrls.length > 0) {\n @defer (on viewport) {\n <sce-office-project-gallery [imageUrls]=\"proj.imageUrls\" [title]=\"proj.title\" [locale]=\"locale()\" [pending]=\"false\" />\n } @placeholder {\n <sce-skeleton variant=\"image\" aspectRatio=\"16/9\" animation=\"wave\" aria-hidden=\"true\" />\n }\n } @else if (projectImagesLoading()) {\n <sce-skeleton variant=\"image\" aspectRatio=\"16/9\" animation=\"wave\" aria-hidden=\"true\" />\n }\n\n <div class=\"projectCardContent\">\n <div class=\"projectDescription\">\n <p class=\"projectDescriptionLabel\">\n {{ 'dashboard.officeProfile.projectDescription' | translate }}\n </p>\n <p class=\"projectCardDescription\">{{ proj.description || '\u2014' }}</p>\n </div>\n </div>\n </div>\n </article>\n }\n </div>\n </div>\n</section>\n", styles: [":host{display:block}\n"] }]
|
|
11424
11631
|
}], ctorParameters: null, propDecorators: { displayProjects: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayProjects", required: false }] }], projectImagesLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "projectImagesLoading", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }] } }) });
|
|
11425
11632
|
|
|
11633
|
+
/** Contact tab of the office profile view, showing email, phone, city and address as info-field cards beside an embedded map and a link out to Google Maps. */
|
|
11426
11634
|
class SceOfficeProfileContactTabComponent {
|
|
11427
11635
|
email = input('', ...(ngDevMode ? [{ debugName: "email" }] : /* istanbul ignore next */ []));
|
|
11428
11636
|
phone = input('', ...(ngDevMode ? [{ debugName: "phone" }] : /* istanbul ignore next */ []));
|
|
@@ -11438,6 +11646,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11438
11646
|
args: [{ selector: 'sce-office-profile-contact-tab', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: { class: 'sce-office-profile-contact-tab' }, imports: [TranslatePipe, SceInfoFieldCardComponent, SceInfoFieldsGridComponent], template: "<section class=\"card overviewCard\">\n <div class=\"section overviewSection\">\n <h3 class=\"sectionTitle overviewSectionTitle\">{{ 'dashboard.officeProfile.contactInfo' | translate }}</h3>\n <sce-info-fields-grid gap=\"sm\" class=\"overviewInfoFieldsGrid\">\n <sce-info-field-card [label]=\"'dashboard.officeProfile.email' | translate\" [value]=\"email() || '\u2014'\" />\n <sce-info-field-card [label]=\"'dashboard.officeProfile.phone' | translate\" [value]=\"phone() || '\u2014'\" />\n <sce-info-field-card [label]=\"'dashboard.officeProfile.city' | translate\" [value]=\"cityName() || '\u2014'\" />\n <sce-info-field-card [label]=\"'dashboard.officeProfile.address' | translate\" [value]=\"addressDisplay() || '\u2014'\" [fullWidth]=\"true\" />\n </sce-info-fields-grid>\n\n <div class=\"locationSection\">\n <div class=\"mapWrap\">\n @if (safeMapEmbedSrc()) {\n <iframe\n class=\"mapFrame\"\n [src]=\"safeMapEmbedSrc()\"\n loading=\"lazy\"\n referrerpolicy=\"no-referrer-when-downgrade\"\n [title]=\"'dashboard.officeProfile.location' | translate\"\n ></iframe>\n } @else {\n <!-- role=\"img\": aria-label is prohibited on a plain div (axe: aria-prohibited-attr). -->\n <div class=\"mapPlaceholder\" role=\"img\" [attr.aria-label]=\"'dashboard.officeProfile.location' | translate\">\n <img src=\"/assets/icons/maps.svg\" width=\"48\" height=\"48\" alt=\"\" aria-hidden=\"true\" />\n </div>\n }\n </div>\n @if (addressDisplay()) {\n <a [href]=\"googleMapsLink()\" target=\"_blank\" rel=\"noreferrer\" class=\"mapLink\">\n {{ addressDisplay() }}\n </a>\n }\n </div>\n </div>\n</section>\n", styles: [":host{display:block}\n"] }]
|
|
11439
11647
|
}], propDecorators: { email: [{ type: i0.Input, args: [{ isSignal: true, alias: "email", required: false }] }], phone: [{ type: i0.Input, args: [{ isSignal: true, alias: "phone", required: false }] }], cityName: [{ type: i0.Input, args: [{ isSignal: true, alias: "cityName", required: false }] }], addressDisplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "addressDisplay", required: false }] }], safeMapEmbedSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "safeMapEmbedSrc", required: false }] }], googleMapsLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "googleMapsLink", required: false }] }] } });
|
|
11440
11648
|
|
|
11649
|
+
/** Official-data tab of the office profile view, showing VAT number, commercial registration, bank/IBAN and national address as info-field cards, with preferred project sizes rendered as PrimeNG tag chips when `useTagChips` is set. */
|
|
11441
11650
|
class SceOfficeProfileOfficialTabComponent {
|
|
11442
11651
|
vatNumber = input('', ...(ngDevMode ? [{ debugName: "vatNumber" }] : /* istanbul ignore next */ []));
|
|
11443
11652
|
commercialRegistrationNumber = input('', ...(ngDevMode ? [{ debugName: "commercialRegistrationNumber" }] : /* istanbul ignore next */ []));
|
|
@@ -11456,6 +11665,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11456
11665
|
args: [{ selector: 'sce-office-profile-official-tab', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: { class: 'sce-office-profile-official-tab' }, imports: [TranslatePipe, Tag, SceInfoFieldCardComponent, SceInfoFieldsGridComponent], template: "<section class=\"card overviewCard\">\n <div class=\"section overviewSection\">\n <h3 class=\"sectionTitle overviewSectionTitle\">{{ 'dashboard.officeProfile.officialData' | translate }}</h3>\n <sce-info-fields-grid gap=\"sm\" class=\"overviewInfoFieldsGrid\">\n <sce-info-field-card [label]=\"'dashboard.officeProfile.taxRegNo' | translate\" [value]=\"vatNumber() || '\u2014'\" />\n <sce-info-field-card [label]=\"'dashboard.officeProfile.unifiedNo' | translate\" [value]=\"commercialRegistrationNumber() || '\u2014'\" />\n <sce-info-field-card [label]=\"'dashboard.officeProfile.city' | translate\" [value]=\"cityName() || '\u2014'\" />\n <sce-info-field-card [label]=\"'dashboard.officeProfile.bankName' | translate\" [value]=\"bankNameDisplay() || '\u2014'\" />\n <sce-info-field-card [label]=\"'dashboard.officeProfile.shortAddress' | translate\" [value]=\"shortNationalAddress() || '\u2014'\" />\n <sce-info-field-card [label]=\"'dashboard.officeProfile.iban' | translate\" [value]=\"ibanNumber() || '\u2014'\" [fullWidth]=\"true\" />\n @if (preferredProjectSizesDisplay().length > 0) {\n <sce-info-field-card\n [label]=\"'dashboard.officeProfile.preferredProjectSize' | translate\"\n [fullWidth]=\"true\"\n [value]=\"useTagChips() ? '' : preferredProjectSizesLabel() || '\u2014'\"\n >\n @if (useTagChips()) {\n <div class=\"preferredSizesChips\">\n @for (size of preferredProjectSizesDisplay(); track size) {\n <p-tag [value]=\"size\" severity=\"secondary\" />\n }\n </div>\n }\n </sce-info-field-card>\n }\n </sce-info-fields-grid>\n </div>\n</section>\n", styles: [":host{display:contents}.preferredSizesChips{display:flex;flex-wrap:wrap;gap:var(--space-2)}\n"] }]
|
|
11457
11666
|
}], propDecorators: { vatNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "vatNumber", required: false }] }], commercialRegistrationNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "commercialRegistrationNumber", required: false }] }], cityName: [{ type: i0.Input, args: [{ isSignal: true, alias: "cityName", required: false }] }], bankNameDisplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "bankNameDisplay", required: false }] }], shortNationalAddress: [{ type: i0.Input, args: [{ isSignal: true, alias: "shortNationalAddress", required: false }] }], ibanNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "ibanNumber", required: false }] }], preferredProjectSizesDisplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "preferredProjectSizesDisplay", required: false }] }], preferredProjectSizesLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "preferredProjectSizesLabel", required: false }] }], useTagChips: [{ type: i0.Input, args: [{ isSignal: true, alias: "useTagChips", required: false }] }] } });
|
|
11458
11667
|
|
|
11668
|
+
/** Collapsible `<details>` panel (open by default) showing the reviewer's rejection note, or an em dash when the note is empty. */
|
|
11459
11669
|
class SceDataRequestRejectionPanelComponent {
|
|
11460
11670
|
/** The rejection note text from the API. Empty string shows a dash. */
|
|
11461
11671
|
note = input('', ...(ngDevMode ? [{ debugName: "note" }] : /* istanbul ignore next */ []));
|
|
@@ -11491,6 +11701,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11491
11701
|
}]
|
|
11492
11702
|
}], propDecorators: { note: [{ type: i0.Input, args: [{ isSignal: true, alias: "note", required: false }] }] } });
|
|
11493
11703
|
|
|
11704
|
+
/** Header card of a data-change request showing its number, status badge and office info grid, revealing the rejection panel only when `statusCode` is rejected. */
|
|
11494
11705
|
class SceDataRequestHeaderCardComponent {
|
|
11495
11706
|
/** Human-readable request number (e.g. "REQ-00123"). */
|
|
11496
11707
|
requestNumber = input.required(...(ngDevMode ? [{ debugName: "requestNumber" }] : /* istanbul ignore next */ []));
|
|
@@ -11529,6 +11740,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11529
11740
|
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { class: 'sce-data-request-header-card' }, template: "<article class=\"detailCard\">\n <header class=\"detailHeaderRow\">\n <div class=\"detailTitleGroup\">\n <h1 class=\"detailTitle\">\n {{ 'dashboard.contractDetails.requestLabel' | translate }}\n <sce-bidi-isolate>#{{ requestNumber() }}</sce-bidi-isolate>\n </h1>\n <sce-business-status-tag [label]=\"statusLabel()\" size=\"sm\" />\n </div>\n <p class=\"detailSubmissionDate\">\n {{ 'dashboard.dataRequests.details.requestInfo.submissionDate' | translate }}:\n {{ submissionDate() }}\n </p>\n </header>\n\n @if (statusCode() === 'rejected') {\n <sce-data-request-rejection-panel [note]=\"rejectionNote()\" />\n }\n\n <sce-info-fields-grid>\n <sce-info-field-card [label]=\"'dashboard.dataRequests.details.requestInfo.licenseNumber' | translate\" [value]=\"licenseNumber()\" />\n <sce-info-field-card [label]=\"'dashboard.dataRequests.details.requestInfo.officeName' | translate\" [value]=\"officeName()\" />\n <sce-info-field-card [label]=\"'dashboard.dataRequests.details.requestInfo.submissionDate' | translate\" [value]=\"submissionDate()\" />\n <sce-info-field-card [label]=\"'dashboard.dataRequests.details.requestInfo.requestedBy' | translate\" [value]=\"representativeName()\" />\n <sce-info-field-card [label]=\"'dashboard.dataRequests.details.requestInfo.reviewRequired' | translate\" [value]=\"reviewRequired()\" />\n <sce-info-field-card [label]=\"'dashboard.dataRequests.details.requestInfo.requestStatus' | translate\" [value]=\"requestStatusLabel()\" />\n <sce-info-field-card\n [label]=\"'dashboard.dataRequests.details.requestInfo.lastActionDate' | translate\"\n [value]=\"lastActionDate() || submissionDate()\"\n />\n </sce-info-fields-grid>\n</article>\n" }]
|
|
11530
11741
|
}], propDecorators: { requestNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "requestNumber", required: true }] }], statusLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "statusLabel", required: true }] }], statusCode: [{ type: i0.Input, args: [{ isSignal: true, alias: "statusCode", required: true }] }], submissionDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "submissionDate", required: true }] }], rejectionNote: [{ type: i0.Input, args: [{ isSignal: true, alias: "rejectionNote", required: false }] }], licenseNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "licenseNumber", required: true }] }], officeName: [{ type: i0.Input, args: [{ isSignal: true, alias: "officeName", required: true }] }], representativeName: [{ type: i0.Input, args: [{ isSignal: true, alias: "representativeName", required: true }] }], reviewRequired: [{ type: i0.Input, args: [{ isSignal: true, alias: "reviewRequired", required: true }] }], requestStatusLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "requestStatusLabel", required: true }] }], lastActionDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "lastActionDate", required: false }] }] } });
|
|
11531
11742
|
|
|
11743
|
+
/** Titled table contrasting each field's current and updated value in a data-change request, flagging the rows that changed. */
|
|
11532
11744
|
class SceDataRequestComparisonTableComponent {
|
|
11533
11745
|
/** Section heading text. */
|
|
11534
11746
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
@@ -11542,6 +11754,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11542
11754
|
args: [{ selector: 'sce-data-request-comparison-table', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { class: 'sce-data-request-comparison-table' }, template: "<section class=\"comparisonSection\">\n <h2 class=\"comparisonSectionTitle\">{{ title() }}</h2>\n <div class=\"comparisonTableHeader\">\n <span>{{ 'dashboard.dataRequests.details.table.field' | translate }}</span>\n <span>{{ 'dashboard.dataRequests.details.table.currentValue' | translate }}</span>\n <span>{{ 'dashboard.dataRequests.details.table.updatedValue' | translate }}</span>\n </div>\n @for (row of rows(); track row.label) {\n <div class=\"comparisonTableRow\" [class.comparisonTableRowChanged]=\"row.changed\">\n <span class=\"comparisonField\">{{ row.label }}</span>\n <span class=\"comparisonCurrent\" [attr.data-label]=\"'dashboard.dataRequests.details.table.currentValue' | translate\">{{\n row.current\n }}</span>\n <span class=\"comparisonUpdated\" [attr.data-label]=\"'dashboard.dataRequests.details.table.updatedValue' | translate\">{{\n row.updated\n }}</span>\n </div>\n }\n</section>\n" }]
|
|
11543
11755
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }] } });
|
|
11544
11756
|
|
|
11757
|
+
/** Side-by-side before/after image frames for a data-change request, sized square for `logo` and widescreen for `cover`, emitting a click per side. */
|
|
11545
11758
|
class SceDataRequestMediaComparisonComponent {
|
|
11546
11759
|
/** Block heading (e.g. "Logo" or "Cover"). */
|
|
11547
11760
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
@@ -11565,6 +11778,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11565
11778
|
args: [{ selector: 'sce-data-request-media-comparison', standalone: true, imports: [TranslatePipe, SceSkeleton, SceIcon], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { class: 'sce-data-request-media-comparison' }, template: "<div class=\"mediaCompareBlock\">\n <p class=\"mediaCompareTitle\">{{ title() }}</p>\n <div class=\"mediaCompareRow\">\n <!-- Current image column -->\n <div class=\"mediaCompareColumn\">\n <span class=\"mediaCompareBadge mediaCompareBadgeCurrent\">\n {{ 'dashboard.dataRequests.details.logoCover.current' | translate }}\n </span>\n <div\n class=\"mediaCompareFrame\"\n [class.mediaCompareLogoFrame]=\"variant() === 'logo'\"\n [class.mediaCompareCoverFrame]=\"variant() === 'cover'\"\n [class.mediaCompareLogoFrameCurrent]=\"variant() === 'logo'\"\n [class.mediaCompareCoverFrameCurrent]=\"variant() === 'cover'\"\n >\n @if (loading()) {\n <sce-skeleton variant=\"rectangular\" width=\"100%\" height=\"100%\" animation=\"wave\" aria-hidden=\"true\" />\n } @else if (currentUrl()) {\n <button type=\"button\" class=\"mediaCompareImageButton\" [attr.aria-label]=\"title()\" (click)=\"currentImageClick.emit()\">\n <img [src]=\"currentUrl()\" alt=\"\" class=\"mediaCompareImage\" loading=\"lazy\" />\n </button>\n } @else {\n <span class=\"mediaComparePlaceholder\">\u2014</span>\n }\n </div>\n </div>\n\n <!-- Direction arrow -->\n <div class=\"mediaCompareArrow\" aria-hidden=\"true\">\n <sce-icon name=\"media-compare-arrow\" [size]=\"23\" [height]=\"9\" />\n </div>\n\n <!-- New image column -->\n <div class=\"mediaCompareColumn\">\n <span class=\"mediaCompareBadge mediaCompareBadgeUpdated\">\n {{ 'dashboard.dataRequests.details.logoCover.updated' | translate }}\n </span>\n <div\n class=\"mediaCompareFrame\"\n [class.mediaCompareLogoFrame]=\"variant() === 'logo'\"\n [class.mediaCompareCoverFrame]=\"variant() === 'cover'\"\n [class.mediaCompareLogoFrameUpdated]=\"variant() === 'logo'\"\n [class.mediaCompareCoverFrameUpdated]=\"variant() === 'cover'\"\n >\n @if (loading()) {\n <sce-skeleton variant=\"rectangular\" width=\"100%\" height=\"100%\" animation=\"wave\" aria-hidden=\"true\" />\n } @else if (newUrl()) {\n <button type=\"button\" class=\"mediaCompareImageButton\" [attr.aria-label]=\"title()\" (click)=\"newImageClick.emit()\">\n <img [src]=\"newUrl()\" alt=\"\" class=\"mediaCompareImage\" loading=\"lazy\" />\n </button>\n } @else {\n <span class=\"mediaComparePlaceholder\">\u2014</span>\n }\n </div>\n </div>\n </div>\n</div>\n" }]
|
|
11566
11779
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], currentUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentUrl", required: false }] }], newUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "newUrl", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], currentImageClick: [{ type: i0.Output, args: ["currentImageClick"] }], newImageClick: [{ type: i0.Output, args: ["newImageClick"] }] } });
|
|
11567
11780
|
|
|
11781
|
+
/** Newsletter subscription dialog collecting a name, email and optional Saudi mobile number with its own touch-based validation, resetting all fields whenever it is closed. */
|
|
11568
11782
|
class SceNewsletterSubscriptionDialogComponent {
|
|
11569
11783
|
translate = inject(TranslateService);
|
|
11570
11784
|
visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
@@ -11671,6 +11885,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11671
11885
|
args: [{ host: { class: 'sce-newsletter-subscription-dialog' }, selector: 'sce-newsletter-subscription-dialog', standalone: true, imports: [TranslatePipe, SceFormDialogComponent, SceFormDialogSectionComponent, SceTextFieldComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<sce-form-dialog\n [visible]=\"visible()\"\n [locale]=\"locale()\"\n [title]=\"titleText()\"\n [subtitle]=\"subtitleText()\"\n [isSubmitting]=\"isSubmitting()\"\n [errorMessage]=\"apiError() || undefined\"\n [submitLabel]=\"submitLabelText()\"\n [cancelLabel]=\"cancelLabelText()\"\n size=\"sm\"\n (close)=\"onClose()\"\n (submitForm)=\"onSubmit()\"\n>\n <sce-form-dialog-section>\n <sce-text-field\n id=\"newsletter-client-name\"\n [label]=\"'newsletter.form.clientName' | translate\"\n [value]=\"clientName()\"\n [placeholder]=\"'newsletter.form.clientNamePlaceholder' | translate\"\n [required]=\"true\"\n [error]=\"clientNameError()\"\n validationMode=\"never\"\n autocomplete=\"name\"\n (valueChange)=\"clientName.set($event); clientNameTouched.set(true)\"\n />\n <sce-text-field\n id=\"newsletter-email\"\n type=\"email\"\n [label]=\"'newsletter.form.email' | translate\"\n [value]=\"email()\"\n [placeholder]=\"'newsletter.form.emailPlaceholder' | translate\"\n [required]=\"true\"\n [error]=\"emailError()\"\n validationMode=\"never\"\n autocomplete=\"email\"\n (valueChange)=\"email.set($event); emailTouched.set(true)\"\n />\n <sce-text-field\n id=\"newsletter-mobile\"\n type=\"tel\"\n [label]=\"'newsletter.form.mobile' | translate\"\n [value]=\"mobile()\"\n [placeholder]=\"'newsletter.form.mobilePlaceholder' | translate\"\n [error]=\"mobileError()\"\n validationMode=\"never\"\n autocomplete=\"tel\"\n (valueChange)=\"mobile.set($event); mobileTouched.set(true)\"\n />\n </sce-form-dialog-section>\n</sce-form-dialog>\n", styles: [":host{display:block;display:contents}\n"] }]
|
|
11672
11886
|
}], ctorParameters: () => [], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], isSubmitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSubmitting", required: false }] }], apiError: [{ type: i0.Input, args: [{ isSignal: true, alias: "apiError", required: false }] }], closeDialog: [{ type: i0.Output, args: ["closeDialog"] }], submitForm: [{ type: i0.Output, args: ["submitForm"] }] } });
|
|
11673
11887
|
|
|
11888
|
+
/** Profile-photo panel with a hidden file input: emits `photoFileSelected` on pick (resetting the input so the same file can be re-chosen) and `viewClick` only when `hasRealPhoto` is true; uses `ViewEncapsulation.None`. */
|
|
11674
11889
|
class SceProfilePhotoSectionComponent {
|
|
11675
11890
|
/** Currently displayed photo URL. Null or undefined shows the default avatar. */
|
|
11676
11891
|
photoUrl = input(null, ...(ngDevMode ? [{ debugName: "photoUrl" }] : /* istanbul ignore next */ []));
|
|
@@ -11718,6 +11933,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11718
11933
|
}] } });
|
|
11719
11934
|
|
|
11720
11935
|
const EMPTY_DISPLAY = '—';
|
|
11936
|
+
/** Personal-profile panel that flips between a read-only field grid and an edit form (`editing`), showing skeletons while `profile` is null and an inline banner for `error`; uses `ViewEncapsulation.None`. */
|
|
11721
11937
|
class SceProfileInfoSectionComponent {
|
|
11722
11938
|
/** Resolved profile data for the read (view) mode. Null shows skeleton. */
|
|
11723
11939
|
profile = input(null, ...(ngDevMode ? [{ debugName: "profile" }] : /* istanbul ignore next */ []));
|
|
@@ -11822,6 +12038,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11822
12038
|
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { class: 'sce-profile-info-section' }, template: "<section class=\"card\">\n @if (error()) {\n <sce-inline-api-error [message]=\"error()\" />\n }\n\n @if (loading()) {\n <sce-info-fields-skeleton [count]=\"8\" />\n }\n\n @if (profile()) {\n @if (!editing()) {\n @for (section of viewSections(); track section.titleKey) {\n <div class=\"cardHeader\">\n <h4 class=\"sectionTitle\">{{ section.titleKey | translate }}</h4>\n @if (section.showEditAction) {\n <sce-button variant=\"primary\" size=\"medium\" [fullWidth]=\"false\" (click)=\"editClick.emit()\">\n {{ 'dashboard.profile.updateProfile' | translate }}\n </sce-button>\n }\n </div>\n\n <sce-info-fields-grid gap=\"sm\">\n @for (field of section.fields; track field.labelKey) {\n <sce-info-field-card [label]=\"field.labelKey | translate\" [value]=\"field.value\" [fullWidth]=\"field.fullWidth === true\" />\n }\n </sce-info-fields-grid>\n }\n } @else {\n <div class=\"headerActions\">\n <h3 class=\"sectionTitle\">\n {{ 'dashboard.profile.editData' | translate }}\n </h3>\n </div>\n\n <div class=\"formContainer\" [attr.dir]=\"fieldDir()\">\n <div class=\"formField\">\n <sce-text-field\n id=\"profile-email\"\n type=\"email\"\n [dir]=\"fieldDir()\"\n [label]=\"'dashboard.profile.email' | translate\"\n [placeholder]=\"'dashboard.profile.emailPlaceholder' | translate\"\n [value]=\"editEmail()\"\n [required]=\"true\"\n validationMode=\"never\"\n [error]=\"emailError() || null\"\n (valueChange)=\"emailChange.emit($event)\"\n />\n </div>\n\n <div class=\"formField\">\n <sce-text-field\n id=\"profile-phone\"\n type=\"tel\"\n [dir]=\"fieldDir()\"\n [label]=\"'dashboard.profile.mobileNumber' | translate\"\n [placeholder]=\"'dashboard.profile.phonePlaceholder' | translate\"\n [value]=\"editPhone()\"\n [maxLength]=\"15\"\n [required]=\"true\"\n validationMode=\"never\"\n [error]=\"phoneError() || null\"\n (valueChange)=\"phoneChange.emit($event)\"\n />\n </div>\n\n <div class=\"formField fullRow\">\n <sce-text-field\n id=\"profile-short-national-address\"\n [dir]=\"fieldDir()\"\n [label]=\"'dashboard.profile.shortNationalAddress' | translate\"\n [placeholder]=\"'dashboard.profile.addressPlaceholder' | translate\"\n [value]=\"editAddress()\"\n [maxLength]=\"20\"\n [required]=\"true\"\n validationMode=\"never\"\n [error]=\"addressError() || null\"\n (valueChange)=\"addressChange.emit($event)\"\n />\n </div>\n\n <div class=\"formField fullRow\">\n <sce-select-field\n id=\"profile-bank\"\n [label]=\"'dashboard.profile.bank' | translate\"\n [placeholder]=\"'dashboard.profile.selectBank' | translate\"\n [options]=\"bankSelectOptions()\"\n [value]=\"bankSelectValue()\"\n [dir]=\"locale() === 'ar' ? 'rtl' : 'ltr'\"\n [filter]=\"true\"\n [showClear]=\"true\"\n [required]=\"true\"\n [borderless]=\"false\"\n validationMode=\"never\"\n inputClassName=\"profileBankSelect\"\n (valueChange)=\"onBankSelectChange($event)\"\n />\n </div>\n <div class=\"formField fullRow\">\n <sce-text-field\n id=\"profile-bank-account\"\n inputClassName=\"profileIbanInput\"\n [label]=\"'dashboard.profile.bankAccount' | translate\"\n [placeholder]=\"'dashboard.profile.bankAccountPlaceholder' | translate\"\n prefix=\"SA\"\n prefixMode=\"inline\"\n [value]=\"editBankAccount()\"\n [required]=\"true\"\n [maxLength]=\"22\"\n validationMode=\"never\"\n [error]=\"bankAccountError() || null\"\n (valueChange)=\"bankAccountChange.emit($event)\"\n />\n </div>\n </div>\n\n <div class=\"formActions fullRow\">\n <sce-button\n type=\"button\"\n variant=\"primary\"\n size=\"large\"\n [fullWidth]=\"false\"\n [disabled]=\"saving()\"\n [loading]=\"saving()\"\n (click)=\"saveClick.emit()\"\n >\n {{ saving() ? ('dashboard.profile.saving' | translate) : ('dashboard.profile.save' | translate) }}\n </sce-button>\n <sce-button type=\"button\" variant=\"outline\" size=\"large\" [fullWidth]=\"false\" [disabled]=\"saving()\" (click)=\"cancelClick.emit()\">\n {{ 'dashboard.profile.cancel' | translate }}\n </sce-button>\n </div>\n }\n }\n</section>\n", styles: ["@charset \"UTF-8\";.sce-profile-info-section{display:block;width:100%;min-width:0}.sce-profile-info-section>.card{display:flex;flex-direction:column;gap:var(--space-16);width:100%;min-width:0;box-sizing:border-box;overflow:hidden;padding:clamp(var(--space-16),4vi,var(--space-30));background:var(--app-surface);border-radius:var(--radius-brand-sm)}.sce-profile-info-section .cardHeader,.sce-profile-info-section .headerActions{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:var(--space-12)}.sce-profile-info-section .sectionTitle{margin:0;color:var(--text-text-primary-900);font-size:var(--font-size-lg-18);font-weight:var(--font-weight-bold);text-align:start}.sce-profile-info-section .cardHeader sce-button,.sce-profile-info-section .formActions sce-button{width:fit-content;max-width:100%}.sce-profile-info-section .formActions sce-button .btn{width:var(--size-179);min-width:var(--size-179);box-sizing:border-box}.sce-profile-info-section .fullRow{grid-column:1/-1}.sce-profile-info-section .formContainer{display:grid;grid-template-columns:1fr;gap:var(--space-20)}.sce-profile-info-section .formField{display:flex;flex-direction:column;gap:var(--space-6);min-width:0}.sce-profile-info-section .sce-field{gap:var(--space-6)}.sce-profile-info-section .sce-field__label{font-size:var(--font-size-md);font-weight:var(--font-weight-medium);color:var(--text-text-secondary-700)}.sce-profile-info-section .formContainer[dir=rtl] sce-text-field .p-inputtext.w-full,.sce-profile-info-section .formContainer[dir=ltr] sce-text-field .p-inputtext.w-full{width:100%;min-height:var(--size-52);box-sizing:border-box;padding-block:0;padding-inline:var(--space-16);font-size:var(--font-size-lg);background:var(--app-surface);border-radius:var(--radius-brand-sm)}.sce-profile-info-section .formContainer[dir=ltr] sce-text-field .p-inputtext.w-full{text-align:start}.sce-profile-info-section .formContainer[dir=rtl] sce-text-field .p-inputtext.w-full{direction:ltr;text-align:end}.sce-profile-info-section .formContainer sce-text-field .inlineContainer .inlineInput{font-size:var(--font-size-lg);color:var(--form-input-value-color)}.sce-profile-info-section .formContainer sce-text-field .inlineContainer .inlineInput::placeholder{color:var(--form-field-text-placeholder)}.sce-profile-info-section .root .profileBankSelect.p-select{min-height:var(--size-52);border-radius:var(--radius-brand-sm);background:var(--app-surface)}.sce-profile-info-section .root .profileBankSelect.p-select .p-select-label{display:flex;align-items:center;width:100%;min-height:var(--size-52);padding-block:0;padding-inline:var(--space-16);font-size:var(--font-size-lg);color:var(--text-text-primary-900)}.sce-profile-info-section .root .profileBankSelect.p-select .p-select-label.p-placeholder{color:var(--form-field-text-placeholder)}.sce-profile-info-section .formContainer[dir=rtl] .profileBankSelect.p-select .p-select-label{direction:ltr;justify-content:flex-end;text-align:end;padding-inline-start:var(--space-8);padding-inline-end:var(--space-16)}.sce-profile-info-section .formContainer[dir=ltr] .profileBankSelect.p-select .p-select-label{justify-content:flex-start;text-align:start}.sce-profile-info-section sce-button .btn{font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-semibold);border-radius:var(--radius-brand-sm);letter-spacing:normal}.sce-profile-info-section sce-button .btn--primary{background-color:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand)}.sce-profile-info-section sce-button .btn--outline{border:1.5px solid var(--color-brand-primary-900);color:var(--color-brand-primary-900);background:var(--background-bg-primary)}.sce-profile-info-section sce-button .btn--outline:hover:not(:disabled){background:var(--color-surface-2);border-color:var(--color-brand-primary-900);color:var(--color-brand-primary-900)}.sce-profile-info-section sce-button .btn--outline:active:not(:disabled){background:var(--color-surface-2);border-color:var(--color-brand-primary-900);color:var(--color-brand-primary-900)}.sce-profile-info-section .cardHeader sce-button .btn--medium{height:var(--space-48);padding-inline:var(--space-24);font-size:var(--font-size-md)}.sce-profile-info-section .formActions sce-button .btn--large{height:var(--size-56);padding-inline:var(--space-24);font-size:var(--font-size-lg)}.sce-profile-info-section .formActions{display:flex;gap:var(--space-12);padding-block-start:var(--space-16);direction:ltr}@media(min-width:768px){.sce-profile-info-section .formContainer{grid-template-columns:repeat(2,1fr)}.sce-profile-info-section .formField{grid-column:1/-1}.sce-profile-info-section .formField:nth-child(1),.sce-profile-info-section .formField:nth-child(2){grid-column:span 1}}@media(max-width:768px){.sce-profile-info-section .cardHeader,.sce-profile-info-section .headerActions{flex-direction:column;align-items:stretch}.sce-profile-info-section .cardHeader sce-button,.sce-profile-info-section .formActions sce-button{width:100%;min-width:0}.sce-profile-info-section .formActions sce-button .btn{width:100%;min-width:0}.sce-profile-info-section>.card{padding:var(--space-20)}.sce-profile-info-section .formActions{flex-direction:column;align-items:stretch}}@media(max-width:480px){.sce-profile-info-section>.card{padding:var(--space-16)}}\n"] }]
|
|
11823
12039
|
}], propDecorators: { profile: [{ type: i0.Input, args: [{ isSignal: true, alias: "profile", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], editing: [{ type: i0.Input, args: [{ isSignal: true, alias: "editing", required: false }] }], saving: [{ type: i0.Input, args: [{ isSignal: true, alias: "saving", required: false }] }], editEmail: [{ type: i0.Input, args: [{ isSignal: true, alias: "editEmail", required: false }] }], editPhone: [{ type: i0.Input, args: [{ isSignal: true, alias: "editPhone", required: false }] }], editAddress: [{ type: i0.Input, args: [{ isSignal: true, alias: "editAddress", required: false }] }], editBankId: [{ type: i0.Input, args: [{ isSignal: true, alias: "editBankId", required: false }] }], editBankAccount: [{ type: i0.Input, args: [{ isSignal: true, alias: "editBankAccount", required: false }] }], emailError: [{ type: i0.Input, args: [{ isSignal: true, alias: "emailError", required: false }] }], phoneError: [{ type: i0.Input, args: [{ isSignal: true, alias: "phoneError", required: false }] }], addressError: [{ type: i0.Input, args: [{ isSignal: true, alias: "addressError", required: false }] }], bankAccountError: [{ type: i0.Input, args: [{ isSignal: true, alias: "bankAccountError", required: false }] }], banks: [{ type: i0.Input, args: [{ isSignal: true, alias: "banks", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], editClick: [{ type: i0.Output, args: ["editClick"] }], cancelClick: [{ type: i0.Output, args: ["cancelClick"] }], saveClick: [{ type: i0.Output, args: ["saveClick"] }], emailChange: [{ type: i0.Output, args: ["emailChange"] }], phoneChange: [{ type: i0.Output, args: ["phoneChange"] }], addressChange: [{ type: i0.Output, args: ["addressChange"] }], bankIdChange: [{ type: i0.Output, args: ["bankIdChange"] }], bankAccountChange: [{ type: i0.Output, args: ["bankAccountChange"] }] } });
|
|
11824
12040
|
|
|
12041
|
+
/** Info-field grid summarising the entity's current contact and registration data on a data-change request; each unset field falls back to an em dash. */
|
|
11825
12042
|
class SceDataRequestCurrentSummaryComponent {
|
|
11826
12043
|
currentPhone = input('—', ...(ngDevMode ? [{ debugName: "currentPhone" }] : /* istanbul ignore next */ []));
|
|
11827
12044
|
currentEmail = input('—', ...(ngDevMode ? [{ debugName: "currentEmail" }] : /* istanbul ignore next */ []));
|
|
@@ -11836,6 +12053,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11836
12053
|
args: [{ selector: 'sce-data-request-current-summary', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: { class: 'sce-data-request-current-summary' }, imports: [TranslatePipe, SceInfoFieldCardComponent, SceInfoFieldsGridComponent], template: "<section class=\"comparisonSection\">\n <h2 class=\"comparisonSectionTitle\">\n {{ 'dashboard.dataRequests.details.sections.currentSummary' | translate }}\n </h2>\n <sce-info-fields-grid>\n <sce-info-field-card [label]=\"'dashboard.dataRequests.details.summary.phone' | translate\" [value]=\"currentPhone()\" />\n <sce-info-field-card [label]=\"'dashboard.dataRequests.details.summary.email' | translate\" [value]=\"currentEmail()\" />\n <sce-info-field-card [label]=\"'dashboard.dataRequests.details.summary.city' | translate\" [value]=\"currentCity()\" />\n <sce-info-field-card [label]=\"'dashboard.dataRequests.details.summary.unifiedNumber' | translate\" [value]=\"unifiedNumber()\" />\n <sce-info-field-card\n [label]=\"'dashboard.dataRequests.details.summary.vatRegistrationNumber' | translate\"\n [value]=\"currentVatNumber()\"\n />\n </sce-info-fields-grid>\n</section>\n", styles: [":host{display:block}\n"] }]
|
|
11837
12054
|
}], propDecorators: { currentPhone: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentPhone", required: false }] }], currentEmail: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentEmail", required: false }] }], currentCity: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentCity", required: false }] }], unifiedNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "unifiedNumber", required: false }] }], currentVatNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentVatNumber", required: false }] }] } });
|
|
11838
12055
|
|
|
12056
|
+
/** Lists the added, updated and removed portfolio projects in a data-change request, emitting the project and image index when a preview is clicked. */
|
|
11839
12057
|
class SceDataRequestProjectChangesComponent {
|
|
11840
12058
|
projectChanges = input([], ...(ngDevMode ? [{ debugName: "projectChanges" }] : /* istanbul ignore next */ []));
|
|
11841
12059
|
isSystemUser = input(false, ...(ngDevMode ? [{ debugName: "isSystemUser" }] : /* istanbul ignore next */ []));
|
|
@@ -11848,6 +12066,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11848
12066
|
args: [{ selector: 'sce-data-request-project-changes', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: { class: 'sce-data-request-project-changes' }, imports: [TranslatePipe], template: "@if (projectChanges().length > 0) {\n <section class=\"projectsChangesSection\">\n <div class=\"projectsChangesHeader\">\n <h2 class=\"projectsChangesTitle\">\n {{ 'dashboard.dataRequests.details.projectsChanges.title' | translate }}\n </h2>\n @if (!isSystemUser()) {\n <span class=\"projectsChangesCount\">\n {{ 'dashboard.dataRequests.details.projectsChanges.countLabel' | translate: { count: projectChanges().length } }}\n </span>\n }\n </div>\n\n @if (isSystemUser()) {\n @for (change of projectChanges(); track change.id) {\n <article class=\"projectChangeCard\">\n <header class=\"projectChangeCardHeader\">\n <div class=\"projectChangeTitleGroup\">\n <h3 class=\"projectChangeTitle\" [class.projectChangeTitleDeleted]=\"change.isRemoved\">{{ change.title }}</h3>\n @if (change.category !== '\u2014') {\n <span class=\"projectChangeCategoryTag\">{{ change.category }}</span>\n }\n </div>\n <span\n class=\"projectChangeBadge\"\n [class.projectChangeBadgeAdded]=\"change.type === 'added'\"\n [class.projectChangeBadgeUpdated]=\"change.type === 'updated'\"\n [class.projectChangeBadgeRemoved]=\"change.type === 'removed'\"\n >{{ change.badgeLabel }}</span\n >\n </header>\n\n <div class=\"projectChangeBody\">\n <div class=\"projectChangeDetails\">\n <div class=\"projectChangeDescriptionBlock\">\n <p class=\"projectChangeDescriptionLabel\">\n {{ 'dashboard.dataRequests.details.projectsChanges.description' | translate }}\n </p>\n <p class=\"projectChangeDescriptionText\">\n @if (change.descriptionChanged) {\n <span class=\"projectCompareValue\">\n <span class=\"projectCompareNew\">{{ change.nextDescription }}</span>\n <span class=\"projectCompareArrow\" aria-hidden=\"true\">\u2190</span>\n <span class=\"projectCompareOld\">{{ change.prevDescription }}</span>\n </span>\n } @else {\n {{ change.description }}\n }\n </p>\n </div>\n\n <div class=\"projectChangeMetrics\">\n @for (metric of change.metrics; track metric.key) {\n <div class=\"projectChangeMetric\" [class.projectChangeMetricChanged]=\"metric.changed\">\n <p class=\"projectChangeMetricLabel\">{{ metric.label }}</p>\n <p class=\"projectChangeMetricValue\">\n @if (metric.changed) {\n <span class=\"projectCompareValue\">\n <span class=\"projectCompareNew\">{{ metric.nextValue }}</span>\n <span class=\"projectCompareArrow\" aria-hidden=\"true\">\u2190</span>\n <span class=\"projectCompareOld\">{{ metric.currentValue }}</span>\n </span>\n } @else {\n {{ metric.nextValue }}\n }\n </p>\n </div>\n }\n </div>\n </div>\n\n @if (change.imageUrls.length > 0) {\n <div class=\"projectChangeGallery\">\n <button\n type=\"button\"\n class=\"projectChangeMainImage\"\n (click)=\"imageClick.emit({ change, index: 0 })\"\n [attr.aria-label]=\"'dashboard.dataRequests.details.projectsChanges.viewImages' | translate\"\n >\n <img [src]=\"change.imageUrls[0]\" [alt]=\"change.title\" class=\"projectChangeImage\" loading=\"lazy\" />\n </button>\n @if (change.imageUrls.length > 1) {\n <div class=\"projectChangeThumbRow\">\n <!-- track $index: fixed max-3 thumbnail slice, positions never reorder -->\n @for (thumbUrl of change.imageUrls.slice(1, 4); track $index) {\n <button\n type=\"button\"\n class=\"projectChangeThumb\"\n (click)=\"imageClick.emit({ change, index: $index + 1 })\"\n [attr.aria-label]=\"'dashboard.dataRequests.details.projectsChanges.viewImages' | translate\"\n >\n <img [src]=\"thumbUrl\" alt=\"\" class=\"projectChangeImage\" loading=\"lazy\" />\n </button>\n }\n </div>\n }\n </div>\n }\n </div>\n </article>\n }\n } @else {\n <div class=\"projectChangeCompactList\">\n @for (change of projectChanges(); track change.id) {\n <article class=\"projectChangeCompactRow\">\n <div class=\"projectChangeCompactMain\">\n @if (change.imageUrls.length > 0) {\n <button\n type=\"button\"\n class=\"projectChangeCompactThumb\"\n (click)=\"imageClick.emit({ change, index: 0 })\"\n [attr.aria-label]=\"'dashboard.dataRequests.details.projectsChanges.viewImages' | translate\"\n >\n <img [src]=\"change.imageUrls[0]\" alt=\"\" class=\"projectChangeImage\" loading=\"lazy\" />\n </button>\n }\n <div class=\"projectChangeCompactText\">\n <h3 class=\"projectChangeCompactTitle\" [class.projectChangeTitleDeleted]=\"change.isRemoved\">{{ change.title }}</h3>\n <p class=\"projectChangeCompactSubtitle\">{{ change.compactSubtitle || '\u2014' }}</p>\n </div>\n </div>\n <span\n class=\"projectChangeBadge\"\n [class.projectChangeBadgeAdded]=\"change.type === 'added'\"\n [class.projectChangeBadgeUpdated]=\"change.type === 'updated'\"\n [class.projectChangeBadgeRemoved]=\"change.type === 'removed'\"\n >{{ change.badgeLabel }}</span\n >\n </article>\n }\n </div>\n }\n </section>\n}\n", styles: [":host{display:block}\n"] }]
|
|
11849
12067
|
}], propDecorators: { projectChanges: [{ type: i0.Input, args: [{ isSignal: true, alias: "projectChanges", required: false }] }], isSystemUser: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSystemUser", required: false }] }], imageClick: [{ type: i0.Output, args: ["imageClick"] }] } });
|
|
11850
12068
|
|
|
12069
|
+
/** Grid of knowledge-center categories that also owns its loading, error and empty states and emits category/retry/ticket actions. */
|
|
11851
12070
|
class SceKnowledgeCenterCategoryGridComponent {
|
|
11852
12071
|
categories = input([], ...(ngDevMode ? [{ debugName: "categories" }] : /* istanbul ignore next */ []));
|
|
11853
12072
|
isLoadingCategories = input(false, ...(ngDevMode ? [{ debugName: "isLoadingCategories" }] : /* istanbul ignore next */ []));
|
|
@@ -11864,6 +12083,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11864
12083
|
args: [{ selector: 'sce-knowledge-center-category-grid', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: { class: 'sce-knowledge-center-category-grid' }, imports: [TranslatePipe, SceSkeleton, SceIcon, SceButton, SceApiErrorStateComponent, SceEmptyStateComponent], template: "<section class=\"kc-landing__browse\">\n <h2 class=\"kc-landing__section-title\">{{ 'knowledge.browseTitle' | translate }}</h2>\n\n @if (isLoadingCategories()) {\n <div class=\"kc-landing__grid\">\n @for (i of [0, 1, 2, 3]; track i) {\n <div class=\"kc-landing__skeleton-card\">\n <sce-skeleton variant=\"circular\" />\n <sce-skeleton variant=\"header\" width=\"75%\" />\n <sce-skeleton variant=\"paragraph\" [count]=\"2\" />\n </div>\n }\n </div>\n } @else if (categoriesError()) {\n <sce-api-error-state (retry)=\"retry.emit()\" />\n } @else if (!categories().length) {\n <sce-empty-state titleKey=\"knowledge.noCategories\" [compact]=\"true\" />\n } @else {\n <div class=\"kc-landing__grid\">\n @for (category of categories(); track category.slug) {\n <button\n class=\"kc-landing__category-card\"\n type=\"button\"\n [style.background-color]=\"category.background\"\n (click)=\"categoryClick.emit(category.slug)\"\n >\n <div class=\"kc-landing__category-icon\" aria-hidden=\"true\">\n <sce-icon [name]=\"category.icon\" [size]=\"32\" />\n </div>\n <h3 class=\"kc-landing__category-title\">{{ category.titleKey }}</h3>\n <p class=\"kc-landing__category-desc\">{{ category.descriptionKey }}</p>\n </button>\n }\n </div>\n\n <div class=\"kc-landing__support\">\n <div class=\"kc-landing__support-copy\">\n <h3 class=\"kc-landing__support-title\">{{ 'knowledge.supportTitle' | translate }}</h3>\n <p class=\"kc-landing__support-text\">{{ 'knowledge.supportSubtitle' | translate }}</p>\n </div>\n <div class=\"kc-landing__support-actions\">\n <sce-button variant=\"primary\" [fullWidth]=\"false\" (click)=\"newTicket.emit()\">\n {{ 'knowledge.newTicket' | translate }}\n </sce-button>\n <sce-button variant=\"outline\" [fullWidth]=\"false\" (click)=\"viewTickets.emit()\">\n {{ 'knowledge.viewTickets' | translate }}\n </sce-button>\n </div>\n </div>\n }\n</section>\n", styles: [":host{display:block}\n"] }]
|
|
11865
12084
|
}], propDecorators: { categories: [{ type: i0.Input, args: [{ isSignal: true, alias: "categories", required: false }] }], isLoadingCategories: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoadingCategories", required: false }] }], categoriesError: [{ type: i0.Input, args: [{ isSignal: true, alias: "categoriesError", required: false }] }], categoryClick: [{ type: i0.Output, args: ["categoryClick"] }], retry: [{ type: i0.Output, args: ["retry"] }], newTicket: [{ type: i0.Output, args: ["newTicket"] }], viewTickets: [{ type: i0.Output, args: ["viewTickets"] }] } });
|
|
11866
12085
|
|
|
12086
|
+
/** Read-only contact details panel rendering working hours, response time, phone number, email link and Instagram/Twitter links. */
|
|
11867
12087
|
class SceContactInfoPanelComponent {
|
|
11868
12088
|
workingHoursValue = input('', ...(ngDevMode ? [{ debugName: "workingHoursValue" }] : /* istanbul ignore next */ []));
|
|
11869
12089
|
responseValue = input('', ...(ngDevMode ? [{ debugName: "responseValue" }] : /* istanbul ignore next */ []));
|
|
@@ -11880,6 +12100,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11880
12100
|
args: [{ selector: 'sce-contact-info-panel', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: { class: 'sce-contact-info-panel' }, imports: [TranslatePipe, ScePhoneNumberComponent, SceBidiIsolate], template: "<aside class=\"contactInfoCol\">\n <div class=\"infoCard\">\n <h3 class=\"infoCardTitle\">{{ 'contact.contactInfo' | translate }}</h3>\n\n <div class=\"infoRow\">\n <div class=\"infoRowLabel\">\n <img src=\"/assets/icons/clock-03.svg\" alt=\"\" width=\"20\" height=\"20\" aria-hidden=\"true\" />\n <span>{{ 'contact.workingHours' | translate }}</span>\n </div>\n <p class=\"infoRowValue\">{{ workingHoursValue() }}</p>\n </div>\n\n <div class=\"infoRow\">\n <div class=\"infoRowLabel\">\n <img src=\"/assets/icons/message-incoming-01.svg\" alt=\"\" width=\"20\" height=\"20\" aria-hidden=\"true\" />\n <span>{{ 'contact.response' | translate }}</span>\n </div>\n <p class=\"infoRowValue\">{{ responseValue() }}</p>\n </div>\n\n <div class=\"infoRow\">\n <div class=\"infoRowLabel\">\n <img src=\"/assets/icons/calling.svg\" alt=\"\" width=\"20\" height=\"20\" aria-hidden=\"true\" />\n <span>{{ 'contact.phone.label' | translate }}</span>\n </div>\n <sce-phone-number class=\"infoRowValue\" [value]=\"phoneValue()\" [showCopy]=\"true\" [showIcon]=\"true\" />\n </div>\n </div>\n\n <div class=\"infoCard\">\n <h3 class=\"infoCardTitle\">{{ 'contact.additionalInfo' | translate }}</h3>\n\n <div class=\"infoRow infoRowEmail\">\n <p class=\"infoRowMuted\">{{ 'contact.email.label' | translate }}</p>\n <a class=\"infoRowLink\" [href]=\"emailHref()\">\n <sce-bidi-isolate [value]=\"emailValue()\" />\n </a>\n </div>\n\n <div class=\"infoRow infoRowSocial\">\n <p class=\"infoRowMuted\">{{ 'contact.social.label' | translate }}</p>\n <div class=\"socialLinks\" dir=\"ltr\">\n <a [href]=\"socialInstagramHref()\" target=\"_blank\" rel=\"noopener noreferrer\" aria-label=\"Instagram\">\n <img src=\"/assets/icons/black-instagram.svg\" alt=\"\" width=\"24\" height=\"24\" />\n </a>\n <a [href]=\"socialTwitterHref()\" target=\"_blank\" rel=\"noopener noreferrer\" aria-label=\"X\" class=\"socialLinkTwitter\">\n <span class=\"iconTwitter\"></span>\n </a>\n </div>\n </div>\n </div>\n</aside>\n", styles: [":host{display:contents}\n"] }]
|
|
11881
12101
|
}], propDecorators: { workingHoursValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "workingHoursValue", required: false }] }], responseValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "responseValue", required: false }] }], phoneValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "phoneValue", required: false }] }], emailHref: [{ type: i0.Input, args: [{ isSignal: true, alias: "emailHref", required: false }] }], emailValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "emailValue", required: false }] }], socialInstagramHref: [{ type: i0.Input, args: [{ isSignal: true, alias: "socialInstagramHref", required: false }] }], socialTwitterHref: [{ type: i0.Input, args: [{ isSignal: true, alias: "socialTwitterHref", required: false }] }] } });
|
|
11882
12102
|
|
|
12103
|
+
/** Fully-controlled contact form panel with name, email, message-type and message fields plus a hidden `website` honeypot; it holds no state of its own — every value, error and loading flag is an input and every change is an output. */
|
|
11883
12104
|
class SceContactFormPanelComponent {
|
|
11884
12105
|
dir = input('rtl', ...(ngDevMode ? [{ debugName: "dir" }] : /* istanbul ignore next */ []));
|
|
11885
12106
|
fullName = input.required(...(ngDevMode ? [{ debugName: "fullName" }] : /* istanbul ignore next */ []));
|
|
@@ -11919,6 +12140,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11919
12140
|
args: [{ selector: 'sce-contact-form-panel', standalone: true, imports: [TranslatePipe, SceTextFieldComponent, SceTextareaFieldComponent, SceSelectFieldComponent, SceSkeleton], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-contact-form-panel' }, template: "<form class=\"sce-contact-form-panel__form\" [attr.dir]=\"dir()\" (submit)=\"formSubmit.emit($event)\">\n <header class=\"sce-contact-form-panel__header\">\n <h2 class=\"sce-contact-form-panel__title\">{{ 'contact.title' | translate }}</h2>\n <p class=\"sce-contact-form-panel__subtitle\">{{ 'contact.subtitle' | translate }}</p>\n </header>\n\n @if (submitSuccess()) {\n <p class=\"sce-contact-form-panel__feedback sce-contact-form-panel__feedback--success\" role=\"status\">\n {{ 'contact.form.success' | translate }}\n </p>\n }\n @if (submitError()) {\n <p class=\"sce-contact-form-panel__feedback sce-contact-form-panel__feedback--error\" role=\"alert\">\n {{ submitError() }}\n </p>\n }\n @if (!messageTypesLoading() && messageTypeUnavailable()) {\n <p class=\"sce-contact-form-panel__feedback sce-contact-form-panel__feedback--error\" role=\"status\">\n {{ 'contact.form.messageTypeUnavailable' | translate }}\n </p>\n }\n\n <input\n type=\"text\"\n class=\"sce-contact-form-panel__honeypot\"\n tabindex=\"-1\"\n autocomplete=\"off\"\n aria-hidden=\"true\"\n [value]=\"website()\"\n (input)=\"websiteChange.emit($any($event.target).value)\"\n />\n\n <div class=\"sce-contact-form-panel__fields\">\n <div class=\"sce-contact-form-panel__input\">\n <sce-text-field\n id=\"contact-full-name\"\n [label]=\"'contact.form.fullName' | translate\"\n [value]=\"fullName()\"\n (valueChange)=\"fullNameChange.emit($event)\"\n [placeholder]=\"'contact.form.fullNamePlaceholder' | translate\"\n [required]=\"true\"\n validationMode=\"onTouched\"\n [validationMessages]=\"fullNameValidationMessages()\"\n [error]=\"fullNameError()\"\n />\n </div>\n <div class=\"sce-contact-form-panel__input\">\n <sce-text-field\n id=\"contact-email\"\n [label]=\"'contact.form.email' | translate\"\n type=\"email\"\n [value]=\"email()\"\n (valueChange)=\"emailChange.emit($event)\"\n [placeholder]=\"'contact.form.emailPlaceholder' | translate\"\n [required]=\"true\"\n validationMode=\"onTouched\"\n [pattern]=\"emailPattern() ?? null\"\n [validationMessages]=\"emailValidationMessages()\"\n [error]=\"emailError()\"\n />\n </div>\n <div class=\"sce-contact-form-panel__select\">\n @if (messageTypesLoading()) {\n <div class=\"sce-contact-form-panel__input\">\n <sce-skeleton variant=\"text\" width=\"35%\" height=\"0.875rem\" animation=\"wave\" />\n <sce-skeleton variant=\"input\" animation=\"wave\" />\n </div>\n } @else {\n <sce-select-field\n id=\"contact-message-type\"\n [label]=\"'contact.form.messageType' | translate\"\n [options]=\"messageTypeOptions()\"\n [value]=\"messageType()\"\n (valueChange)=\"messageTypeChange.emit($event)\"\n [placeholder]=\"messageTypePlaceholder()\"\n [dir]=\"dir()\"\n [required]=\"true\"\n [borderless]=\"false\"\n [validationMessages]=\"messageTypeValidationMessages()\"\n [error]=\"messageTypeError()\"\n />\n }\n </div>\n <div class=\"sce-contact-form-panel__textarea\">\n <sce-textarea-field\n id=\"contact-message\"\n [label]=\"'contact.form.message' | translate\"\n [value]=\"message()\"\n (valueChange)=\"messageChange.emit($event)\"\n [placeholder]=\"'contact.form.messagePlaceholder' | translate\"\n [rows]=\"5\"\n [required]=\"true\"\n validationMode=\"onTouched\"\n [validationMessages]=\"messageValidationMessages()\"\n [error]=\"messageError()\"\n />\n </div>\n </div>\n\n <button type=\"submit\" class=\"sce-contact-form-panel__submit\" [disabled]=\"isSubmitDisabled()\">\n {{ submitLabel() }}\n </button>\n</form>\n", styles: [":host.sce-contact-form-panel{display:block}.sce-contact-form-panel__form{display:grid;gap:var(--space-24);background:var(--background-bg-primary);border-radius:var(--radius-2xl, var(--radius-2xl));padding:var(--space-30);height:100%}.sce-contact-form-panel__header{display:grid;gap:var(--space-8);text-align:start}.sce-contact-form-panel__title{margin:0;font-family:var(--font-family-arabic-primary);font-weight:700;font-size:var(--font-size-2xl, var(--font-size-24));line-height:1.35;color:var(--text-primary-emphasis)}.sce-contact-form-panel__subtitle{margin:0;font-family:var(--font-family-arabic-primary);font-weight:400;font-size:var(--font-size-md);line-height:1.6;color:var(--text-text-secondary)}.sce-contact-form-panel__feedback{margin:0;padding:var(--space-10) var(--space-14);border-radius:var(--radius-lg, var(--radius-lg));font-size:var(--font-size-sm);font-weight:var(--font-weight-medium)}.sce-contact-form-panel__feedback--success{background:var(--color-success-100);color:var(--color-success-700)}.sce-contact-form-panel__feedback--error{background:var(--color-error-50);color:var(--color-error-600)}.sce-contact-form-panel__honeypot{position:absolute;inset-inline-start:-9999px;opacity:0;pointer-events:none;tab-size:-1}.sce-contact-form-panel__fields{display:grid;gap:var(--space-20)}.sce-contact-form-panel__input,.sce-contact-form-panel__select,.sce-contact-form-panel__textarea{width:100%;min-width:0}.sce-contact-form-panel__submit{min-height:var(--size-52);border-radius:var(--radius-xl);border:0;background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand);font-size:var(--font-size-md);font-weight:var(--font-weight-semibold);cursor:pointer;transition:opacity .15s ease}.sce-contact-form-panel__submit:disabled{opacity:.55;cursor:not-allowed}\n"] }]
|
|
11920
12141
|
}], propDecorators: { dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], fullName: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullName", required: true }] }], email: [{ type: i0.Input, args: [{ isSignal: true, alias: "email", required: true }] }], messageType: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageType", required: true }] }], message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }], website: [{ type: i0.Input, args: [{ isSignal: true, alias: "website", required: false }] }], submitSuccess: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitSuccess", required: false }] }], submitError: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitError", required: false }] }], isSubmitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSubmitting", required: false }] }], isSubmitDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSubmitDisabled", required: false }] }], submitLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitLabel", required: true }] }], messageTypesLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageTypesLoading", required: false }] }], messageTypeUnavailable: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageTypeUnavailable", required: false }] }], messageTypeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageTypeOptions", required: false }] }], messageTypePlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageTypePlaceholder", required: false }] }], fullNameError: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullNameError", required: false }] }], emailError: [{ type: i0.Input, args: [{ isSignal: true, alias: "emailError", required: false }] }], messageTypeError: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageTypeError", required: false }] }], messageError: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageError", required: false }] }], emailPattern: [{ type: i0.Input, args: [{ isSignal: true, alias: "emailPattern", required: false }] }], fullNameValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullNameValidationMessages", required: false }] }], emailValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "emailValidationMessages", required: false }] }], messageTypeValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageTypeValidationMessages", required: false }] }], messageValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageValidationMessages", required: false }] }], fullNameChange: [{ type: i0.Output, args: ["fullNameChange"] }], emailChange: [{ type: i0.Output, args: ["emailChange"] }], messageTypeChange: [{ type: i0.Output, args: ["messageTypeChange"] }], messageChange: [{ type: i0.Output, args: ["messageChange"] }], websiteChange: [{ type: i0.Output, args: ["websiteChange"] }], formSubmit: [{ type: i0.Output, args: ["formSubmit"] }] } });
|
|
11921
12142
|
|
|
12143
|
+
/** Renders the platform settings list as read-only info cards or editable controls, emitting a typed update per field kind (boolean, integer, force-majeure durations). */
|
|
11922
12144
|
class ScePlatformSettingsFieldsComponent {
|
|
11923
12145
|
viewFields = input.required(...(ngDevMode ? [{ debugName: "viewFields" }] : /* istanbul ignore next */ []));
|
|
11924
12146
|
isEditMode = input(false, ...(ngDevMode ? [{ debugName: "isEditMode" }] : /* istanbul ignore next */ []));
|
|
@@ -11937,6 +12159,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11937
12159
|
args: [{ selector: 'sce-platform-settings-fields', standalone: true, imports: [TranslatePipe, SceInfoFieldCardComponent, SceInfoFieldsGridComponent, SceSwitchComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-platform-settings-fields' }, template: "<sce-info-fields-grid>\n @for (field of viewFields(); track field.apiKey) {\n @if (field.type === 'forceMajeureDurations') {\n <div class=\"ps-fields__fm-card\">\n <p class=\"ps-fields__fm-label\">{{ field.label }}</p>\n\n <div class=\"ps-fields__fm-group\">\n <p class=\"ps-fields__fm-group-title\">\n {{ 'dashboard.platformSettings.forceMajeure.notificationDays' | translate }}\n </p>\n <div class=\"ps-fields__fm-input-grid\">\n <div class=\"ps-fields__fm-input-row\">\n <label class=\"ps-fields__fm-input-label\" [for]=\"field.apiKey + '-nd-general'\">\n {{ 'dashboard.platformSettings.forceMajeure.general' | translate }}\n </label>\n @if (isEditMode()) {\n <input\n class=\"ps-fields__num-input\"\n type=\"text\"\n inputmode=\"numeric\"\n [id]=\"field.apiKey + '-nd-general'\"\n [value]=\"field.value.notificationDays.general\"\n [disabled]=\"saving()\"\n (input)=\"\n forceMajeureNotificationUpdate.emit({ apiKey: field.apiKey, sub: 'general', rawInput: $any($event.target).value })\n \"\n />\n } @else {\n <span class=\"ps-fields__fm-value\">{{ field.value.notificationDays.general }}</span>\n }\n </div>\n <div class=\"ps-fields__fm-input-row\">\n <label class=\"ps-fields__fm-input-label\" [for]=\"field.apiKey + '-nd-supervision'\">\n {{ 'dashboard.platformSettings.forceMajeure.supervision' | translate }}\n </label>\n @if (isEditMode()) {\n <input\n class=\"ps-fields__num-input\"\n type=\"text\"\n inputmode=\"numeric\"\n [id]=\"field.apiKey + '-nd-supervision'\"\n [value]=\"field.value.notificationDays.supervision\"\n [disabled]=\"saving()\"\n (input)=\"\n forceMajeureNotificationUpdate.emit({ apiKey: field.apiKey, sub: 'supervision', rawInput: $any($event.target).value })\n \"\n />\n } @else {\n <span class=\"ps-fields__fm-value\">{{ field.value.notificationDays.supervision }}</span>\n }\n </div>\n <div class=\"ps-fields__fm-input-row\">\n <label class=\"ps-fields__fm-input-label\" [for]=\"field.apiKey + '-nd-consultancy'\">\n {{ 'dashboard.platformSettings.forceMajeure.consultancy' | translate }}\n </label>\n @if (isEditMode()) {\n <input\n class=\"ps-fields__num-input\"\n type=\"text\"\n inputmode=\"numeric\"\n [id]=\"field.apiKey + '-nd-consultancy'\"\n [value]=\"field.value.notificationDays.consultancy\"\n [disabled]=\"saving()\"\n (input)=\"\n forceMajeureNotificationUpdate.emit({ apiKey: field.apiKey, sub: 'consultancy', rawInput: $any($event.target).value })\n \"\n />\n } @else {\n <span class=\"ps-fields__fm-value\">{{ field.value.notificationDays.consultancy }}</span>\n }\n </div>\n </div>\n </div>\n\n <div class=\"ps-fields__fm-group\">\n <p class=\"ps-fields__fm-group-title\">\n {{ 'dashboard.platformSettings.forceMajeure.extensionDays' | translate }}\n </p>\n <div class=\"ps-fields__fm-input-grid\">\n <div class=\"ps-fields__fm-input-row\">\n <label class=\"ps-fields__fm-input-label\" [for]=\"field.apiKey + '-ed-general'\">\n {{ 'dashboard.platformSettings.forceMajeure.general' | translate }}\n </label>\n @if (isEditMode()) {\n <input\n class=\"ps-fields__num-input\"\n type=\"text\"\n inputmode=\"numeric\"\n [id]=\"field.apiKey + '-ed-general'\"\n [value]=\"field.value.extensionDays.general\"\n [disabled]=\"saving()\"\n (input)=\"forceMajeureExtensionUpdate.emit({ apiKey: field.apiKey, sub: 'general', rawInput: $any($event.target).value })\"\n />\n } @else {\n <span class=\"ps-fields__fm-value\">{{ field.value.extensionDays.general }}</span>\n }\n </div>\n <div class=\"ps-fields__fm-input-row\">\n <label class=\"ps-fields__fm-input-label\" [for]=\"field.apiKey + '-ed-consultancy'\">\n {{ 'dashboard.platformSettings.forceMajeure.consultancy' | translate }}\n </label>\n @if (isEditMode()) {\n <input\n class=\"ps-fields__num-input\"\n type=\"text\"\n inputmode=\"numeric\"\n [id]=\"field.apiKey + '-ed-consultancy'\"\n [value]=\"field.value.extensionDays.consultancy\"\n [disabled]=\"saving()\"\n (input)=\"\n forceMajeureExtensionUpdate.emit({ apiKey: field.apiKey, sub: 'consultancy', rawInput: $any($event.target).value })\n \"\n />\n } @else {\n <span class=\"ps-fields__fm-value\">{{ field.value.extensionDays.consultancy }}</span>\n }\n </div>\n </div>\n </div>\n </div>\n } @else if (field.type === 'boolean') {\n <sce-info-field-card [label]=\"field.label\">\n <sce-switch\n [checked]=\"field.value\"\n [showLabel]=\"true\"\n [activeLabel]=\"'dashboard.status.active' | translate\"\n [inactiveLabel]=\"'dashboard.status.inactive' | translate\"\n [disabled]=\"!isEditMode() || saving()\"\n (checkedChange)=\"booleanUpdate.emit({ apiKey: field.apiKey, value: $event })\"\n />\n </sce-info-field-card>\n } @else {\n @if (isEditMode()) {\n <div class=\"ps-fields__int-field\">\n <label class=\"ps-fields__int-label\" [for]=\"'ps-' + field.apiKey\">{{ field.label }}</label>\n <input\n class=\"ps-fields__num-input\"\n type=\"text\"\n inputmode=\"numeric\"\n [id]=\"'ps-' + field.apiKey\"\n [value]=\"field.value\"\n [disabled]=\"saving()\"\n (input)=\"integerUpdate.emit({ apiKey: field.apiKey, rawInput: $any($event.target).value })\"\n />\n </div>\n } @else {\n <sce-info-field-card [label]=\"field.label\" [value]=\"'' + field.value\" />\n }\n }\n }\n</sce-info-fields-grid>\n\n@if (isEditMode()) {\n <div class=\"ps-fields__actions-row\">\n <button type=\"button\" class=\"ps-fields__btn ps-fields__btn--secondary\" [disabled]=\"saving()\" (click)=\"editCancel.emit()\">\n {{ 'dashboard.platformSettings.actions.cancel' | translate }}\n </button>\n <button type=\"button\" class=\"ps-fields__btn ps-fields__btn--primary\" [disabled]=\"saving()\" (click)=\"editSave.emit()\">\n {{ 'dashboard.platformSettings.actions.save' | translate }}\n </button>\n </div>\n}\n", styles: [".ps-fields__fm-card{grid-column:1/-1;display:grid;gap:var(--space-3);padding:var(--space-4);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl);background:var(--surface-primary)}.ps-fields__fm-label{margin:0;color:var(--text-text-primary-900);font-size:var(--font-size-lg);font-weight:600}.ps-fields__fm-group{padding:var(--space-3);border:1px solid var(--color-neutral-100);border-radius:var(--radius-10);display:grid;gap:var(--space-3)}.ps-fields__fm-group-title{margin:0;color:var(--text-text-secondary-700);font-size:var(--font-size-md);font-weight:600}.ps-fields__fm-input-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:var(--space-3)}.ps-fields__fm-input-row{display:grid;gap:var(--space-1)}.ps-fields__fm-input-label{color:var(--color-neutral-700);font-size:var(--font-size-sm);font-weight:500}.ps-fields__fm-value{color:var(--details-value-color);font-size:var(--font-size-md);font-weight:600}.ps-fields__int-field{display:grid;gap:var(--space-1)}.ps-fields__int-label{color:var(--color-neutral-700);font-size:.85rem;font-weight:600}.ps-fields__num-input{height:var(--space-48);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl);padding:0 var(--space-14, var(--space-14));font-family:var(--font-family-arabic-primary);font-size:var(--font-size-md);color:var(--details-value-color);outline:0;background:var(--surface-primary);width:100%;box-sizing:border-box}.ps-fields__num-input:disabled{opacity:.6;cursor:not-allowed}.ps-fields__actions-row{display:flex;align-items:center;gap:var(--space-10);flex-wrap:wrap}.ps-fields__btn{min-height:var(--space-48);border-radius:var(--radius-xl);padding:var(--space-8) var(--space-24);font-size:var(--font-size-md-15);font-weight:var(--font-weight-semibold);cursor:pointer}.ps-fields__btn:disabled{opacity:.55;cursor:not-allowed}.ps-fields__btn--primary{border:0;background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand)}.ps-fields__btn--secondary{border:1px solid var(--button-background-primary-bg-primary);background:transparent;color:var(--button-background-primary-bg-primary)}\n"] }]
|
|
11938
12160
|
}], propDecorators: { viewFields: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewFields", required: true }] }], isEditMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEditMode", required: false }] }], saving: [{ type: i0.Input, args: [{ isSignal: true, alias: "saving", required: false }] }], booleanUpdate: [{ type: i0.Output, args: ["booleanUpdate"] }], integerUpdate: [{ type: i0.Output, args: ["integerUpdate"] }], forceMajeureNotificationUpdate: [{ type: i0.Output, args: ["forceMajeureNotificationUpdate"] }], forceMajeureExtensionUpdate: [{ type: i0.Output, args: ["forceMajeureExtensionUpdate"] }], editCancel: [{ type: i0.Output, args: ["editCancel"] }], editSave: [{ type: i0.Output, args: ["editSave"] }] } });
|
|
11939
12161
|
|
|
12162
|
+
/** Presentational entity-profile edit form bound to a caller-owned `FormGroup`; it holds no form state of its own and re-emits each field's raw input `Event` for the host to handle. */
|
|
11940
12163
|
class SceEntityProfileEditFormComponent {
|
|
11941
12164
|
form = input.required(...(ngDevMode ? [{ debugName: "form" }] : /* istanbul ignore next */ []));
|
|
11942
12165
|
dir = input('rtl', ...(ngDevMode ? [{ debugName: "dir" }] : /* istanbul ignore next */ []));
|
|
@@ -11971,6 +12194,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11971
12194
|
], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-entity-profile-edit-form' }, template: "<section class=\"card\">\n <h3 class=\"sectionTitle\">\n {{ 'dashboard.entityProfile.entityData' | translate }}\n </h3>\n\n <form class=\"formContainer\" [formGroup]=\"form()\" (ngSubmit)=\"formSubmit.emit()\">\n <div class=\"formField\">\n <span class=\"formLabel\">{{ 'dashboard.entityProfile.entityName' | translate }}</span>\n <div class=\"formInputReadonly\">{{ entityName() || '\u2014' }}</div>\n </div>\n\n <div class=\"formField\">\n <span class=\"formLabel\">{{ 'dashboard.entityProfile.unifiedNumber' | translate }}</span>\n <div class=\"formInputReadonly\">{{ unifiedNumber() || '\u2014' }}</div>\n </div>\n\n <div class=\"formField\">\n <span class=\"formLabel\">{{ 'dashboard.entityProfile.entityType' | translate }}</span>\n <div class=\"formInputReadonly\">{{ entityType() || '\u2014' }}</div>\n </div>\n\n <div class=\"formField\">\n <sce-form-input\n label=\"{{ 'dashboard.entityProfile.mobileNumber' | translate }}\"\n type=\"phone\"\n formControlName=\"phone\"\n [required]=\"true\"\n [errorMessages]=\"{ pattern: 'dashboard.entityProfile.errors.phoneSaudiFormat' }\"\n (input)=\"phoneInput.emit($event)\"\n ></sce-form-input>\n </div>\n\n <div class=\"formField\">\n <sce-form-input\n label=\"{{ 'dashboard.entityProfile.email' | translate }}\"\n type=\"email\"\n formControlName=\"email\"\n [required]=\"true\"\n ></sce-form-input>\n </div>\n\n <div class=\"formField\">\n <sce-form-input\n label=\"{{ 'dashboard.entityProfile.licenseNumber' | translate }}\"\n type=\"number\"\n formControlName=\"licenseNumber\"\n [placeholder]=\"'dashboard.entityProfileEdit.licensePlaceholder' | translate\"\n [errorMessages]=\"{ pattern: 'dashboard.entityProfile.errors.licenseFormat' }\"\n (input)=\"licenseInput.emit($event)\"\n ></sce-form-input>\n </div>\n\n <div class=\"formField\">\n <sce-form-input\n label=\"{{ 'dashboard.entityProfile.taxRegistrationNumber' | translate }}\"\n type=\"number\"\n formControlName=\"taxRegistrationNumber\"\n [required]=\"true\"\n [placeholder]=\"'dashboard.entityProfileEdit.taxPlaceholder' | translate\"\n [errorMessages]=\"{ pattern: 'dashboard.entityProfile.errors.vatFormat' }\"\n (input)=\"taxInput.emit($event)\"\n ></sce-form-input>\n </div>\n\n <div class=\"formField\">\n <sce-form-input\n label=\"{{ 'dashboard.entityProfile.shortNationalAddress' | translate }}\"\n type=\"text\"\n formControlName=\"shortNationalAddress\"\n [required]=\"true\"\n [placeholder]=\"'dashboard.entityProfileEdit.addressPlaceholder' | translate\"\n [maxLengthOverride]=\"8\"\n [errorMessages]=\"{ pattern: 'dashboard.entityProfile.errors.addressFormat' }\"\n (input)=\"addressInput.emit($event)\"\n ></sce-form-input>\n </div>\n\n <div class=\"formField\">\n <sce-select-field\n id=\"bank\"\n [label]=\"'dashboard.entityProfile.bank' | translate\"\n [options]=\"bankOptions()\"\n [value]=\"selectedBankId()\"\n [dir]=\"dir()\"\n [filter]=\"true\"\n [showClear]=\"true\"\n [required]=\"true\"\n [error]=\"bankError()\"\n [validationMode]=\"'never'\"\n [placeholder]=\"'dashboard.entityProfileEdit.bankPlaceholder' | translate\"\n (valueChange)=\"bankChange.emit($event)\"\n />\n </div>\n\n <div class=\"formField\">\n <sce-form-input\n label=\"{{ 'dashboard.entityProfile.bankAccount' | translate }}\"\n type=\"text\"\n formControlName=\"bankAccount\"\n [required]=\"true\"\n [placeholder]=\"'dashboard.entityProfileEdit.bankAccountPlaceholder' | translate\"\n [maxLengthOverride]=\"22\"\n [inlineSuffix]=\"'SA'\"\n [errorMessages]=\"{ invalidIban: 'dashboard.entityProfile.errors.ibanFormat' }\"\n (input)=\"ibanInput.emit($event)\"\n ></sce-form-input>\n </div>\n\n <div class=\"formActions\">\n <sce-button type=\"submit\" variant=\"primary\" size=\"large\" [disabled]=\"submitting()\" [loading]=\"submitting()\">\n {{ 'dashboard.entityProfileEdit.updateData' | translate }}\n </sce-button>\n <sce-button routerLink=\"/dashboard/entity-profile\" variant=\"outline\" size=\"large\">\n {{ 'common.cancel' | translate }}\n </sce-button>\n </div>\n </form>\n</section>\n", styles: [".card{background:var(--app-surface);border-radius:var(--radius-brand-sm);padding:clamp(1rem,4vi,var(--space-30));display:flex;flex-direction:column;gap:var(--space-16);width:100%;min-width:0;box-sizing:border-box;overflow:hidden}.sectionTitle{color:var(--color-violet-800);font-size:var(--space-20);font-weight:var(--font-weight-bold)}.formContainer{display:grid;grid-template-columns:1fr;gap:var(--space-20)}.formField{display:flex;flex-direction:column;gap:var(--space-8)}.formLabel{color:var(--details-label-color);font-size:var(--font-size-md);font-weight:var(--font-weight-medium)}.formRequired{color:var(--color-red-600);margin-inline-start:var(--space-1)}.formInput,.formInputReadonly{width:100%;min-height:var(--space-52, var(--size-52));border-radius:var(--radius-xl);font-size:var(--font-size-lg);color:var(--text-text-disabled);font-family:var(--font-family-arabic-primary);transition:border-color .2s}.formInput{border:1px solid var(--color-neutral-200);background:var(--background-bg-primary);padding:0 1rem}.formInput:focus{outline:none;border-color:var(--button-background-primary-bg-primary)}.formInputWithPrefix{position:relative;display:flex;align-items:center;width:100%}.formInputPrefix{position:absolute;inset-inline-start:var(--space-4);top:50%;transform:translateY(-50%);color:var(--color-muted-fg);-webkit-user-select:none;user-select:none;pointer-events:none;z-index:1}.formInput--prefixed{padding-inline-start:calc(var(--space-4) + var(--space-24))}.formInputReadonly{display:flex;align-items:center;box-sizing:border-box;border:1px solid var(--color-neutral-200);background:var(--details-row-bg);color:var(--details-value-color);cursor:default;padding:0 1rem}.inputError{border-color:var(--color-red-600)}.inputError:focus{border-color:var(--color-red-600)}.errorText{color:var(--color-red-600);font-size:var(--font-size-xs);margin-block-start:var(--space-4)}.formActions{display:flex;gap:var(--space-12);direction:ltr}.primaryButton,.secondaryButton{min-width:var(--size-200);height:var(--space-52, var(--size-52));border-radius:var(--radius-xl);font-weight:var(--font-weight-semibold);text-decoration:none;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;font-size:var(--font-size-lg)}.primaryButton{border:0;background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand)}.primaryButton:disabled{opacity:.7;cursor:not-allowed}.secondaryButton{border:1px solid var(--button-background-primary-bg-primary);color:var(--button-background-primary-bg-primary);background:transparent}@media(max-width:768px){.formActions{flex-direction:column;align-items:stretch}.primaryButton,.secondaryButton{width:100%;min-width:0;box-sizing:border-box}}\n"] }]
|
|
11972
12195
|
}], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], entityName: [{ type: i0.Input, args: [{ isSignal: true, alias: "entityName", required: false }] }], entityType: [{ type: i0.Input, args: [{ isSignal: true, alias: "entityType", required: false }] }], unifiedNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "unifiedNumber", required: false }] }], bankOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "bankOptions", required: false }] }], selectedBankId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedBankId", required: false }] }], bankError: [{ type: i0.Input, args: [{ isSignal: true, alias: "bankError", required: false }] }], submitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitting", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], phoneInput: [{ type: i0.Output, args: ["phoneInput"] }], licenseInput: [{ type: i0.Output, args: ["licenseInput"] }], taxInput: [{ type: i0.Output, args: ["taxInput"] }], addressInput: [{ type: i0.Output, args: ["addressInput"] }], ibanInput: [{ type: i0.Output, args: ["ibanInput"] }], bankChange: [{ type: i0.Output, args: ["bankChange"] }], formSubmit: [{ type: i0.Output, args: ["formSubmit"] }] } });
|
|
11973
12196
|
|
|
12197
|
+
/** Title bar with account-users / engineering-staff tabs and an optional Add button (`showAddButton`, off by default); it emits clicks and never switches `activeTab` itself. */
|
|
11974
12198
|
class SceAccountUsersTabsBarComponent {
|
|
11975
12199
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
11976
12200
|
activeTab = input.required(...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
|
|
@@ -11986,6 +12210,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11986
12210
|
args: [{ selector: 'sce-account-users-tabs-bar', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-account-users-tabs-bar' }, template: "<div class=\"sce-account-users-tabs-bar__header\">\n <h2 class=\"sce-account-users-tabs-bar__title\">{{ title() }}</h2>\n @if (showAddButton() && activeTab() === 'account-users') {\n <button class=\"sce-account-users-tabs-bar__add-btn\" type=\"button\" (click)=\"addUserClick.emit()\">\n {{ 'dashboard.users.addUser' | translate }}\n </button>\n }\n</div>\n\n<div class=\"sce-account-users-tabs-bar__tabs\">\n <div>\n <button\n class=\"sce-account-users-tabs-bar__tab-btn\"\n [class.sce-account-users-tabs-bar__tab-btn--active]=\"activeTab() === 'account-users'\"\n type=\"button\"\n (click)=\"accountUsersTabClick.emit()\"\n >\n {{ 'dashboard.accountUsers.tabs.accountUsers' | translate }}\n </button>\n <button\n class=\"sce-account-users-tabs-bar__tab-btn\"\n [class.sce-account-users-tabs-bar__tab-btn--active]=\"activeTab() === 'engineering-staff'\"\n type=\"button\"\n (click)=\"staffTabClick.emit()\"\n >\n {{ 'dashboard.accountUsers.tabs.engineeringStaff' | translate }}\n </button>\n </div>\n @if (activeTab() === 'engineering-staff') {\n <p class=\"sce-account-users-tabs-bar__hint\">\n {{ 'dashboard.accountUsers.engineeringStaff.staffHint' | translate }}\n </p>\n }\n</div>\n", styles: [":host.sce-account-users-tabs-bar{display:block}.sce-account-users-tabs-bar__header{display:flex;align-items:center;justify-content:space-between;gap:var(--space-4);margin-block-end:var(--space-4)}.sce-account-users-tabs-bar__title{font-size:var(--font-size-xl);font-weight:500;color:var(--text-text-display);margin:0}.sce-account-users-tabs-bar__add-btn{border:0;border-radius:var(--radius-md);padding:var(--space-12) var(--space-24);display:inline-flex;align-items:center;justify-content:center;gap:var(--space-4);background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand);font-size:var(--font-size-md);font-weight:var(--font-weight-semibold);cursor:pointer}.sce-account-users-tabs-bar__tabs{display:flex;gap:0;border-block-end:1px solid var(--color-neutral-200);margin-block-end:var(--space-20);justify-content:space-between;align-items:center}.sce-account-users-tabs-bar__tab-btn{padding:var(--space-10) var(--space-24);border:0;border-block-end:var(--space-2) solid transparent;background:transparent;color:var(--text-text-secondary);font-size:var(--font-size-md);font-weight:var(--font-weight-medium);cursor:pointer;transition:color .15s ease,border-color .15s ease;margin-block-end:-1px}.sce-account-users-tabs-bar__tab-btn:hover{color:var(--text-text-brand-primary)}.sce-account-users-tabs-bar__tab-btn--active{color:var(--text-text-brand-primary);border-block-end-color:var(--button-background-primary-bg-primary);font-weight:var(--font-weight-semibold)}.sce-account-users-tabs-bar__hint{color:var(--color-brand-primary-600);font-size:var(--font-size-sm);margin-block-end:var(--space-12)}\n"] }]
|
|
11987
12211
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], activeTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTab", required: true }] }], showAddButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAddButton", required: false }] }], accountUsersTabClick: [{ type: i0.Output, args: ["accountUsersTabClick"] }], staffTabClick: [{ type: i0.Output, args: ["staffTabClick"] }], addUserClick: [{ type: i0.Output, args: ["addUserClick"] }] } });
|
|
11988
12212
|
|
|
12213
|
+
/** Dialog that collects a national ID and birth date (Hijri or Gregorian via `calendarSystem`) to verify a user before assigning them; fully controlled, emitting `submitVerify` rather than calling any API. */
|
|
11989
12214
|
class SceAccountUserVerifyDialogComponent {
|
|
11990
12215
|
visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
11991
12216
|
locale = input.required(...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
|
|
@@ -12008,6 +12233,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12008
12233
|
args: [{ selector: 'sce-account-user-verify-dialog', standalone: true, imports: [FormsModule, TranslatePipe, SceDialogShellComponent, SceDateFieldComponent, SceInlineApiErrorComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-account-user-verify-dialog' }, template: "<sce-dialog-shell\n [visible]=\"visible()\"\n [locale]=\"locale()\"\n [title]=\"'dashboard.accountUsers.dialog.addTitle' | translate\"\n [subtitle]=\"'dashboard.accountUsers.dialog.verifyDescription' | translate\"\n size=\"md\"\n [centerHeader]=\"false\"\n [style]=\"{ 'min-height': '380px' }\"\n (close)=\"dialogClose.emit()\"\n>\n <div class=\"sce-account-user-verify-dialog__group\">\n <div class=\"sce-account-user-verify-dialog__field\">\n <p class=\"sce-account-user-verify-dialog__label\">{{ 'dashboard.accountUsers.dialog.nationalId' | translate }} *</p>\n <input\n class=\"sce-account-user-verify-dialog__input\"\n [class.sce-account-user-verify-dialog__input--error]=\"nationalIdError()\"\n [placeholder]=\"'dashboard.accountUsers.dialog.nationalIdPlaceholder' | translate\"\n inputmode=\"numeric\"\n maxlength=\"10\"\n [ngModel]=\"nationalId()\"\n (ngModelChange)=\"nationalIdChange.emit($event)\"\n />\n @if (nationalIdError()) {\n <p class=\"sce-account-user-verify-dialog__error\">{{ nationalIdError() }}</p>\n }\n </div>\n <div class=\"sce-account-user-verify-dialog__field\">\n <sce-date-field\n id=\"verify-birth-date\"\n [label]=\"'dashboard.accountUsers.dialog.birthDate' | translate\"\n [calendarSystem]=\"calendarSystem()\"\n [locale]=\"locale()\"\n [value]=\"birthDate()\"\n [error]=\"birthDateError()\"\n displayFormat=\"iso\"\n [showIcon]=\"true\"\n (valueChange)=\"birthDateChange.emit($event)\"\n />\n </div>\n @if (actionError()) {\n <sce-inline-api-error [message]=\"actionError()\" />\n }\n </div>\n <div class=\"sce-account-user-verify-dialog__actions\" dialogFooter>\n <button\n class=\"sce-account-user-verify-dialog__btn sce-account-user-verify-dialog__btn--secondary\"\n type=\"button\"\n (click)=\"dialogClose.emit()\"\n >\n {{ 'dashboard.accountUsers.dialog.cancel' | translate }}\n </button>\n <button\n class=\"sce-account-user-verify-dialog__btn sce-account-user-verify-dialog__btn--primary\"\n type=\"button\"\n [disabled]=\"submitting()\"\n (click)=\"submitVerify.emit()\"\n >\n {{ 'dashboard.accountUsers.dialog.verify' | translate }}\n </button>\n </div>\n</sce-dialog-shell>\n", styles: [":host.sce-account-user-verify-dialog{display:contents}.sce-account-user-verify-dialog__group{display:grid;gap:var(--space-12)}.sce-account-user-verify-dialog__field{display:grid;gap:.4rem;width:100%;min-width:0}.sce-account-user-verify-dialog__label{color:var(--details-label-color);font-size:var(--details-label-size);font-weight:var(--details-label-weight)}.sce-account-user-verify-dialog__input{width:100%;box-sizing:border-box;height:var(--space-48);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl, var(--radius-xl));background:var(--color-surface);padding:var(--space-12) var(--space-16);font-size:var(--font-size-md);font-weight:var(--font-weight-normal);color:var(--color-neutral-500);outline:0}.sce-account-user-verify-dialog__input::placeholder{color:var(--color-neutral-500)}.sce-account-user-verify-dialog__input--error{border:1.5px solid var(--text-text-error-primary)}.sce-account-user-verify-dialog__input--error:focus{border-color:var(--text-text-error-primary)}.sce-account-user-verify-dialog__error{color:var(--text-text-error-primary);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium)}.sce-account-user-verify-dialog__actions{display:flex;gap:.6rem}.sce-account-user-verify-dialog__btn{border-radius:var(--radius-10);padding:var(--space-10) var(--space-24);font-size:var(--font-size-md-15);font-weight:var(--font-weight-semibold);cursor:pointer;width:50%}.sce-account-user-verify-dialog__btn:disabled{opacity:.55;cursor:not-allowed}.sce-account-user-verify-dialog__btn--primary{border:0;flex:1;background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand)}.sce-account-user-verify-dialog__btn--secondary{border:1px solid var(--button-background-primary-bg-primary);background:transparent;color:var(--button-background-primary-bg-primary)}\n"] }]
|
|
12009
12234
|
}], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: true }] }], nationalId: [{ type: i0.Input, args: [{ isSignal: true, alias: "nationalId", required: true }] }], nationalIdError: [{ type: i0.Input, args: [{ isSignal: true, alias: "nationalIdError", required: false }] }], birthDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "birthDate", required: true }] }], birthDateError: [{ type: i0.Input, args: [{ isSignal: true, alias: "birthDateError", required: false }] }], calendarSystem: [{ type: i0.Input, args: [{ isSignal: true, alias: "calendarSystem", required: false }] }], submitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitting", required: false }] }], actionError: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionError", required: false }] }], dialogClose: [{ type: i0.Output, args: ["dialogClose"] }], nationalIdChange: [{ type: i0.Output, args: ["nationalIdChange"] }], birthDateChange: [{ type: i0.Output, args: ["birthDateChange"] }], submitVerify: [{ type: i0.Output, args: ["submitVerify"] }] } });
|
|
12010
12235
|
|
|
12236
|
+
/** Dialog for assigning an account user roles and contact details; fully controlled — it mutates nothing, emitting every field change and `submitAssign` to the host — and uses `ViewEncapsulation.None`. */
|
|
12011
12237
|
class SceAccountUserAssignDialogComponent {
|
|
12012
12238
|
visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
12013
12239
|
locale = input.required(...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
|
|
@@ -12036,6 +12262,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12036
12262
|
args: [{ selector: 'sce-account-user-assign-dialog', standalone: true, imports: [FormsModule, TranslatePipe, MultiSelect, SceDialogShellComponent, SceSwitchComponent, SceSkeleton], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-account-user-assign-dialog' }, template: "<sce-dialog-shell\n [visible]=\"visible()\"\n [locale]=\"locale()\"\n [title]=\"'dashboard.accountUsers.dialog.addTitle' | translate\"\n [subtitle]=\"description()\"\n size=\"md\"\n [centerHeader]=\"false\"\n (close)=\"dialogClose.emit()\"\n>\n <div class=\"sce-account-user-assign-dialog__readonly-grid\">\n <div class=\"sce-account-user-assign-dialog__readonly-field\">\n <p class=\"sce-account-user-assign-dialog__label\">{{ 'dashboard.accountUsers.dialog.nationalId' | translate }}</p>\n <p class=\"sce-account-user-assign-dialog__value\">{{ assignForm().nationalId || '\u2014' }}</p>\n </div>\n <div class=\"sce-account-user-assign-dialog__readonly-field\">\n <p class=\"sce-account-user-assign-dialog__label\">{{ 'dashboard.accountUsers.dialog.birthDate' | translate }}</p>\n <p class=\"sce-account-user-assign-dialog__value\">{{ assignForm().birthDate || '\u2014' }}</p>\n </div>\n <div class=\"sce-account-user-assign-dialog__readonly-field\">\n <p class=\"sce-account-user-assign-dialog__label\">{{ 'dashboard.accountUsers.dialog.fullName' | translate }}</p>\n <p class=\"sce-account-user-assign-dialog__value\">{{ assignForm().userName || '\u2014' }}</p>\n </div>\n @if (requireEmail()) {\n <div class=\"sce-account-user-assign-dialog__field\">\n <p class=\"sce-account-user-assign-dialog__label\">{{ 'dashboard.accountUsers.dialog.email' | translate }} *</p>\n <input\n class=\"sce-account-user-assign-dialog__input\"\n [class.sce-account-user-assign-dialog__input--error]=\"emailError()\"\n [ngModel]=\"assignForm().email\"\n (ngModelChange)=\"emailChange.emit($event)\"\n inputmode=\"email\"\n />\n @if (emailError()) {\n <p class=\"sce-account-user-assign-dialog__error\">{{ emailError() }}</p>\n }\n </div>\n } @else {\n <div class=\"sce-account-user-assign-dialog__readonly-field\">\n <p class=\"sce-account-user-assign-dialog__label\">{{ 'dashboard.accountUsers.dialog.email' | translate }}</p>\n <p class=\"sce-account-user-assign-dialog__value\">{{ assignForm().email || '\u2014' }}</p>\n </div>\n }\n @if (requireMobile()) {\n <div class=\"sce-account-user-assign-dialog__field\">\n <p class=\"sce-account-user-assign-dialog__label\">{{ 'dashboard.accountUsers.dialog.mobile' | translate }} *</p>\n <input\n class=\"sce-account-user-assign-dialog__input\"\n [class.sce-account-user-assign-dialog__input--error]=\"mobileError()\"\n [ngModel]=\"assignForm().mobile\"\n (ngModelChange)=\"mobileChange.emit($event)\"\n inputmode=\"numeric\"\n maxlength=\"15\"\n />\n @if (mobileError()) {\n <p class=\"sce-account-user-assign-dialog__error\">{{ mobileError() }}</p>\n }\n </div>\n } @else {\n <div class=\"sce-account-user-assign-dialog__readonly-field\">\n <p class=\"sce-account-user-assign-dialog__label\">{{ 'dashboard.accountUsers.dialog.mobile' | translate }}</p>\n <p class=\"sce-account-user-assign-dialog__value\">{{ assignForm().mobile || '\u2014' }}</p>\n </div>\n }\n </div>\n\n <div class=\"sce-account-user-assign-dialog__group\">\n <h4 class=\"sce-account-user-assign-dialog__group-title\">{{ 'dashboard.accountUsers.dialog.permissions' | translate }}</h4>\n <div class=\"sce-account-user-assign-dialog__multi-select\">\n @if (rolesLoading()) {\n <sce-skeleton variant=\"input\" animation=\"wave\" aria-hidden=\"true\" />\n } @else {\n <p-multiSelect\n [options]=\"roleOptions()\"\n [ngModel]=\"assignForm().roleIds\"\n (ngModelChange)=\"roleIdsChange.emit($event)\"\n display=\"chip\"\n [selectedItemsLabel]=\"'dashboard.accountUsers.dialog.selectedItems' | translate\"\n [placeholder]=\"'dashboard.accountUsers.dialog.selectPermissions' | translate\"\n optionLabel=\"label\"\n optionValue=\"value\"\n appendTo=\"body\"\n />\n }\n </div>\n @if (rolesError()) {\n <p class=\"sce-account-user-assign-dialog__error\">{{ rolesError() }}</p>\n }\n\n <div class=\"sce-account-user-assign-dialog__status-row\">\n <div class=\"sce-account-user-assign-dialog__readonly-field\">\n <h4 class=\"sce-account-user-assign-dialog__group-title sce-account-user-assign-dialog__status-title\">\n {{ 'dashboard.accountUsers.dialog.userStatus' | translate }}\n </h4>\n <sce-switch\n [checked]=\"assignForm().isActive\"\n [showLabel]=\"true\"\n [activeLabel]=\"'dashboard.accountUsers.dialog.active' | translate\"\n [inactiveLabel]=\"'dashboard.accountUsers.dialog.inactive' | translate\"\n (checkedChange)=\"isActiveChange.emit($event)\"\n />\n </div>\n </div>\n\n @if (actionError()) {\n <p class=\"sce-account-user-assign-dialog__error\">{{ actionError() }}</p>\n }\n </div>\n\n <div class=\"sce-account-user-assign-dialog__actions\" dialogFooter>\n <button\n class=\"sce-account-user-assign-dialog__btn sce-account-user-assign-dialog__btn--secondary\"\n type=\"button\"\n (click)=\"dialogClose.emit()\"\n >\n {{ 'dashboard.accountUsers.dialog.cancel' | translate }}\n </button>\n <button\n class=\"sce-account-user-assign-dialog__btn sce-account-user-assign-dialog__btn--primary\"\n type=\"button\"\n [disabled]=\"submitting()\"\n (click)=\"submitAssign.emit()\"\n >\n {{ 'dashboard.accountUsers.dialog.addUser' | translate }}\n </button>\n </div>\n</sce-dialog-shell>\n", styles: [".sce-account-user-assign-dialog__readonly-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12)}@media(max-width:640px){.sce-account-user-assign-dialog__readonly-grid{grid-template-columns:1fr}}.sce-account-user-assign-dialog__readonly-field{background:var(--app-surface-hover);border-radius:var(--radius-xl, var(--radius-xl));min-height:var(--size-89);padding:var(--space-16);display:grid;align-content:center;gap:var(--space-8);width:100%}.sce-account-user-assign-dialog__field{display:grid;gap:.4rem;width:100%;min-width:0}.sce-account-user-assign-dialog__label{color:var(--details-label-color);font-size:var(--details-label-size);font-weight:var(--details-label-weight)}.sce-account-user-assign-dialog__value{color:var(--details-value-color);font-size:var(--details-value-size);font-weight:var(--details-value-weight)}.sce-account-user-assign-dialog__input{width:100%;box-sizing:border-box;height:var(--space-48);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl, var(--radius-xl));background:var(--color-surface);padding:var(--space-12) var(--space-16);font-size:var(--font-size-md);color:var(--color-neutral-500);outline:0}.sce-account-user-assign-dialog__input--error{border:1.5px solid var(--text-text-error-primary)}.sce-account-user-assign-dialog__group{display:grid;gap:var(--space-12)}.sce-account-user-assign-dialog__group-title{color:var(--details-label-color);font-size:var(--details-label-size);font-weight:var(--details-label-weight)}.sce-account-user-assign-dialog__multi-select{width:100%;min-width:0}.sce-account-user-assign-dialog__multi-select .p-multiselect{width:100%;min-height:var(--space-48);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl, var(--radius-xl));background:var(--color-surface);font-size:var(--font-size-md)}.sce-account-user-assign-dialog__status-row{display:flex;align-items:center;justify-content:space-between;gap:var(--space-12);width:100%}.sce-account-user-assign-dialog__status-title{color:var(--details-label-color);font-size:var(--font-size-md);font-weight:var(--font-weight-semibold);text-align:start}.sce-account-user-assign-dialog__error{color:var(--text-text-error-primary);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium)}.sce-account-user-assign-dialog__actions{display:flex;gap:.6rem}.sce-account-user-assign-dialog__btn{border-radius:var(--radius-10);padding:var(--space-10) var(--space-24);font-size:var(--font-size-md-15);font-weight:var(--font-weight-semibold);cursor:pointer;width:50%}.sce-account-user-assign-dialog__btn:disabled{opacity:.55;cursor:not-allowed}.sce-account-user-assign-dialog__btn--primary{border:0;flex:1;background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand)}.sce-account-user-assign-dialog__btn--secondary{border:1px solid var(--button-background-primary-bg-primary);background:transparent;color:var(--button-background-primary-bg-primary)}\n"] }]
|
|
12037
12263
|
}], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: true }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: true }] }], assignForm: [{ type: i0.Input, args: [{ isSignal: true, alias: "assignForm", required: true }] }], requireEmail: [{ type: i0.Input, args: [{ isSignal: true, alias: "requireEmail", required: false }] }], requireMobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "requireMobile", required: false }] }], emailError: [{ type: i0.Input, args: [{ isSignal: true, alias: "emailError", required: false }] }], mobileError: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileError", required: false }] }], rolesLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "rolesLoading", required: false }] }], roleOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "roleOptions", required: false }] }], rolesError: [{ type: i0.Input, args: [{ isSignal: true, alias: "rolesError", required: false }] }], actionError: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionError", required: false }] }], submitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitting", required: false }] }], dialogClose: [{ type: i0.Output, args: ["dialogClose"] }], emailChange: [{ type: i0.Output, args: ["emailChange"] }], mobileChange: [{ type: i0.Output, args: ["mobileChange"] }], roleIdsChange: [{ type: i0.Output, args: ["roleIdsChange"] }], isActiveChange: [{ type: i0.Output, args: ["isActiveChange"] }], submitAssign: [{ type: i0.Output, args: ["submitAssign"] }] } });
|
|
12038
12264
|
|
|
12265
|
+
/** Dialog for editing an existing account user's roles and active state over a read-only identity summary; fully controlled and uses `ViewEncapsulation.None`. */
|
|
12039
12266
|
class SceAccountUserEditDialogComponent {
|
|
12040
12267
|
visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
12041
12268
|
locale = input.required(...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
|
|
@@ -12062,6 +12289,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12062
12289
|
args: [{ selector: 'sce-account-user-edit-dialog', standalone: true, imports: [FormsModule, TranslatePipe, MultiSelect, SceDialogShellComponent, SceSwitchComponent, SceSkeleton], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-account-user-edit-dialog' }, template: "<sce-dialog-shell\n [visible]=\"visible()\"\n [locale]=\"locale()\"\n [title]=\"title()\"\n [subtitle]=\"subtitle()\"\n size=\"md\"\n [centerHeader]=\"false\"\n (close)=\"closed.emit()\"\n>\n @if (readOnlyFields().length) {\n <div class=\"sce-account-user-edit-dialog__readonly-grid\">\n @for (field of readOnlyFields(); track field.label) {\n <div\n class=\"sce-account-user-edit-dialog__readonly-field\"\n [class.sce-account-user-edit-dialog__readonly-field--full-width]=\"field.fullWidth\"\n >\n <p class=\"sce-account-user-edit-dialog__label\">{{ field.label }}</p>\n <p class=\"sce-account-user-edit-dialog__value\">{{ field.value || '\u2014' }}</p>\n </div>\n }\n </div>\n }\n\n <div class=\"sce-account-user-edit-dialog__group\">\n <h4 class=\"sce-account-user-edit-dialog__group-title\">{{ 'DASHBOARD.STAFF_DETAIL.PERMISSIONS' | translate }} *</h4>\n <div class=\"sce-account-user-edit-dialog__multi-select\">\n @if (rolesLoading()) {\n <sce-skeleton variant=\"input\" animation=\"wave\" aria-hidden=\"true\" />\n } @else {\n <p-multiSelect\n [options]=\"roleOptions()\"\n [ngModel]=\"draftRoleIds()\"\n (ngModelChange)=\"draftRoleIdsChange.emit($event)\"\n display=\"chip\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'DASHBOARD.STAFF_DETAIL.SELECT_PERMISSION_PLACEHOLDER' | translate\"\n [selectedItemsLabel]=\"'DASHBOARD.STAFF_DETAIL.SELECTED_ITEMS' | translate\"\n appendTo=\"body\"\n />\n }\n </div>\n @if (permissionsError()) {\n <p class=\"sce-account-user-edit-dialog__error\">{{ permissionsError() }}</p>\n }\n\n <div class=\"sce-account-user-edit-dialog__status-card\">\n <p class=\"sce-account-user-edit-dialog__label\">\n {{ 'DASHBOARD.STAFF_DETAIL.USER_STATUS' | translate }}\n </p>\n <div class=\"sce-account-user-edit-dialog__status-switch\">\n <sce-switch\n [checked]=\"isActive()\"\n [showLabel]=\"true\"\n [activeLabel]=\"'DASHBOARD.STAFF_DETAIL.STATUS_ACTIVE' | translate\"\n [inactiveLabel]=\"'DASHBOARD.STAFF_DETAIL.STATUS_INACTIVE' | translate\"\n (checkedChange)=\"isActiveChange.emit($event)\"\n />\n </div>\n </div>\n\n @if (dialogError()) {\n <p class=\"sce-account-user-edit-dialog__error\">{{ dialogError() }}</p>\n }\n </div>\n\n <div class=\"sce-account-user-edit-dialog__actions\" dialogFooter>\n <button class=\"sce-account-user-edit-dialog__btn sce-account-user-edit-dialog__btn--secondary\" type=\"button\" (click)=\"closed.emit()\">\n {{ 'DASHBOARD.STAFF_DETAIL.CANCEL' | translate }}\n </button>\n <button\n class=\"sce-account-user-edit-dialog__btn sce-account-user-edit-dialog__btn--primary\"\n type=\"button\"\n [disabled]=\"submitting()\"\n (click)=\"submitted.emit()\"\n >\n {{ submitLabel() }}\n </button>\n </div>\n</sce-dialog-shell>\n", styles: ["@charset \"UTF-8\";.sce-account-user-edit-dialog__readonly-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-3);margin-block-end:var(--space-5)}@media(max-width:576px){.sce-account-user-edit-dialog__readonly-grid{grid-template-columns:1fr}}.sce-account-user-edit-dialog__readonly-field{background:var(--app-surface-hover);border-radius:var(--radius-lg);min-height:var(--space-80);padding:var(--space-3-5) var(--space-4-5);display:flex;flex-direction:column;justify-content:center;gap:var(--space-24);width:100%}.sce-account-user-edit-dialog__readonly-field--full-width{grid-column:1/-1}.sce-account-user-edit-dialog__label{color:var(--details-label-color);font-size:var(--details-label-size);font-weight:var(--details-label-weight);margin:0;text-align:start}.sce-account-user-edit-dialog__value{color:var(--details-value-color);font-size:var(--details-value-size);font-weight:var(--details-value-weight);margin:0;text-align:start}.sce-account-user-edit-dialog__group{display:flex;flex-direction:column;gap:var(--space-2);margin-block-end:var(--space-5)}.sce-account-user-edit-dialog__group-title{color:var(--details-label-color);font-size:var(--details-label-size);font-weight:var(--font-weight-bold);margin:0;text-align:start}.sce-account-user-edit-dialog__multi-select{width:100%;min-width:0}.sce-account-user-edit-dialog__multi-select .p-multiselect{width:100%;min-height:var(--space-56);border:1px solid var(--color-neutral-200);border-radius:var(--radius-lg);background:var(--color-surface);font-size:var(--font-size-md);display:flex;align-items:center;box-shadow:none}.sce-account-user-edit-dialog__multi-select .p-multiselect:not(.p-disabled):hover{border-color:var(--color-neutral-300)}.sce-account-user-edit-dialog__multi-select .p-multiselect:not(.p-disabled).p-focus{border-color:var(--color-brand-primary-500);box-shadow:0 0 0 2px color-mix(in srgb,var(--color-brand-primary-500) 10%,transparent)}.sce-account-user-edit-dialog__multi-select .p-multiselect .p-multiselect-label-container{padding:0;width:100%;display:flex}.sce-account-user-edit-dialog__multi-select .p-multiselect .p-multiselect-label{padding:var(--space-3) var(--space-4);display:flex;flex-wrap:wrap;gap:var(--space-2);align-items:center;width:100%}.sce-account-user-edit-dialog__multi-select .p-multiselect .p-multiselect-label:has(.p-multiselect-token){padding:var(--space-24) var(--space-4)}.sce-account-user-edit-dialog__multi-select .p-multiselect .p-multiselect-token{display:inline-flex;flex-direction:row-reverse;align-items:center;background:var(--color-neutral-100);color:var(--color-neutral-700);border-radius:var(--radius-full);padding:var(--space-24) var(--space-4);gap:var(--space-2-5);margin-block:var(--space-2);border:none}.sce-account-user-edit-dialog__multi-select .p-multiselect .p-multiselect-token .p-multiselect-token-label{font-size:var(--font-size-sm);font-weight:var(--font-weight-medium)}.sce-account-user-edit-dialog__multi-select .p-multiselect .p-multiselect-token .p-multiselect-token-icon{font-size:var(--font-size-md);color:var(--color-neutral-600);margin:0;cursor:pointer}.sce-account-user-edit-dialog__multi-select .p-multiselect .p-multiselect-token .p-multiselect-token-icon:before{content:\"\\d7\"}.sce-account-user-edit-dialog__multi-select .p-multiselect .p-multiselect-trigger{color:var(--color-neutral-600)}.sce-account-user-edit-dialog__status-card{background:var(--app-surface-hover);border-radius:var(--radius-lg);padding:var(--space-3-5) var(--space-4-5);min-height:var(--space-64);margin-block-start:var(--space-1)}.sce-account-user-edit-dialog__status-card .sce-account-user-edit-dialog__label{font-weight:var(--font-weight-bold)}.sce-account-user-edit-dialog__status-switch{margin-block-start:var(--space-2)}.sce-account-user-edit-dialog__status-switch sce-switch{display:inline-flex;align-items:center}.sce-account-user-edit-dialog__status-switch sce-switch .sce-switch-label{font-size:var(--font-size-md-15);font-weight:var(--font-weight-bold);color:var(--color-success-600)}.sce-account-user-edit-dialog__status-switch sce-switch .sce-switch-label--inactive{color:var(--color-neutral-600)}.sce-account-user-edit-dialog__error{color:var(--text-text-error-primary);font-size:var(--font-size-xs);font-weight:var(--font-weight-medium);margin:0;text-align:start}.sce-account-user-edit-dialog__actions{display:flex;gap:var(--space-4);margin-block-start:var(--space-24);width:100%}.sce-account-user-edit-dialog__btn{flex:1;min-height:var(--size-54);border-radius:var(--radius-lg);font-size:var(--font-size-md);font-weight:var(--font-weight-semibold);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:background .2s ease-in-out}.sce-account-user-edit-dialog__btn:disabled{opacity:.55;cursor:not-allowed}.sce-account-user-edit-dialog__btn--primary{border:0;background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand)}.sce-account-user-edit-dialog__btn--secondary{border:1px solid var(--button-background-primary-bg-primary);background:var(--color-surface);color:var(--button-background-primary-bg-primary)}\n"] }]
|
|
12063
12290
|
}], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: true }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: true }] }], readOnlyFields: [{ type: i0.Input, args: [{ isSignal: true, alias: "readOnlyFields", required: false }] }], roleOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "roleOptions", required: false }] }], draftRoleIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "draftRoleIds", required: false }] }], rolesLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "rolesLoading", required: false }] }], isActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "isActive", required: false }] }], permissionsError: [{ type: i0.Input, args: [{ isSignal: true, alias: "permissionsError", required: false }] }], dialogError: [{ type: i0.Input, args: [{ isSignal: true, alias: "dialogError", required: false }] }], submitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitting", required: false }] }], submitLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitLabel", required: true }] }], closed: [{ type: i0.Output, args: ["closed"] }], submitted: [{ type: i0.Output, args: ["submitted"] }], draftRoleIdsChange: [{ type: i0.Output, args: ["draftRoleIdsChange"] }], isActiveChange: [{ type: i0.Output, args: ["isActiveChange"] }] } });
|
|
12064
12291
|
|
|
12292
|
+
/** Header of an account-user detail page: name, status tags, membership/national-ID badges, and an Edit button; all labels are passed in already translated. */
|
|
12065
12293
|
class SceAccountUserDetailHeaderComponent {
|
|
12066
12294
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
12067
12295
|
statusTags = input([], ...(ngDevMode ? [{ debugName: "statusTags" }] : /* istanbul ignore next */ []));
|
|
@@ -12077,6 +12305,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12077
12305
|
args: [{ selector: 'sce-account-user-detail-header', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-account-user-detail-header' }, imports: [SceBusinessStatusTagComponent], template: "<div class=\"sce-account-user-detail-header__left\">\n <div class=\"sce-account-user-detail-header__name-wrap\">\n <div class=\"sce-account-user-detail-header__title-row\">\n <h2 class=\"sce-account-user-detail-header__title\">{{ title() }}</h2>\n @if (membershipBadge(); as badge) {\n <span class=\"sce-account-user-detail-header__badge\">\n <span class=\"sce-account-user-detail-header__badge-label\">{{ badge.label }}</span>\n <span class=\"sce-account-user-detail-header__badge-value\">{{ badge.value }}</span>\n </span>\n }\n </div>\n <div class=\"sce-account-user-detail-header__status-row\">\n @for (tag of statusTags(); track tag.label) {\n <sce-business-status-tag [label]=\"tag.label\" [tone]=\"tag.tone\" size=\"sm\" />\n }\n </div>\n </div>\n</div>\n<div class=\"sce-account-user-detail-header__actions\">\n @if (nationalIdBadge(); as badge) {\n <span class=\"sce-account-user-detail-header__badge\">\n <span class=\"sce-account-user-detail-header__badge-label\">{{ badge.label }}</span>\n <span class=\"sce-account-user-detail-header__badge-value\">{{ badge.value }}</span>\n </span>\n }\n <button type=\"button\" class=\"sce-account-user-detail-header__edit-btn\" (click)=\"editClick.emit()\">\n {{ editButtonLabel() }}\n </button>\n</div>\n", styles: [":host{display:flex;align-items:center;justify-content:space-between;gap:var(--space-4);flex-wrap:wrap;margin-block-end:var(--space-5)}@media(max-width:768px){:host{flex-direction:column;align-items:stretch}}.sce-account-user-detail-header__left{display:flex;flex-direction:column;gap:var(--space-2);flex:1;min-width:0}.sce-account-user-detail-header__name-wrap{display:flex;flex-direction:column;gap:var(--space-2);min-width:0}.sce-account-user-detail-header__title-row{display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap}.sce-account-user-detail-header__title{font-size:var(--font-size-xl);font-weight:700;color:var(--color-neutral-950, var(--color-neutral-900));margin:0;overflow-wrap:anywhere}.sce-account-user-detail-header__badge{background:var(--color-neutral-100, var(--app-surface-muted));border-radius:var(--radius-full, var(--radius-100));padding:var(--space-1) var(--space-3);display:inline-flex;align-items:center;gap:var(--space-1-5, var(--space-6));font-size:var(--font-size-2xs, var(--font-size-11));font-family:var(--font-family-arabic-primary)}.sce-account-user-detail-header__badge-label{color:var(--color-neutral-500, var(--text-text-secondary-600));font-weight:500}.sce-account-user-detail-header__badge-value{color:var(--color-neutral-950, var(--color-neutral-900));font-weight:700}.sce-account-user-detail-header__status-row{display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap;margin-block-start:var(--space-2)}.sce-account-user-detail-header__status-row sce-business-status-tag span.tag,.sce-account-user-detail-header__status-row sce-business-status-tag .tag,.sce-account-user-detail-header__status-row sce-business-status-tag .sce-tag,.sce-account-user-detail-header__status-row sce-business-status-tag .sce-tag--sm,.sce-account-user-detail-header__status-row sce-business-status-tag .tag--sm{border-radius:var(--radius-full);padding:var(--space-1) var(--space-3);font-size:var(--font-size-2xs, var(--font-size-11));font-weight:var(--font-weight-bold);border:none;background-color:var(--color-success-50, var(--color-kiwi-200));color:var(--color-success-700, var(--color-kiwi-600))}.sce-account-user-detail-header__actions{display:flex;align-items:center;gap:var(--space-4)}.sce-account-user-detail-header__edit-btn{padding:var(--space-3) var(--space-7, var(--space-28));border-radius:var(--radius-lg);background:var(--color-brand-primary-900, var(--color-brand-primary-800));color:var(--color-white, var(--background-bg-primary));font-size:var(--font-size-sm);font-weight:700;border:none;cursor:pointer;white-space:nowrap;height:fit-content;transition:background var(--duration-fast, .2s) ease-in-out}.sce-account-user-detail-header__edit-btn:hover{background:var(--color-brand-primary-950, var(--color-brand-primary-900))}@media(max-width:768px){.sce-account-user-detail-header__edit-btn{width:100%;box-sizing:border-box}}\n"] }]
|
|
12078
12306
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], statusTags: [{ type: i0.Input, args: [{ isSignal: true, alias: "statusTags", required: false }] }], membershipBadge: [{ type: i0.Input, args: [{ isSignal: true, alias: "membershipBadge", required: false }] }], nationalIdBadge: [{ type: i0.Input, args: [{ isSignal: true, alias: "nationalIdBadge", required: false }] }], editButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "editButtonLabel", required: true }] }], editClick: [{ type: i0.Output, args: ["editClick"] }] } });
|
|
12079
12307
|
|
|
12308
|
+
/** Titled grid of read-only personal-detail `fields` for an account user; labels and values arrive already translated and formatted. */
|
|
12080
12309
|
class SceAccountUserPersonalSectionComponent {
|
|
12081
12310
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
12082
12311
|
fields = input.required(...(ngDevMode ? [{ debugName: "fields" }] : /* istanbul ignore next */ []));
|
|
@@ -12088,6 +12317,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12088
12317
|
args: [{ selector: 'sce-account-user-personal-section', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-account-user-personal-section' }, imports: [SceInfoFieldCardComponent, SceInfoFieldsGridComponent], template: "<h3 class=\"sce-account-user-personal-section__title\">{{ title() }}</h3>\n<sce-info-fields-grid gap=\"sm\">\n @for (field of fields(); track field.label) {\n <sce-info-field-card [label]=\"field.label\" [value]=\"field.value ?? ''\" [fullWidth]=\"field.fullWidth ?? false\" />\n }\n</sce-info-fields-grid>\n", styles: [":host{display:block}.sce-account-user-personal-section__title{font-size:var(--font-size-xl, var(--font-size-xl));font-weight:700;color:var(--color-brand-primary-900, var(--color-brand-primary-800));margin-block-end:var(--space-4);margin-block-start:var(--space-4)}\n"] }]
|
|
12089
12318
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], fields: [{ type: i0.Input, args: [{ isSignal: true, alias: "fields", required: true }] }] } });
|
|
12090
12319
|
|
|
12320
|
+
/** Read-only permissions panel listing an account user's roles as `pills`, falling back to `noPermissionsLabel` when empty and to skeletons while `loading`. */
|
|
12091
12321
|
class SceAccountUserPermissionsSectionComponent {
|
|
12092
12322
|
sectionTitle = input.required(...(ngDevMode ? [{ debugName: "sectionTitle" }] : /* istanbul ignore next */ []));
|
|
12093
12323
|
permissionsLabel = input.required(...(ngDevMode ? [{ debugName: "permissionsLabel" }] : /* istanbul ignore next */ []));
|
|
@@ -12102,6 +12332,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12102
12332
|
args: [{ selector: 'sce-account-user-permissions-section', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-account-user-permissions-section' }, imports: [SceInfoFieldCardComponent, SceInfoFieldsGridComponent, SceSkeleton], template: "<h3 class=\"sce-account-user-permissions-section__title\">{{ sectionTitle() }}</h3>\n<sce-info-fields-grid gap=\"sm\">\n <sce-info-field-card class=\"permissionsCard\" [label]=\"permissionsLabel()\" [fullWidth]=\"true\">\n <div class=\"sce-account-user-permissions-section__list\">\n @if (loading()) {\n <div class=\"sce-account-user-permissions-section__skeleton\">\n @for (i of [1, 2, 3]; track i) {\n <sce-skeleton variant=\"chip\" width=\"6rem\" height=\"1.5rem\" animation=\"wave\" aria-hidden=\"true\" />\n }\n </div>\n } @else if (pills().length > 0) {\n @for (pill of pills(); track pill) {\n <span class=\"sce-account-user-permissions-section__pill\">{{ pill }}</span>\n }\n } @else {\n <span class=\"sce-account-user-permissions-section__no-permissions\">{{ noPermissionsLabel() }}</span>\n }\n </div>\n </sce-info-field-card>\n</sce-info-fields-grid>\n", styles: [":host{display:block}.sce-account-user-permissions-section__title{font-size:var(--font-size-xl, var(--font-size-xl));font-weight:700;color:var(--color-brand-primary-900, var(--color-brand-primary-800));margin-block-end:var(--space-4);margin-block-start:var(--space-4)}.sce-account-user-permissions-section__list{display:flex;flex-wrap:wrap;gap:var(--space-2);margin-block-start:var(--space-1)}.sce-account-user-permissions-section__skeleton{display:flex;flex-wrap:wrap;gap:var(--space-2)}.sce-account-user-permissions-section__pill{padding:var(--space-1-5, var(--space-6)) var(--space-3-5, var(--space-14));border-radius:var(--radius-full, var(--radius-100));background:var(--color-info-50, var(--color-blue-100));color:var(--color-brand-primary-700, var(--color-brand-primary-600));font-size:var(--font-size-xs);font-weight:700;display:inline-block}.sce-account-user-permissions-section__no-permissions{font-size:var(--font-size-sm);color:var(--color-neutral-400, var(--form-label-muted))}\n"] }]
|
|
12103
12333
|
}], propDecorators: { sectionTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "sectionTitle", required: true }] }], permissionsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "permissionsLabel", required: true }] }], noPermissionsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "noPermissionsLabel", required: true }] }], pills: [{ type: i0.Input, args: [{ isSignal: true, alias: "pills", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }] } });
|
|
12104
12334
|
|
|
12335
|
+
/** Inline (non-dialog) national-ID and birth-date step for verifying an internal user before creation; `calendarSystem` selects Hijri or Gregorian input and `verify` is emitted for the host to call the API. */
|
|
12105
12336
|
class SceInternalUserVerifySectionComponent {
|
|
12106
12337
|
nationalId = input.required(...(ngDevMode ? [{ debugName: "nationalId" }] : /* istanbul ignore next */ []));
|
|
12107
12338
|
birthDate = input.required(...(ngDevMode ? [{ debugName: "birthDate" }] : /* istanbul ignore next */ []));
|
|
@@ -12121,6 +12352,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12121
12352
|
args: [{ selector: 'sce-internal-user-verify-section', standalone: true, imports: [FormsModule, TranslatePipe, SceDateFieldComponent, SceSkeleton], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-internal-user-verify-section' }, template: "<div class=\"sce-internal-user-verify-section__panel\">\n <p class=\"sce-internal-user-verify-section__hint\">\n {{ 'dashboard.users.dialog.verifySectionDescription' | translate }}\n </p>\n\n <div class=\"sce-internal-user-verify-section__fields\">\n <div class=\"sce-internal-user-verify-section__field\">\n <label for=\"nationalId\" class=\"sce-internal-user-verify-section__label\">\n {{ 'dashboard.internalUserForm.nationalId' | translate }}\n <span aria-hidden=\"true\"> *</span>\n </label>\n <input\n id=\"nationalId\"\n dir=\"ltr\"\n class=\"sce-internal-user-verify-section__input\"\n [class.sce-internal-user-verify-section__input--error]=\"nationalIdError()\"\n [placeholder]=\"'dashboard.internalUserForm.nationalIdPlaceholder' | translate\"\n inputmode=\"numeric\"\n maxlength=\"10\"\n [ngModel]=\"nationalId()\"\n (ngModelChange)=\"nationalIdChange.emit($event)\"\n />\n @if (nationalIdError()) {\n <p class=\"sce-internal-user-verify-section__error\" role=\"alert\">{{ nationalIdError() }}</p>\n }\n </div>\n\n <div class=\"sce-internal-user-verify-section__field\">\n <sce-date-field\n id=\"birthDate\"\n [label]=\"'dashboard.internalUserForm.birthDate' | translate\"\n [calendarSystem]=\"calendarSystem()\"\n [locale]=\"locale()\"\n [value]=\"birthDate()\"\n [error]=\"birthDateError()\"\n displayFormat=\"iso\"\n [showIcon]=\"true\"\n (valueChange)=\"birthDateChange.emit($event)\"\n />\n </div>\n </div>\n\n <div>\n <!-- aria-label: while verifying, the visible content is an aria-hidden skeleton,\n which would otherwise leave the button nameless (axe: button-name). -->\n <button\n type=\"button\"\n class=\"sce-internal-user-verify-section__button\"\n [attr.aria-label]=\"'dashboard.internalUserForm.verify' | translate\"\n [disabled]=\"verifying()\"\n (click)=\"verify.emit()\"\n >\n @if (verifying()) {\n <sce-skeleton variant=\"text\" width=\"5rem\" height=\"1rem\" animation=\"wave\" aria-hidden=\"true\" />\n } @else {\n {{ 'dashboard.internalUserForm.verify' | translate }}\n }\n </button>\n </div>\n</div>\n", styles: [":host{display:block}.sce-internal-user-verify-section__panel{display:grid;gap:var(--space-16);padding:var(--space-20);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl);background:var(--app-surface-hover)}.sce-internal-user-verify-section__hint{margin:0;color:var(--text-text-secondary-700);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium)}.sce-internal-user-verify-section__fields{display:grid;grid-template-columns:1fr;gap:var(--space-12)}@media(min-width:769px){.sce-internal-user-verify-section__fields{grid-template-columns:repeat(2,minmax(0,1fr))}}.sce-internal-user-verify-section__field{display:grid;gap:var(--space-24)}.sce-internal-user-verify-section__label{margin:0;color:var(--text-text-secondary-700);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium)}.sce-internal-user-verify-section__input{height:var(--space-48);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl);background:var(--color-surface);padding-inline:var(--space-16);font-size:var(--font-size-md);font-weight:var(--font-weight-normal);color:var(--text-text-primary-900);outline:0;width:100%;box-sizing:border-box;transition:border-color .15s ease}.sce-internal-user-verify-section__input::placeholder{color:var(--color-neutral-500)}.sce-internal-user-verify-section__input:focus{border-color:var(--button-background-primary-bg-primary)}.sce-internal-user-verify-section__input--error{border-color:var(--text-text-error-primary)}.sce-internal-user-verify-section__input--error:focus{border-color:var(--text-text-error-primary);box-shadow:none}.sce-internal-user-verify-section__error{margin:0;color:var(--text-text-error-primary);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium)}.sce-internal-user-verify-section__button{display:inline-flex;align-items:center;justify-content:center;min-height:var(--space-48);min-width:var(--size-140);padding:var(--space-8) var(--space-24);border:0;border-radius:var(--radius-xl);background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand);font-weight:var(--font-weight-bold);font-size:var(--font-size-md);cursor:pointer;transition:opacity .15s ease}.sce-internal-user-verify-section__button:disabled{opacity:.6;cursor:not-allowed}\n"] }]
|
|
12122
12353
|
}], propDecorators: { nationalId: [{ type: i0.Input, args: [{ isSignal: true, alias: "nationalId", required: true }] }], birthDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "birthDate", required: true }] }], nationalIdError: [{ type: i0.Input, args: [{ isSignal: true, alias: "nationalIdError", required: false }] }], birthDateError: [{ type: i0.Input, args: [{ isSignal: true, alias: "birthDateError", required: false }] }], calendarSystem: [{ type: i0.Input, args: [{ isSignal: true, alias: "calendarSystem", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: true }] }], verifying: [{ type: i0.Input, args: [{ isSignal: true, alias: "verifying", required: false }] }], nationalIdChange: [{ type: i0.Output, args: ["nationalIdChange"] }], birthDateChange: [{ type: i0.Output, args: ["birthDateChange"] }], verify: [{ type: i0.Output, args: ["verify"] }] } });
|
|
12123
12354
|
|
|
12355
|
+
/** Contact-detail fields for an internal user: national ID, birth date, and name are read-only, and only email and mobile are editable (emitted back to the host). */
|
|
12124
12356
|
class SceInternalUserFormFieldsComponent {
|
|
12125
12357
|
mode = input.required(...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
12126
12358
|
nationalId = input('', ...(ngDevMode ? [{ debugName: "nationalId" }] : /* istanbul ignore next */ []));
|
|
@@ -12140,6 +12372,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12140
12372
|
args: [{ selector: 'sce-internal-user-form-fields', standalone: true, imports: [FormsModule, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-internal-user-form-fields' }, template: "<div class=\"sce-internal-user-form-fields__grid\">\n @if (mode() === 'edit') {\n <div class=\"sce-internal-user-form-fields__readonly\">\n <p class=\"sce-internal-user-form-fields__label\">{{ 'dashboard.internalUserForm.nationalId' | translate }}</p>\n <p class=\"sce-internal-user-form-fields__value\">{{ nationalId() || '\u2014' }}</p>\n </div>\n <div class=\"sce-internal-user-form-fields__readonly\">\n <p class=\"sce-internal-user-form-fields__label\">{{ 'dashboard.internalUserForm.birthDate' | translate }}</p>\n <p class=\"sce-internal-user-form-fields__value\">{{ birthDate() || '\u2014' }}</p>\n </div>\n <div class=\"sce-internal-user-form-fields__readonly\">\n <p class=\"sce-internal-user-form-fields__label\">{{ 'dashboard.internalUserForm.userName' | translate }}</p>\n <p class=\"sce-internal-user-form-fields__value\">{{ userName() || '\u2014' }}</p>\n </div>\n <div class=\"sce-internal-user-form-fields__readonly\">\n <p class=\"sce-internal-user-form-fields__label\">{{ 'dashboard.internalUserForm.email' | translate }}</p>\n <p class=\"sce-internal-user-form-fields__value\">{{ email() || '\u2014' }}</p>\n </div>\n <div class=\"sce-internal-user-form-fields__readonly\">\n <p class=\"sce-internal-user-form-fields__label\">{{ 'dashboard.internalUserForm.mobile' | translate }}</p>\n <p class=\"sce-internal-user-form-fields__value\">{{ mobile() || '\u2014' }}</p>\n </div>\n } @else {\n <div class=\"sce-internal-user-form-fields__readonly\">\n <p class=\"sce-internal-user-form-fields__label\">{{ 'dashboard.internalUserForm.userName' | translate }}</p>\n <p class=\"sce-internal-user-form-fields__value\">{{ userName() || '\u2014' }}</p>\n </div>\n\n <div class=\"sce-internal-user-form-fields__field\">\n <label for=\"email\" class=\"sce-internal-user-form-fields__label\">\n {{ 'dashboard.internalUserForm.email' | translate }}\n </label>\n <input\n id=\"email\"\n type=\"email\"\n dir=\"ltr\"\n inputmode=\"email\"\n class=\"sce-internal-user-form-fields__input\"\n [class.sce-internal-user-form-fields__input--error]=\"emailError()\"\n [placeholder]=\"'dashboard.internalUserForm.emailPlaceholder' | translate\"\n [ngModel]=\"email()\"\n (ngModelChange)=\"emailChange.emit($event)\"\n />\n @if (emailError()) {\n <p class=\"sce-internal-user-form-fields__error\" role=\"alert\">{{ emailError() }}</p>\n }\n </div>\n\n <div class=\"sce-internal-user-form-fields__field\">\n <label for=\"mobile\" class=\"sce-internal-user-form-fields__label\">\n {{ 'dashboard.internalUserForm.mobile' | translate }}\n </label>\n <input\n id=\"mobile\"\n type=\"tel\"\n dir=\"ltr\"\n inputmode=\"numeric\"\n maxlength=\"15\"\n class=\"sce-internal-user-form-fields__input\"\n [class.sce-internal-user-form-fields__input--error]=\"mobileError()\"\n [placeholder]=\"'dashboard.internalUserForm.mobilePlaceholder' | translate\"\n [ngModel]=\"mobile()\"\n (ngModelChange)=\"mobileChange.emit($event)\"\n />\n @if (mobileError()) {\n <p class=\"sce-internal-user-form-fields__error\" role=\"alert\">{{ mobileError() }}</p>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block}.sce-internal-user-form-fields__grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12)}@media(max-width:576px){.sce-internal-user-form-fields__grid{grid-template-columns:1fr}}.sce-internal-user-form-fields__field{display:grid;gap:var(--space-24)}.sce-internal-user-form-fields__label{margin:0;color:var(--text-text-secondary-700);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium)}.sce-internal-user-form-fields__input{height:var(--space-48);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl);background:var(--color-surface);padding-inline:var(--space-16);font-size:var(--font-size-md);font-weight:var(--font-weight-normal);color:var(--text-text-primary-900);outline:0;width:100%;box-sizing:border-box;transition:border-color .15s ease}.sce-internal-user-form-fields__input::placeholder{color:var(--color-neutral-500)}.sce-internal-user-form-fields__input:focus{border-color:var(--button-background-primary-bg-primary)}.sce-internal-user-form-fields__input--error{border-color:var(--text-text-error-primary)}.sce-internal-user-form-fields__input--error:focus{border-color:var(--text-text-error-primary);box-shadow:none}.sce-internal-user-form-fields__error{margin:0;color:var(--text-text-error-primary);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium)}.sce-internal-user-form-fields__readonly{background:var(--app-surface-hover);border-radius:var(--radius-xl);min-height:var(--space-48);padding:var(--space-16);display:grid;align-content:center;gap:var(--space-8)}.sce-internal-user-form-fields__value{margin:0;color:var(--text-text-primary-900);font-size:var(--font-size-md);font-weight:var(--font-weight-medium)}\n"] }]
|
|
12141
12373
|
}], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: true }] }], nationalId: [{ type: i0.Input, args: [{ isSignal: true, alias: "nationalId", required: false }] }], birthDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "birthDate", required: false }] }], userName: [{ type: i0.Input, args: [{ isSignal: true, alias: "userName", required: false }] }], email: [{ type: i0.Input, args: [{ isSignal: true, alias: "email", required: false }] }], mobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobile", required: false }] }], emailError: [{ type: i0.Input, args: [{ isSignal: true, alias: "emailError", required: false }] }], mobileError: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileError", required: false }] }], emailChange: [{ type: i0.Output, args: ["emailChange"] }], mobileChange: [{ type: i0.Output, args: ["mobileChange"] }] } });
|
|
12142
12374
|
|
|
12375
|
+
/** Editable permissions panel for an internal user: a roles multi-select (skeletons while `rolesLoading`) plus an active/inactive switch that defaults to on. */
|
|
12143
12376
|
class SceInternalUserPermissionsSectionComponent {
|
|
12144
12377
|
roleOptions = input([], ...(ngDevMode ? [{ debugName: "roleOptions" }] : /* istanbul ignore next */ []));
|
|
12145
12378
|
selectedRoleNumbers = input([], ...(ngDevMode ? [{ debugName: "selectedRoleNumbers" }] : /* istanbul ignore next */ []));
|
|
@@ -12155,6 +12388,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12155
12388
|
args: [{ selector: 'sce-internal-user-permissions-section', standalone: true, imports: [FormsModule, TranslatePipe, MultiSelect, SceSkeleton, SceSwitchComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-internal-user-permissions-section' }, template: "<div class=\"sce-internal-user-permissions-section__permissions\">\n <label for=\"int-user-permissions\" class=\"sce-internal-user-permissions-section__label\">\n {{ 'dashboard.internalUserForm.permissions' | translate }}\n </label>\n @if (rolesLoading()) {\n <sce-skeleton variant=\"input\" animation=\"wave\" aria-hidden=\"true\" />\n } @else {\n <p-multiSelect\n inputId=\"int-user-permissions\"\n [options]=\"roleOptions()\"\n [ngModel]=\"selectedRoleNumbers()\"\n (ngModelChange)=\"selectedRoleNumbersChange.emit($event)\"\n display=\"chip\"\n [filter]=\"true\"\n [placeholder]=\"'dashboard.internalUserForm.permissionsPlaceholder' | translate\"\n optionLabel=\"label\"\n optionValue=\"value\"\n appendTo=\"body\"\n styleClass=\"w-full\"\n />\n }\n</div>\n\n<div class=\"sce-internal-user-permissions-section__status\">\n <h4 class=\"sce-internal-user-permissions-section__status-title\">\n {{ 'dashboard.internalUserForm.isActive' | translate }}\n </h4>\n <sce-switch\n [checked]=\"isActive()\"\n [showLabel]=\"true\"\n [activeLabel]=\"'dashboard.status.active' | translate\"\n [inactiveLabel]=\"'dashboard.status.inactive' | translate\"\n (checkedChange)=\"isActiveChange.emit($event)\"\n />\n</div>\n", styles: [":host{display:grid;gap:var(--space-16)}.sce-internal-user-permissions-section__permissions{display:grid;gap:var(--space-24)}.sce-internal-user-permissions-section__label{margin:0;color:var(--text-text-secondary-700);font-size:var(--font-size-md);font-weight:var(--font-weight-semibold)}.sce-internal-user-permissions-section__status{display:flex;flex-direction:column;align-items:start;gap:var(--space-12);padding:var(--space-14) var(--space-16);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl)}.sce-internal-user-permissions-section__status-title{margin:0;color:var(--text-text-secondary-700);font-size:var(--font-size-md);font-weight:var(--font-weight-semibold)}\n"] }]
|
|
12156
12389
|
}], propDecorators: { roleOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "roleOptions", required: false }] }], selectedRoleNumbers: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedRoleNumbers", required: false }] }], rolesLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "rolesLoading", required: false }] }], isActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "isActive", required: false }] }], selectedRoleNumbersChange: [{ type: i0.Output, args: ["selectedRoleNumbersChange"] }], isActiveChange: [{ type: i0.Output, args: ["isActiveChange"] }] } });
|
|
12157
12390
|
|
|
12391
|
+
/** Segmented grid/list/map switch for the offices browser; fully controlled — it reports `viewModeChange` rather than holding the mode itself. */
|
|
12158
12392
|
class SceOfficesViewToggleComponent {
|
|
12159
12393
|
viewMode = input.required(...(ngDevMode ? [{ debugName: "viewMode" }] : /* istanbul ignore next */ []));
|
|
12160
12394
|
viewModeChange = output();
|
|
@@ -12166,6 +12400,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12166
12400
|
args: [{ selector: 'sce-offices-view-toggle', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-offices-view-toggle' }, imports: [TranslatePipe], template: "<button\n type=\"button\"\n class=\"sce-offices-view-toggle__btn\"\n [class.sce-offices-view-toggle__btn--active]=\"viewMode() === 'grid'\"\n [attr.aria-label]=\"'engineeringOffices.browser.viewMode.grid' | translate\"\n (click)=\"viewModeChange.emit('grid')\"\n>\n <img src=\"/assets/icons/microsoft.svg\" class=\"sce-offices-view-toggle__icon\" width=\"24\" height=\"24\" alt=\"\" aria-hidden=\"true\" />\n</button>\n\n<button\n type=\"button\"\n class=\"sce-offices-view-toggle__btn\"\n [class.sce-offices-view-toggle__btn--active]=\"viewMode() === 'list'\"\n [attr.aria-label]=\"'engineeringOffices.browser.viewMode.list' | translate\"\n (click)=\"viewModeChange.emit('list')\"\n>\n <img src=\"/assets/icons/menu.svg\" class=\"sce-offices-view-toggle__icon\" width=\"24\" height=\"24\" alt=\"\" aria-hidden=\"true\" />\n</button>\n\n<button\n type=\"button\"\n class=\"sce-offices-view-toggle__btn\"\n [class.sce-offices-view-toggle__btn--active]=\"viewMode() === 'map'\"\n [attr.aria-label]=\"'engineeringOffices.browser.viewMode.map' | translate\"\n (click)=\"viewModeChange.emit('map')\"\n>\n <img src=\"/assets/icons/maps.svg\" class=\"sce-offices-view-toggle__icon\" width=\"24\" height=\"24\" alt=\"\" aria-hidden=\"true\" />\n</button>\n", styles: [":host{display:inline-flex;gap:var(--space-2)}.sce-offices-view-toggle__btn{width:var(--space-44);height:var(--space-44);border:1px solid var(--border-subtle);border-radius:var(--space-10);background:var(--surface-primary);color:var(--cta-bg);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background-color .2s ease,color .2s ease}.sce-offices-view-toggle__btn--active{background:var(--cta-bg);color:var(--text-on-brand-primary);border-color:var(--cta-bg)}.sce-offices-view-toggle__btn--active .sce-offices-view-toggle__icon{filter:brightness(0) saturate(100%) invert(100%)}.sce-offices-view-toggle__icon{width:1.35rem;height:1.35rem}\n"] }]
|
|
12167
12401
|
}], propDecorators: { viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: true }] }], viewModeChange: [{ type: i0.Output, args: ["viewModeChange"] }] } });
|
|
12168
12402
|
|
|
12403
|
+
/** Paginated grid/list of engineering-office cards with skeleton and empty states; `viewMode` switches the layout and `skeletonCount` is floored at 4. */
|
|
12169
12404
|
class SceOfficesGridPanelComponent {
|
|
12170
12405
|
cards = input.required(...(ngDevMode ? [{ debugName: "cards" }] : /* istanbul ignore next */ []));
|
|
12171
12406
|
isLoading = input.required(...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
|
|
@@ -12201,6 +12436,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12201
12436
|
], template: "@if (isLoading()) {\n <div [class]=\"skeletonContainerClass()\">\n @for (i of skeletonIndices(); track i) {\n <sce-engineering-office-card-skeleton [viewMode]=\"viewMode()\" />\n }\n </div>\n} @else if (isEmpty()) {\n <div class=\"sce-offices-grid-panel__empty\" role=\"status\">\n <h3 class=\"sce-offices-grid-panel__empty-title\">{{ 'engineeringOffices.empty.title' | translate }}</h3>\n <p class=\"sce-offices-grid-panel__empty-subtitle\">{{ 'engineeringOffices.empty.subtitle' | translate }}</p>\n </div>\n} @else {\n <div [class]=\"cardsClass()\">\n @for (card of cards(); track card.href ?? card.name) {\n <sce-engineering-office-card\n [office]=\"card\"\n [viewMode]=\"viewMode()\"\n [bookmarked]=\"bookmarkedIds().has(card.href ?? card.name)\"\n (bookmarkClick)=\"bookmarkClick.emit(card)\"\n [bookmarkLabel]=\"bookmarkLabel()\"\n [ratingLabel]=\"ratingLabel()\"\n [locationLabel]=\"locationLabel()\"\n [otherLabel]=\"otherLabel()\"\n />\n }\n </div>\n\n <div class=\"sce-offices-grid-panel__footer\">\n <sce-paginator\n [page]=\"page()\"\n [pageSize]=\"pageSize()\"\n [totalItems]=\"totalItems()\"\n [locale]=\"locale()\"\n [pageSizeOptions]=\"pageSizeOptions()\"\n (pageChange)=\"pageChange.emit($event)\"\n (pageSizeChange)=\"pageSizeChange.emit($event)\"\n />\n </div>\n}\n", styles: [":host{display:grid;gap:var(--space-4)}.sce-offices-grid-panel__cards--grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-4)}.sce-offices-grid-panel__cards--list{display:grid;grid-template-columns:1fr;gap:.9rem}.sce-offices-grid-panel__footer{display:block}.sce-offices-grid-panel__empty{min-height:var(--size-280);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-2);padding:var(--space-8);border-radius:var(--radius-brand-sm);background:var(--color-surface);text-align:center}.sce-offices-grid-panel__empty-title{margin:0;font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-bold);font-size:var(--font-size-2xl-24);line-height:1.4;color:var(--text-text-primary-900)}.sce-offices-grid-panel__empty-subtitle{margin:0;max-width:42rem;font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-regular);font-size:var(--font-size-lg);line-height:1.5;color:var(--text-text-secondary-700)}@media(max-width:1200px){.sce-offices-grid-panel__cards--grid{grid-template-columns:1fr}}\n"] }]
|
|
12202
12437
|
}], propDecorators: { cards: [{ type: i0.Input, args: [{ isSignal: true, alias: "cards", required: true }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: true }] }], isEmpty: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEmpty", required: true }] }], viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], skeletonCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "skeletonCount", required: false }] }], page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: true }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: true }] }], totalItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalItems", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: true }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }], bookmarkedIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "bookmarkedIds", required: false }] }], bookmarkLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "bookmarkLabel", required: false }] }], ratingLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ratingLabel", required: false }] }], locationLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "locationLabel", required: false }] }], otherLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "otherLabel", required: false }] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], pageSizeChange: [{ type: i0.Output, args: ["pageSizeChange"] }], bookmarkClick: [{ type: i0.Output, args: ["bookmarkClick"] }] } });
|
|
12203
12438
|
|
|
12439
|
+
/** Wraps the OSM offices map with a fallback link shown when `mapLoadFailed`; emits `selectOffice` when a marker is picked. */
|
|
12204
12440
|
class SceOfficesMapPanelComponent {
|
|
12205
12441
|
mapPoints = input.required(...(ngDevMode ? [{ debugName: "mapPoints" }] : /* istanbul ignore next */ []));
|
|
12206
12442
|
mapLoadFailed = input.required(...(ngDevMode ? [{ debugName: "mapLoadFailed" }] : /* istanbul ignore next */ []));
|
|
@@ -12260,6 +12496,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12260
12496
|
}]
|
|
12261
12497
|
}], ctorParameters: () => [], propDecorators: { sceSliderValuenow: [{ type: i0.Input, args: [{ isSignal: true, alias: "sceSliderValuenow", required: false }] }] } });
|
|
12262
12498
|
|
|
12499
|
+
/** Fully controlled sort/size/budget/experience filter sidebar for the offices browser: it owns no state, taking every draft value, slider bound, and budget-histogram bar as a required input and emitting changes back — including the pre-flipped `*SliderLtr` values PrimeNG's slider needs under RTL. */
|
|
12263
12500
|
class SceOfficesFiltersSidebarComponent {
|
|
12264
12501
|
/** Current draft sort/filter values */
|
|
12265
12502
|
draftSort = input.required(...(ngDevMode ? [{ debugName: "draftSort" }] : /* istanbul ignore next */ []));
|
|
@@ -12991,6 +13228,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12991
13228
|
args: [{ host: { class: 'sce-tab-panel' }, selector: 'sce-tab-panel', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"sce-tab-panel__box\"\n [class.sce-tab-panel__box--active]=\"isActive()\"\n [attr.id]=\"'panel-' + panelId()\"\n [attr.aria-labelledby]=\"'tab-' + panelId()\"\n [attr.aria-hidden]=\"!isActive()\"\n role=\"tabpanel\"\n>\n @if (isActive()) {\n <ng-content />\n }\n</div>\n", styles: [":host{display:block}.sce-tab-panel__box{display:none;padding-block:var(--space-lg)}.sce-tab-panel__box--active{display:block;animation:sce-tab-panel-fade var(--transition-medium)}@keyframes sce-tab-panel-fade{0%{opacity:0;transform:translateY(var(--space-10))}to{opacity:1;transform:translateY(0)}}\n"] }]
|
|
12992
13229
|
}], propDecorators: { panelId: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelId", required: true }] }], activeId: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeId", required: false }] }] } });
|
|
12993
13230
|
|
|
13231
|
+
/** Label-and-value display rendered either as a standalone padded tile or, in `field` layout, as a plain row inside a parent panel. */
|
|
12994
13232
|
class SceBasicCardComponent {
|
|
12995
13233
|
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
12996
13234
|
value = input.required(...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
@@ -13007,6 +13245,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
13007
13245
|
}, template: "<div class=\"sce-basic-card__box\" [class.sce-basic-card__box--field]=\"layout() === 'field'\">\n <span class=\"sce-basic-card__label\">{{ label() | translate }}</span>\n <span class=\"sce-basic-card__value\">{{ value() | translate }}</span>\n</div>\n", styles: [":host{display:block}:host(.sce-basic-card--full-width){grid-column:1/-1;inline-size:100%}.sce-basic-card__box{display:flex;flex-direction:column;gap:var(--space-6);block-size:100%;padding:var(--space-16);border:var(--border-width-1) solid var(--color-border-subtle);border-radius:var(--radius-xl);background:var(--color-surface-primary)}.sce-basic-card__box--field{padding:0;border:0;border-radius:0;background:transparent}.sce-basic-card__label{font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);line-height:var(--line-height-normal);color:var(--color-text-muted);text-align:start}.sce-basic-card__value{font-size:var(--font-size-md);font-weight:var(--font-weight-semibold);line-height:var(--line-height-normal);color:var(--color-text-primary);text-align:start;overflow-wrap:anywhere}\n"] }]
|
|
13008
13246
|
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }] } });
|
|
13009
13247
|
|
|
13248
|
+
/** Renders a grid of `sce-nav-card` tiles from `items`; stays route-agnostic by taking a required `getItemRoute` factory that turns an item slug into a router link. */
|
|
13010
13249
|
class SceNavCardsListComponent {
|
|
13011
13250
|
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
13012
13251
|
/** Maps an item slug to a router link. Kept as an input so the organism stays route-agnostic. */
|
|
@@ -13109,6 +13348,7 @@ function hasObservationFor(item) {
|
|
|
13109
13348
|
return Boolean(observation.notes || observation.reasonLabel || observation.attachments?.length);
|
|
13110
13349
|
}
|
|
13111
13350
|
|
|
13351
|
+
/** Card summarising an entity by logo, name and description, listing its sectors as clickable chips (disabled ones emit nothing) with info and optional settings actions. */
|
|
13112
13352
|
class SceEntitySummaryCardComponent {
|
|
13113
13353
|
logo = input.required(...(ngDevMode ? [{ debugName: "logo" }] : /* istanbul ignore next */ []));
|
|
13114
13354
|
name = input.required(...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
@@ -13699,6 +13939,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
13699
13939
|
|
|
13700
13940
|
/** Tags without an explicit variant cycle through these, so a tag cloud stays visually varied. */
|
|
13701
13941
|
const VARIANT_CYCLE = ['brand', 'accent', 'info'];
|
|
13942
|
+
/** Titled tag cloud for knowledge articles; any tag without an explicit variant is assigned one by cycling through brand, accent and info so the cloud stays visually varied. */
|
|
13702
13943
|
class SceArticleTagsListComponent {
|
|
13703
13944
|
items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
13704
13945
|
titleKey = input('knowledge.tags', ...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
|
|
@@ -13907,5 +14148,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
13907
14148
|
* Generated bundle index. Do not edit.
|
|
13908
14149
|
*/
|
|
13909
14150
|
|
|
13910
|
-
export { Alert, Breadcrumb, Card, ColumnsEnum, DYNAMIC_MULTI_TYPES, DYNAMIC_NATIVE_TYPES, DashboardPageHeaderComponent, FileType, FormInput, LocalizedValuePipe, OtpInput, Popup, PopupModalBase, RESULT_STATE_ACTION_META, RESULT_STATE_PRESETS, SCE_MIRROR_LABEL_AS_PLACEHOLDER, SceAccordionComponent, SceAccountSwitcherComponent, SceAccountUserAssignDialogComponent, SceAccountUserDetailHeaderComponent, SceAccountUserEditDialogComponent, SceAccountUserPermissionsSectionComponent, SceAccountUserPersonalSectionComponent, SceAccountUserVerifyDialogComponent, SceAccountUsersTabsBarComponent, SceActionDialogComponent, SceApiErrorStateComponent, SceAreaChartComponent, SceArticleDetailComponent, SceArticleLayoutComponent, SceArticlePageComponent, SceArticleSidebarComponent, SceArticleTagsListComponent, SceAsyncPageGateComponent, SceAttachmentsListComponent, SceAuthLayoutComponent, SceBarChartComponent, SceBasicCardComponent, SceBidiIsolate, SceBrandLoaderComponent, SceBulletListComponent, SceBusinessStatusTagComponent, SceButton, SceButtonWithSelectionCount, SceCaptchaInput, SceCardRadioGroupComponent, SceCardsListPageComponent, SceCardsStatisticsComponent, SceCategoryTile, SceChartLegendComponent, SceCheckItem, SceCheckbox, SceChoiceCard, SceCircularProgress, SceConfirmDialogComponent, SceConfirmDialogDemoComponent, SceContactFormPanelComponent, SceContactInfoPanelComponent, SceContentBlockComponent, SceContractQrCodeComponent, SceContractRequestCardComponent, SceCopyButtonComponent, SceCopyRight, SceCriteriaSectionComponent, SceCurrencyInputComponent, SceCustomColsDirective, SceDashboardAccountRoleIconComponent, SceDashboardFeatureComingSoonComponent, SceDashboardLayoutComponent, SceDashboardTableFiltersComponent, SceDataRequestComparisonTableComponent, SceDataRequestCurrentSummaryComponent, SceDataRequestHeaderCardComponent, SceDataRequestMediaComparisonComponent, SceDataRequestProjectChangesComponent, SceDataRequestRejectionPanelComponent, SceDateFieldComponent, SceDatePickerModalComponent, SceDetailHeaderComponent, SceDialogShellComponent, SceDialogShellDemoComponent, SceDivider, SceDonutChartComponent, SceDynamicFormComponent, SceEmptyStateComponent, SceEngineeringOfficeCardComponent, SceEngineeringOfficeCardSkeletonComponent, SceEngineeringOfficeVerificationBadgeComponent, SceEntityInfoCardComponent, SceEntityProfileEditFormComponent, SceEntitySummaryCardComponent, SceEntityTypeCard, SceExportPdfButton, SceExportPdfContainerComponent, SceFaqItemCard, SceFeaturedOfficeCardComponent, SceFeaturedOfficeCardSkeletonComponent, SceFeedbackSectionComponent, SceFieldComponent, SceFileUploadZoneComponent, SceFileUploadZoneDemoComponent, SceFileViewerComponent, SceFileViewerDirective, SceFileViewerService, SceFilterCalendarComponent, SceFilterCalendarRangeComponent, SceFilterDropdownComponent, SceFilterFieldIconComponent, SceFilterFormComponent, SceFormCheckboxRadio, SceFormDialogComponent, SceFormDialogSectionComponent, SceFormError, SceFormFieldsSkeletonComponent, SceFormHint, SceFormLabel, SceFormPageLayoutComponent, SceFormRichTextComponent, SceGaugeChartComponent, SceGearsLoaderComponent, SceGenericTableComponent, SceGenericTableDemoComponent, SceGeoLocationFieldComponent, SceGlobalLoadingBarComponent, SceGoogleMapsLocationPickerComponent, SceGridExpansionDirective, SceGridTableComponent, SceGuidedTourComponent, SceHorizontalBarChartComponent, SceHorizontalWizardStepperComponent, SceIcon, SceIconCard, SceImageGallerySwapperComponent, SceImagePickerComponent, SceInfoFieldCardComponent, SceInfoFieldsGridComponent, SceInfoFieldsSkeletonComponent, SceInfoRowComponent, SceInlineApiErrorComponent, SceInquiryRequestCardComponent, SceInternalUserFormFieldsComponent, SceInternalUserPermissionsSectionComponent, SceInternalUserVerifySectionComponent, SceKnowledgeCenterCategoryGridComponent, SceLandingHeroHeaderComponent, SceLandingMobileMenuComponent, SceLandingNavComponent, SceLangToggleComponent, SceLatestContractsTableComponent, SceLineChartComponent, SceListPageLayoutComponent, SceLocationPickerDialogComponent, SceLoginAccountSelectStepComponent, SceLoginCompleteDataStepComponent, SceLoginCredentialsStepComponent, SceLoginErrorStepComponent, SceLoginOtpStepComponent, SceLoginUserTypeStepComponent, SceLogoutModalComponent, SceModalHostComponent, SceMultiSegmentBarChartComponent, SceMultiSegmentGaugeComponent, SceMultiSelectFieldComponent, SceNavCard, SceNavCardsListComponent, SceNewsletterSubscriptionDialogComponent, SceNotificationListComponent, SceNotificationListSkeletonComponent, SceNotificationTypeBadgeComponent, SceOfficeBrandLogoComponent, SceOfficeDetailHeroBodyComponent, SceOfficeDetailLoadingStateComponent, SceOfficeDetailNotFoundComponent, SceOfficeDetailOverviewPanelComponent, SceOfficeDetailProjectsPanelComponent, SceOfficeDetailReviewsPanelComponent, SceOfficeDetailTabsBarComponent, SceOfficeDetailsSkeletonComponent, SceOfficeLocationMapComponent, SceOfficeMetricCardComponent, SceOfficeMetricCardsRowComponent, SceOfficeProfileContactTabComponent, SceOfficeProfileEditBioSectionComponent, SceOfficeProfileEditContactSectionComponent, SceOfficeProfileEditMediaSectionComponent, SceOfficeProfileEditOfficialSectionComponent, SceOfficeProfileEditProjectsSectionComponent, SceOfficeProfileHeroComponent, SceOfficeProfileOfficialTabComponent, SceOfficeProfileOverviewTabComponent, SceOfficeProfileProjectDeleteDialogComponent, SceOfficeProfileProjectEditorDialogComponent, SceOfficeProfileProjectsTabComponent, SceOfficeProfileStatsRowComponent, SceOfficeProfileSubmitResultComponent, SceOfficeProjectGalleryComponent, SceOfficeProjectsSkeletonComponent, SceOfficesFiltersSidebarComponent, SceOfficesGridPanelComponent, SceOfficesMapPanelComponent, SceOfficesViewToggleComponent, SceOfflineBannerComponent, SceOptionGroup, SceOsmLeafletMapComponent, SceOsmLocationPickerComponent, SceOsmOfficesMapComponent, SceOverviewStatCardComponent, SceOverviewStatSparklineComponent, ScePackageFeatureCard, ScePageErrorComponent, ScePageHeaderComponent, ScePaginatorComponent, ScePaginatorDemoComponent, ScePasswordFieldComponent, ScePendingUpdateBannerComponent, ScePhoneNumberComponent, ScePieChartComponent, ScePlatformSettingsFieldsComponent, SceProfileHeroComponent, SceProfileHeroSkeletonComponent, SceProfileInfoSectionComponent, SceProfilePhotoEditDialogComponent, SceProfilePhotoSectionComponent, SceProgressBar, SceProgressCardComponent, ScePublicLegalProseComponent, SceQuickFilterBarComponent, SceRadioButtonComponent, SceRadioGroup, SceRadioGroupOption, SceRadioOptionCard, SceRangeBar, SceRegisterLayoutComponent, SceRelatedCardsListComponent, SceRequestCardSkeletonComponent, SceRequestDetailsCardComponent, SceRequestHeaderComponent, SceResourcesListComponent, SceResultStateComponent, SceReviewFieldTablePanelComponent, SceRingChartComponent, SceRingLoaderComponent, SceRowActionIconComponent, SceSaveFilterPopupComponent, SceScaleIndicatorComponent, SceScrollToTopButtonComponent, SceSearchableUsersListComponent, SceSelectFieldComponent, SceSelectableListWithSearchComponent, SceSelectionButton, SceServiceCardComponent, SceServiceCardStartButtonComponent, SceServiceDetailSkeletonComponent, SceServiceMiniCardComponent, SceServiceMiniCardSkeletonComponent, SceServicesTopFiltersComponent, SceSettingsLayoutComponent, SceSidebarComponent, SceSkeleton, SceSpinner, SceStackedDistributionChartComponent, SceStamp, SceStarRatingInputComponent, SceStatCardSkeletonComponent, SceStatGaugeComponent, SceStatRingComponent, SceStatsAnalyticsCardComponent, SceStatusPageComponent, SceStoreLocationsComponent, SceSummaryCardComponent, SceSupportContactCard, SceSupportThreadComponent, SceSwitchComponent, SceTabPanel, SceTableSkeletonComponent, SceTagComponent, SceTextFieldComponent, SceTextareaFieldComponent, SceThemeSwitcherComponent, SceThemeToggleButtonComponent, SceTimelineComponent, SceTooltip, SceUnitInputComponent, SceUnitInputFieldComponent, SceUserDropdownPickerComponent, SceUserVerifySectionPanelComponent, SceVerticalStepperComponent, SceVideoPlayerComponent, Stepper, Tabs, TabsInkbarRtlDirective, addHijriMonths, buildCalendarGrid, buildDynamicFormGroup, buildFieldValidators, detectFileType, getHijriYmdFromDate, isDataUri, mimeFromDataUri, parseValueToDate, resolveBusinessStatusPresentation, resolveBusinessStatusTone, scheduleLeafletResize, toBusinessStatusTableCell, toGregorianValue, toHijriValue };
|
|
14151
|
+
export { Alert, Breadcrumb, Card, ColumnsEnum, DYNAMIC_MULTI_TYPES, DYNAMIC_NATIVE_TYPES, DashboardPageHeaderComponent, FileType, FormInput, LocalizedValuePipe, OtpInput, Popup, PopupModalBase, RESULT_STATE_ACTION_META, RESULT_STATE_PRESETS, SCE_MIRROR_LABEL_AS_PLACEHOLDER, SceAccordionComponent, SceAccountSwitcherComponent, SceAccountUserAssignDialogComponent, SceAccountUserDetailHeaderComponent, SceAccountUserEditDialogComponent, SceAccountUserPermissionsSectionComponent, SceAccountUserPersonalSectionComponent, SceAccountUserVerifyDialogComponent, SceAccountUsersTabsBarComponent, SceActionDialogComponent, SceApiErrorStateComponent, SceAreaChartComponent, SceArticleDetailComponent, SceArticleLayoutComponent, SceArticlePageComponent, SceArticleSidebarComponent, SceArticleTagsListComponent, SceAsyncPageGateComponent, SceAttachmentsListComponent, SceAuthLayoutComponent, SceBarChartComponent, SceBasicCardComponent, SceBidiIsolate, SceBrandLoaderComponent, SceBulletListComponent, SceBusinessStatusTagComponent, SceButton, SceButtonWithSelectionCount, SceCaptchaInput, SceCardRadioGroupComponent, SceCardsListPageComponent, SceCardsStatisticsComponent, SceCategoryTile, SceChartLegendComponent, SceCheckItem, SceCheckbox, SceChoiceCard, SceCircularProgress, SceConfirmDialogComponent, SceConfirmDialogDemoComponent, SceContactFormPanelComponent, SceContactInfoPanelComponent, SceContentBlockComponent, SceContractQrCodeComponent, SceContractRequestCardComponent, SceCopyButtonComponent, SceCopyRight, SceCriteriaSectionComponent, SceCurrencyInputComponent, SceCustomColsDirective, SceDashboardAccountRoleIconComponent, SceDashboardFeatureComingSoonComponent, SceDashboardLayoutComponent, SceDashboardTableFiltersComponent, SceDataRequestComparisonTableComponent, SceDataRequestCurrentSummaryComponent, SceDataRequestHeaderCardComponent, SceDataRequestMediaComparisonComponent, SceDataRequestProjectChangesComponent, SceDataRequestRejectionPanelComponent, SceDateFieldComponent, SceDatePickerModalComponent, SceDetailHeaderComponent, SceDialogShellComponent, SceDialogShellDemoComponent, SceDivider, SceDonutChartComponent, SceDynamicFormComponent, SceEmptyStateComponent, SceEngineeringOfficeCardComponent, SceEngineeringOfficeCardSkeletonComponent, SceEngineeringOfficeVerificationBadgeComponent, SceEntityInfoCardComponent, SceEntityProfileEditFormComponent, SceEntitySummaryCardComponent, SceEntityTypeCard, SceExportPdfButton, SceExportPdfContainerComponent, SceFaqItemCard, SceFeaturedOfficeCardComponent, SceFeaturedOfficeCardSkeletonComponent, SceFeedbackSectionComponent, SceFieldComponent, SceFileUploadZoneComponent, SceFileUploadZoneDemoComponent, SceFileViewerComponent, SceFileViewerDirective, SceFileViewerService, SceFilterCalendarComponent, SceFilterCalendarRangeComponent, SceFilterDropdownComponent, SceFilterFieldIconComponent, SceFilterFormComponent, SceFormCheckboxRadio, SceFormDialogComponent, SceFormDialogSectionComponent, SceFormError, SceFormFieldsSkeletonComponent, SceFormHint, SceFormLabel, SceFormPageLayoutComponent, SceFormRichTextComponent, SceGaugeChartComponent, SceGearsLoaderComponent, SceGenericTableComponent, SceGenericTableDemoComponent, SceGeoLocationFieldComponent, SceGlobalLoadingBarComponent, SceGoogleMapsLocationPickerComponent, SceGridExpansionDirective, SceGridTableComponent, SceGuidedTourComponent, SceHorizontalBarChartComponent, SceHorizontalWizardStepperComponent, SceIcon, SceIconCard, SceImageGallerySwapperComponent, SceImagePickerComponent, SceInfoFieldCardComponent, SceInfoFieldsGridComponent, SceInfoFieldsSkeletonComponent, SceInfoRowComponent, SceInlineApiErrorComponent, SceInquiryRequestCardComponent, SceInternalUserFormFieldsComponent, SceInternalUserPermissionsSectionComponent, SceInternalUserVerifySectionComponent, SceKnowledgeCenterCategoryGridComponent, SceLandingHeroHeaderComponent, SceLandingMobileMenuComponent, SceLandingNavComponent, SceLangToggleComponent, SceLatestContractsTableComponent, SceLibraryAccessDeniedComponent, SceLineChartComponent, SceListPageLayoutComponent, SceLocationPickerDialogComponent, SceLoginAccountSelectStepComponent, SceLoginCompleteDataStepComponent, SceLoginCredentialsStepComponent, SceLoginErrorStepComponent, SceLoginOtpStepComponent, SceLoginUserTypeStepComponent, SceLogoutModalComponent, SceModalHostComponent, SceMultiSegmentBarChartComponent, SceMultiSegmentGaugeComponent, SceMultiSelectFieldComponent, SceNavCard, SceNavCardsListComponent, SceNewsletterSubscriptionDialogComponent, SceNotificationListComponent, SceNotificationListSkeletonComponent, SceNotificationTypeBadgeComponent, SceOfficeBrandLogoComponent, SceOfficeDetailHeroBodyComponent, SceOfficeDetailLoadingStateComponent, SceOfficeDetailNotFoundComponent, SceOfficeDetailOverviewPanelComponent, SceOfficeDetailProjectsPanelComponent, SceOfficeDetailReviewsPanelComponent, SceOfficeDetailTabsBarComponent, SceOfficeDetailsSkeletonComponent, SceOfficeLocationMapComponent, SceOfficeMetricCardComponent, SceOfficeMetricCardsRowComponent, SceOfficeProfileContactTabComponent, SceOfficeProfileEditBioSectionComponent, SceOfficeProfileEditContactSectionComponent, SceOfficeProfileEditMediaSectionComponent, SceOfficeProfileEditOfficialSectionComponent, SceOfficeProfileEditProjectsSectionComponent, SceOfficeProfileHeroComponent, SceOfficeProfileOfficialTabComponent, SceOfficeProfileOverviewTabComponent, SceOfficeProfileProjectDeleteDialogComponent, SceOfficeProfileProjectEditorDialogComponent, SceOfficeProfileProjectsTabComponent, SceOfficeProfileStatsRowComponent, SceOfficeProfileSubmitResultComponent, SceOfficeProjectGalleryComponent, SceOfficeProjectsSkeletonComponent, SceOfficesFiltersSidebarComponent, SceOfficesGridPanelComponent, SceOfficesMapPanelComponent, SceOfficesViewToggleComponent, SceOfflineBannerComponent, SceOptionGroup, SceOsmLeafletMapComponent, SceOsmLocationPickerComponent, SceOsmOfficesMapComponent, SceOverviewStatCardComponent, SceOverviewStatSparklineComponent, ScePackageFeatureCard, ScePageErrorComponent, ScePageHeaderComponent, ScePaginatorComponent, ScePaginatorDemoComponent, ScePasswordFieldComponent, ScePendingUpdateBannerComponent, ScePhoneNumberComponent, ScePieChartComponent, ScePlatformSettingsFieldsComponent, SceProfileHeroComponent, SceProfileHeroSkeletonComponent, SceProfileInfoSectionComponent, SceProfilePhotoEditDialogComponent, SceProfilePhotoSectionComponent, SceProgressBar, SceProgressCardComponent, ScePublicLegalProseComponent, SceQuickFilterBarComponent, SceRadioButtonComponent, SceRadioGroup, SceRadioGroupOption, SceRadioOptionCard, SceRangeBar, SceRegisterLayoutComponent, SceRelatedCardsListComponent, SceRequestCardSkeletonComponent, SceRequestDetailsCardComponent, SceRequestHeaderComponent, SceResourcesListComponent, SceResultStateComponent, SceReviewFieldTablePanelComponent, SceRingChartComponent, SceRingLoaderComponent, SceRowActionIconComponent, SceSaveFilterPopupComponent, SceScaleIndicatorComponent, SceScrollToTopButtonComponent, SceSearchableUsersListComponent, SceSelectFieldComponent, SceSelectableListWithSearchComponent, SceSelectionButton, SceServiceCardComponent, SceServiceCardStartButtonComponent, SceServiceDetailSkeletonComponent, SceServiceMiniCardComponent, SceServiceMiniCardSkeletonComponent, SceServicesTopFiltersComponent, SceSettingsLayoutComponent, SceSidebarComponent, SceSkeleton, SceSpinner, SceStackedDistributionChartComponent, SceStamp, SceStarRatingInputComponent, SceStatCardSkeletonComponent, SceStatGaugeComponent, SceStatRingComponent, SceStatsAnalyticsCardComponent, SceStatusPageComponent, SceStoreLocationsComponent, SceSummaryCardComponent, SceSupportContactCard, SceSupportThreadComponent, SceSwitchComponent, SceTabPanel, SceTableSkeletonComponent, SceTagComponent, SceTextFieldComponent, SceTextareaFieldComponent, SceThemeSwitcherComponent, SceThemeToggleButtonComponent, SceTimelineComponent, SceTooltip, SceUnitInputComponent, SceUnitInputFieldComponent, SceUserDropdownPickerComponent, SceUserVerifySectionPanelComponent, SceVerticalStepperComponent, SceVideoPlayerComponent, Stepper, Tabs, TabsInkbarRtlDirective, addHijriMonths, buildCalendarGrid, buildDynamicFormGroup, buildFieldValidators, detectFileType, getHijriYmdFromDate, isDataUri, mimeFromDataUri, parseValueToDate, resolveBusinessStatusPresentation, resolveBusinessStatusTone, scheduleLeafletResize, toBusinessStatusTableCell, toGregorianValue, toHijriValue };
|
|
13911
14152
|
//# sourceMappingURL=moatamed-sce-ui-components.mjs.map
|