@moatamed-sce/ui-components 0.1.1 → 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.
|
@@ -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 */ []));
|
|
@@ -10089,6 +10231,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10089
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"] }]
|
|
10090
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"] }] } });
|
|
10091
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. */
|
|
10092
10235
|
class SceAuthLayoutComponent {
|
|
10093
10236
|
/** Logo image URL for the auth header */
|
|
10094
10237
|
logoSrc = input('', ...(ngDevMode ? [{ debugName: "logoSrc" }] : /* istanbul ignore next */ []));
|
|
@@ -10163,6 +10306,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10163
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"] }]
|
|
10164
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 }] }] } });
|
|
10165
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. */
|
|
10166
10310
|
class SceSelectableListWithSearchComponent {
|
|
10167
10311
|
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
10168
10312
|
items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
@@ -10228,6 +10372,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10228
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"] }]
|
|
10229
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"] }] } });
|
|
10230
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. */
|
|
10231
10376
|
class SceQuickFilterBarComponent {
|
|
10232
10377
|
activeFilters = input([], ...(ngDevMode ? [{ debugName: "activeFilters" }] : /* istanbul ignore next */ []));
|
|
10233
10378
|
showSaveFilter = input(true, ...(ngDevMode ? [{ debugName: "showSaveFilter" }] : /* istanbul ignore next */ []));
|
|
@@ -10250,6 +10395,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10250
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"] }]
|
|
10251
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"] }] } });
|
|
10252
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. */
|
|
10253
10399
|
class SceUserVerifySectionPanelComponent {
|
|
10254
10400
|
// ── Inputs ──
|
|
10255
10401
|
step = input(1, ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
|
|
@@ -10363,6 +10509,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10363
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"] }]
|
|
10364
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"] }] } });
|
|
10365
10511
|
|
|
10512
|
+
/** Renderer the file viewer picks for a file; `Unsupported` shows a download-only fallback. */
|
|
10366
10513
|
var FileType;
|
|
10367
10514
|
(function (FileType) {
|
|
10368
10515
|
FileType["Image"] = "image";
|
|
@@ -10703,6 +10850,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10703
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"] }]
|
|
10704
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"] }] } });
|
|
10705
10852
|
|
|
10853
|
+
/** User list with a client-side name search box; filtering happens internally and only `deleteUser` is emitted to the host. */
|
|
10706
10854
|
class SceSearchableUsersListComponent {
|
|
10707
10855
|
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
10708
10856
|
users = input([], ...(ngDevMode ? [{ debugName: "users" }] : /* istanbul ignore next */ []));
|
|
@@ -10731,6 +10879,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10731
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"] }]
|
|
10732
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"] }] } });
|
|
10733
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. */
|
|
10734
10883
|
class SceDetailHeaderComponent {
|
|
10735
10884
|
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
10736
10885
|
breadcrumbs = input([], ...(ngDevMode ? [{ debugName: "breadcrumbs" }] : /* istanbul ignore next */ []));
|
|
@@ -10791,6 +10940,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10791
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"] }]
|
|
10792
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 }] }] } });
|
|
10793
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`). */
|
|
10794
10944
|
class SceRequestHeaderComponent {
|
|
10795
10945
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
10796
10946
|
requestId = input.required(...(ngDevMode ? [{ debugName: "requestId" }] : /* istanbul ignore next */ []));
|
|
@@ -10806,6 +10956,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10806
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"] }]
|
|
10807
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 }] }] } });
|
|
10808
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. */
|
|
10809
10960
|
class SceRequestDetailsCardComponent {
|
|
10810
10961
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
10811
10962
|
requestId = input.required(...(ngDevMode ? [{ debugName: "requestId" }] : /* istanbul ignore next */ []));
|
|
@@ -10828,6 +10979,7 @@ function resolveAttachmentType(attachment) {
|
|
|
10828
10979
|
const ext = attachment.name.split('.').pop()?.toLowerCase() ?? '';
|
|
10829
10980
|
return ext === 'pdf' || ext === 'doc' || ext === 'docx' ? 'pdf' : 'image';
|
|
10830
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. */
|
|
10831
10983
|
class SceAttachmentsListComponent {
|
|
10832
10984
|
attachments = input([], ...(ngDevMode ? [{ debugName: "attachments" }] : /* istanbul ignore next */ []));
|
|
10833
10985
|
titleKey = input('common.attachments', ...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
|
|
@@ -10855,6 +11007,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10855
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"] }]
|
|
10856
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"] }] } });
|
|
10857
11009
|
|
|
11010
|
+
/** Profile banner showing an avatar (`avatarUrl`, falling back to a person icon), `name`, and `role`. */
|
|
10858
11011
|
class SceProfileHeroComponent {
|
|
10859
11012
|
name = input('', ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
10860
11013
|
role = input('', ...(ngDevMode ? [{ debugName: "role" }] : /* istanbul ignore next */ []));
|
|
@@ -10867,6 +11020,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10867
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"] }]
|
|
10868
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 }] }] } });
|
|
10869
11022
|
|
|
11023
|
+
/** Titled list of downloadable/linked resources from `items`; `titleKey` defaults to the knowledge-centre resources heading. */
|
|
10870
11024
|
class SceResourcesListComponent {
|
|
10871
11025
|
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
10872
11026
|
titleKey = input('knowledgeCenter.resources', ...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
|
|
@@ -10878,6 +11032,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10878
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"] }]
|
|
10879
11033
|
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: false }] }] } });
|
|
10880
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. */
|
|
10881
11036
|
class SceFeedbackSectionComponent {
|
|
10882
11037
|
questionKey = input('knowledge.helpful', ...(ngDevMode ? [{ debugName: "questionKey" }] : /* istanbul ignore next */ []));
|
|
10883
11038
|
yesKey = input('common.YES', ...(ngDevMode ? [{ debugName: "yesKey" }] : /* istanbul ignore next */ []));
|
|
@@ -10909,6 +11064,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10909
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"] }]
|
|
10910
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"] }] } });
|
|
10911
11066
|
|
|
11067
|
+
/** Renders a titled grid of related-content cards from `items`, each optionally linking to its own `route`. */
|
|
10912
11068
|
class SceRelatedCardsListComponent {
|
|
10913
11069
|
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
10914
11070
|
titleKey = input('', ...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
|
|
@@ -10928,6 +11084,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10928
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"] }]
|
|
10929
11085
|
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: false }] }] } });
|
|
10930
11086
|
|
|
11087
|
+
/** Loading placeholder for the office-detail page, rendering the hero header plus a skeleton body matching the currently active tab. */
|
|
10931
11088
|
class SceOfficeDetailLoadingStateComponent {
|
|
10932
11089
|
activeTab = input('overview', ...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
|
|
10933
11090
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SceOfficeDetailLoadingStateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -10938,6 +11095,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10938
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"] }]
|
|
10939
11096
|
}], propDecorators: { activeTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTab", required: false }] }] } });
|
|
10940
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. */
|
|
10941
11099
|
class SceOfficeDetailNotFoundComponent {
|
|
10942
11100
|
breadcrumbs = input([], ...(ngDevMode ? [{ debugName: "breadcrumbs" }] : /* istanbul ignore next */ []));
|
|
10943
11101
|
/** The page owns its own navigation links, so the preset's `back` button is suppressed. */
|
|
@@ -10950,6 +11108,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10950
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"] }]
|
|
10951
11109
|
}], propDecorators: { breadcrumbs: [{ type: i0.Input, args: [{ isSignal: true, alias: "breadcrumbs", required: false }] }] } });
|
|
10952
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. */
|
|
10953
11112
|
class SceOfficeDetailHeroBodyComponent {
|
|
10954
11113
|
officeName = input.required(...(ngDevMode ? [{ debugName: "officeName" }] : /* istanbul ignore next */ []));
|
|
10955
11114
|
verificationStatus = input(null, ...(ngDevMode ? [{ debugName: "verificationStatus" }] : /* istanbul ignore next */ []));
|
|
@@ -10968,6 +11127,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10968
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"] }]
|
|
10969
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"] }] } });
|
|
10970
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. */
|
|
10971
11131
|
class SceOfficeDetailTabsBarComponent {
|
|
10972
11132
|
tabItems = input.required(...(ngDevMode ? [{ debugName: "tabItems" }] : /* istanbul ignore next */ []));
|
|
10973
11133
|
activeTab = input.required(...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
|
|
@@ -10982,6 +11142,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10982
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"] }]
|
|
10983
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"] }] } });
|
|
10984
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. */
|
|
10985
11146
|
class SceOfficeDetailOverviewPanelComponent {
|
|
10986
11147
|
officeBio = input('', ...(ngDevMode ? [{ debugName: "officeBio" }] : /* istanbul ignore next */ []));
|
|
10987
11148
|
locationText = input('', ...(ngDevMode ? [{ debugName: "locationText" }] : /* istanbul ignore next */ []));
|
|
@@ -10996,6 +11157,7 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "21.2.17", n
|
|
|
10996
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"] }]
|
|
10997
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 }] }] } }) });
|
|
10998
11159
|
|
|
11160
|
+
/** Projects tab of the office-detail page, rendering each of the office's projects alongside its image gallery. */
|
|
10999
11161
|
class SceOfficeDetailProjectsPanelComponent {
|
|
11000
11162
|
projects = input([], ...(ngDevMode ? [{ debugName: "projects" }] : /* istanbul ignore next */ []));
|
|
11001
11163
|
projectGalleryImages = input([], ...(ngDevMode ? [{ debugName: "projectGalleryImages" }] : /* istanbul ignore next */ []));
|
|
@@ -11008,6 +11170,7 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "21.2.17", n
|
|
|
11008
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"] }]
|
|
11009
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 }] }] } }) });
|
|
11010
11172
|
|
|
11173
|
+
/** Reviews tab of the office-detail page, showing the overall rating, the per-star rating distribution and the individual reviews. */
|
|
11011
11174
|
class SceOfficeDetailReviewsPanelComponent {
|
|
11012
11175
|
reviews = input([], ...(ngDevMode ? [{ debugName: "reviews" }] : /* istanbul ignore next */ []));
|
|
11013
11176
|
totalReviews = input(0, ...(ngDevMode ? [{ debugName: "totalReviews" }] : /* istanbul ignore next */ []));
|
|
@@ -11072,6 +11235,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11072
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"] }]
|
|
11073
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 }] }] } });
|
|
11074
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. */
|
|
11075
11239
|
class LocalizedValuePipe {
|
|
11076
11240
|
translate = inject(TranslateService);
|
|
11077
11241
|
transform(obj, key, options) {
|
|
@@ -11100,6 +11264,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11100
11264
|
}]
|
|
11101
11265
|
}] });
|
|
11102
11266
|
|
|
11267
|
+
/** Displays a phone number with an optional leading icon and a copy-to-clipboard button (shown by default). */
|
|
11103
11268
|
class ScePhoneNumberComponent {
|
|
11104
11269
|
value = input.required(...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
11105
11270
|
showCopy = input(true, ...(ngDevMode ? [{ debugName: "showCopy" }] : /* istanbul ignore next */ []));
|
|
@@ -11113,6 +11278,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11113
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"] }]
|
|
11114
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 }] }] } });
|
|
11115
11280
|
|
|
11281
|
+
/** Title-and-description row with a trailing edit button (shown by default, labelled from the translated "edit" key unless overridden). */
|
|
11116
11282
|
class SceInfoRowComponent {
|
|
11117
11283
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
11118
11284
|
description = input.required(...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
|
|
@@ -11130,6 +11296,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11130
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"] }]
|
|
11131
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"] }] } });
|
|
11132
11298
|
|
|
11299
|
+
/** Compact summary tile pairing an icon with a label, a primary value and an optional secondary value. */
|
|
11133
11300
|
class SceSummaryCardComponent {
|
|
11134
11301
|
icon = input.required(...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
11135
11302
|
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
@@ -11143,6 +11310,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11143
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"] }]
|
|
11144
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 }] }] } });
|
|
11145
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. */
|
|
11146
11314
|
class SceEntityInfoCardComponent {
|
|
11147
11315
|
labelKey = input.required(...(ngDevMode ? [{ debugName: "labelKey" }] : /* istanbul ignore next */ []));
|
|
11148
11316
|
nameKey = input('', ...(ngDevMode ? [{ debugName: "nameKey" }] : /* istanbul ignore next */ []));
|
|
@@ -11169,6 +11337,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11169
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"] }]
|
|
11170
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 }] }] } });
|
|
11171
11339
|
|
|
11340
|
+
/** Card that either shows a completion progress bar or, in `cta` mode, an illustrated call-to-action button emitting `nextStep`. */
|
|
11172
11341
|
class SceProgressCardComponent {
|
|
11173
11342
|
mode = input('progress', ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
11174
11343
|
titleKey = input('', ...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
|
|
@@ -11190,6 +11359,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11190
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"] }]
|
|
11191
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"] }] } });
|
|
11192
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. */
|
|
11193
11363
|
class SceContentBlockComponent {
|
|
11194
11364
|
contentKey = input.required(...(ngDevMode ? [{ debugName: "contentKey" }] : /* istanbul ignore next */ []));
|
|
11195
11365
|
contentHtml = input(null, ...(ngDevMode ? [{ debugName: "contentHtml" }] : /* istanbul ignore next */ []));
|
|
@@ -11201,6 +11371,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11201
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"] }]
|
|
11202
11372
|
}], propDecorators: { contentKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentKey", required: true }] }], contentHtml: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentHtml", required: false }] }] } });
|
|
11203
11373
|
|
|
11374
|
+
/** Renders `items` (translation keys) as an icon-bulleted list, laid out across `maxColumns` columns (default 1). */
|
|
11204
11375
|
class SceBulletListComponent {
|
|
11205
11376
|
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
11206
11377
|
maxColumns = input(1, ...(ngDevMode ? [{ debugName: "maxColumns" }] : /* istanbul ignore next */ []));
|
|
@@ -11212,6 +11383,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11212
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"] }]
|
|
11213
11384
|
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], maxColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxColumns", required: false }] }] } });
|
|
11214
11385
|
|
|
11386
|
+
/** Dashboard KPI card showing a headline value, an up/down trend percentage and an optional sparkline chart. */
|
|
11215
11387
|
class SceStatsAnalyticsCardComponent {
|
|
11216
11388
|
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
11217
11389
|
titleLinkText = input('', ...(ngDevMode ? [{ debugName: "titleLinkText" }] : /* istanbul ignore next */ []));
|
|
@@ -11232,6 +11404,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11232
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"] }]
|
|
11233
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 }] }] } });
|
|
11234
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. */
|
|
11235
11408
|
class SceOfficeProfileSubmitResultComponent {
|
|
11236
11409
|
result = input.required(...(ngDevMode ? [{ debugName: "result" }] : /* istanbul ignore next */ []));
|
|
11237
11410
|
viewProfile = output();
|
|
@@ -11244,6 +11417,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11244
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"] }]
|
|
11245
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"] }] } });
|
|
11246
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. */
|
|
11247
11421
|
class ScePendingUpdateBannerComponent {
|
|
11248
11422
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ScePendingUpdateBannerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
11249
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 });
|
|
@@ -11253,6 +11427,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11253
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"] }]
|
|
11254
11428
|
}] });
|
|
11255
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. */
|
|
11256
11431
|
class SceOfficeProfileEditBioSectionComponent {
|
|
11257
11432
|
form = input.required(...(ngDevMode ? [{ debugName: "form" }] : /* istanbul ignore next */ []));
|
|
11258
11433
|
serviceOptions = input.required(...(ngDevMode ? [{ debugName: "serviceOptions" }] : /* istanbul ignore next */ []));
|
|
@@ -11266,6 +11441,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11266
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"] }]
|
|
11267
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 }] }] } });
|
|
11268
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. */
|
|
11269
11445
|
class SceOfficeProfileEditMediaSectionComponent {
|
|
11270
11446
|
locale = input('ar', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
|
|
11271
11447
|
coverExistingUrl = input('', ...(ngDevMode ? [{ debugName: "coverExistingUrl" }] : /* istanbul ignore next */ []));
|
|
@@ -11286,6 +11462,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11286
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"] }]
|
|
11287
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"] }] } });
|
|
11288
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. */
|
|
11289
11466
|
class SceOfficeProfileEditOfficialSectionComponent {
|
|
11290
11467
|
form = input.required(...(ngDevMode ? [{ debugName: "form" }] : /* istanbul ignore next */ []));
|
|
11291
11468
|
bankOptions = input.required(...(ngDevMode ? [{ debugName: "bankOptions" }] : /* istanbul ignore next */ []));
|
|
@@ -11310,6 +11487,7 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "21.2.17", n
|
|
|
11310
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"] }]
|
|
11311
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"] }] } }) });
|
|
11312
11489
|
|
|
11490
|
+
/** Contact section of the office-profile edit form, binding the parent's `FormGroup` to the contact detail inputs. */
|
|
11313
11491
|
class SceOfficeProfileEditContactSectionComponent {
|
|
11314
11492
|
form = input.required(...(ngDevMode ? [{ debugName: "form" }] : /* istanbul ignore next */ []));
|
|
11315
11493
|
dir = input('rtl', ...(ngDevMode ? [{ debugName: "dir" }] : /* istanbul ignore next */ []));
|
|
@@ -11321,6 +11499,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11321
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"] }]
|
|
11322
11500
|
}], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }] } });
|
|
11323
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. */
|
|
11324
11503
|
class SceOfficeProfileEditProjectsSectionComponent {
|
|
11325
11504
|
projects = input.required(...(ngDevMode ? [{ debugName: "projects" }] : /* istanbul ignore next */ []));
|
|
11326
11505
|
addProject = output();
|
|
@@ -11339,6 +11518,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11339
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"] }]
|
|
11340
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"] }] } });
|
|
11341
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. */
|
|
11342
11522
|
class SceOfficeProfileProjectEditorDialogComponent {
|
|
11343
11523
|
visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
11344
11524
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
@@ -11362,6 +11542,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11362
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"] }]
|
|
11363
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"] }] } });
|
|
11364
11544
|
|
|
11545
|
+
/** Confirmation dialog asking the user to confirm deleting an office project. */
|
|
11365
11546
|
class SceOfficeProfileProjectDeleteDialogComponent {
|
|
11366
11547
|
visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
11367
11548
|
closeDialog = output();
|
|
@@ -11374,6 +11555,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11374
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"] }]
|
|
11375
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"] }] } });
|
|
11376
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. */
|
|
11377
11559
|
class SceOfficeProfileHeroComponent {
|
|
11378
11560
|
bannerUrl = input(null, ...(ngDevMode ? [{ debugName: "bannerUrl" }] : /* istanbul ignore next */ []));
|
|
11379
11561
|
logoUrl = input(null, ...(ngDevMode ? [{ debugName: "logoUrl" }] : /* istanbul ignore next */ []));
|
|
@@ -11406,6 +11588,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11406
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"] }]
|
|
11407
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"] }] } });
|
|
11408
11590
|
|
|
11591
|
+
/** Row of headline office statistics: years of experience, project count and service count. */
|
|
11409
11592
|
class SceOfficeProfileStatsRowComponent {
|
|
11410
11593
|
yearsOfExperience = input('—', ...(ngDevMode ? [{ debugName: "yearsOfExperience" }] : /* istanbul ignore next */ []));
|
|
11411
11594
|
projectsCount = input(0, ...(ngDevMode ? [{ debugName: "projectsCount" }] : /* istanbul ignore next */ []));
|
|
@@ -11418,6 +11601,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11418
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"] }]
|
|
11419
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 }] }] } });
|
|
11420
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. */
|
|
11421
11605
|
class SceOfficeProfileOverviewTabComponent {
|
|
11422
11606
|
summary = input('', ...(ngDevMode ? [{ debugName: "summary" }] : /* istanbul ignore next */ []));
|
|
11423
11607
|
servicesDisplay = input([], ...(ngDevMode ? [{ debugName: "servicesDisplay" }] : /* istanbul ignore next */ []));
|
|
@@ -11433,6 +11617,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11433
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"] }]
|
|
11434
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 }] }] } });
|
|
11435
11619
|
|
|
11620
|
+
/** Projects tab of the office profile view, rendering each project with its image gallery and showing skeletons while the project images load. */
|
|
11436
11621
|
class SceOfficeProfileProjectsTabComponent {
|
|
11437
11622
|
displayProjects = input([], ...(ngDevMode ? [{ debugName: "displayProjects" }] : /* istanbul ignore next */ []));
|
|
11438
11623
|
projectImagesLoading = input(false, ...(ngDevMode ? [{ debugName: "projectImagesLoading" }] : /* istanbul ignore next */ []));
|
|
@@ -11445,6 +11630,7 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "21.2.17", n
|
|
|
11445
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"] }]
|
|
11446
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 }] }] } }) });
|
|
11447
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. */
|
|
11448
11634
|
class SceOfficeProfileContactTabComponent {
|
|
11449
11635
|
email = input('', ...(ngDevMode ? [{ debugName: "email" }] : /* istanbul ignore next */ []));
|
|
11450
11636
|
phone = input('', ...(ngDevMode ? [{ debugName: "phone" }] : /* istanbul ignore next */ []));
|
|
@@ -11460,6 +11646,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11460
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"] }]
|
|
11461
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 }] }] } });
|
|
11462
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. */
|
|
11463
11650
|
class SceOfficeProfileOfficialTabComponent {
|
|
11464
11651
|
vatNumber = input('', ...(ngDevMode ? [{ debugName: "vatNumber" }] : /* istanbul ignore next */ []));
|
|
11465
11652
|
commercialRegistrationNumber = input('', ...(ngDevMode ? [{ debugName: "commercialRegistrationNumber" }] : /* istanbul ignore next */ []));
|
|
@@ -11478,6 +11665,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11478
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"] }]
|
|
11479
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 }] }] } });
|
|
11480
11667
|
|
|
11668
|
+
/** Collapsible `<details>` panel (open by default) showing the reviewer's rejection note, or an em dash when the note is empty. */
|
|
11481
11669
|
class SceDataRequestRejectionPanelComponent {
|
|
11482
11670
|
/** The rejection note text from the API. Empty string shows a dash. */
|
|
11483
11671
|
note = input('', ...(ngDevMode ? [{ debugName: "note" }] : /* istanbul ignore next */ []));
|
|
@@ -11513,6 +11701,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11513
11701
|
}]
|
|
11514
11702
|
}], propDecorators: { note: [{ type: i0.Input, args: [{ isSignal: true, alias: "note", required: false }] }] } });
|
|
11515
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. */
|
|
11516
11705
|
class SceDataRequestHeaderCardComponent {
|
|
11517
11706
|
/** Human-readable request number (e.g. "REQ-00123"). */
|
|
11518
11707
|
requestNumber = input.required(...(ngDevMode ? [{ debugName: "requestNumber" }] : /* istanbul ignore next */ []));
|
|
@@ -11551,6 +11740,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11551
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" }]
|
|
11552
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 }] }] } });
|
|
11553
11742
|
|
|
11743
|
+
/** Titled table contrasting each field's current and updated value in a data-change request, flagging the rows that changed. */
|
|
11554
11744
|
class SceDataRequestComparisonTableComponent {
|
|
11555
11745
|
/** Section heading text. */
|
|
11556
11746
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
@@ -11564,6 +11754,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11564
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" }]
|
|
11565
11755
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }] } });
|
|
11566
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. */
|
|
11567
11758
|
class SceDataRequestMediaComparisonComponent {
|
|
11568
11759
|
/** Block heading (e.g. "Logo" or "Cover"). */
|
|
11569
11760
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
@@ -11587,6 +11778,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11587
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" }]
|
|
11588
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"] }] } });
|
|
11589
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. */
|
|
11590
11782
|
class SceNewsletterSubscriptionDialogComponent {
|
|
11591
11783
|
translate = inject(TranslateService);
|
|
11592
11784
|
visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
@@ -11693,6 +11885,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11693
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"] }]
|
|
11694
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"] }] } });
|
|
11695
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`. */
|
|
11696
11889
|
class SceProfilePhotoSectionComponent {
|
|
11697
11890
|
/** Currently displayed photo URL. Null or undefined shows the default avatar. */
|
|
11698
11891
|
photoUrl = input(null, ...(ngDevMode ? [{ debugName: "photoUrl" }] : /* istanbul ignore next */ []));
|
|
@@ -11740,6 +11933,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11740
11933
|
}] } });
|
|
11741
11934
|
|
|
11742
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`. */
|
|
11743
11937
|
class SceProfileInfoSectionComponent {
|
|
11744
11938
|
/** Resolved profile data for the read (view) mode. Null shows skeleton. */
|
|
11745
11939
|
profile = input(null, ...(ngDevMode ? [{ debugName: "profile" }] : /* istanbul ignore next */ []));
|
|
@@ -11844,6 +12038,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11844
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"] }]
|
|
11845
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"] }] } });
|
|
11846
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. */
|
|
11847
12042
|
class SceDataRequestCurrentSummaryComponent {
|
|
11848
12043
|
currentPhone = input('—', ...(ngDevMode ? [{ debugName: "currentPhone" }] : /* istanbul ignore next */ []));
|
|
11849
12044
|
currentEmail = input('—', ...(ngDevMode ? [{ debugName: "currentEmail" }] : /* istanbul ignore next */ []));
|
|
@@ -11858,6 +12053,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11858
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"] }]
|
|
11859
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 }] }] } });
|
|
11860
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. */
|
|
11861
12057
|
class SceDataRequestProjectChangesComponent {
|
|
11862
12058
|
projectChanges = input([], ...(ngDevMode ? [{ debugName: "projectChanges" }] : /* istanbul ignore next */ []));
|
|
11863
12059
|
isSystemUser = input(false, ...(ngDevMode ? [{ debugName: "isSystemUser" }] : /* istanbul ignore next */ []));
|
|
@@ -11870,6 +12066,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11870
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"] }]
|
|
11871
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"] }] } });
|
|
11872
12068
|
|
|
12069
|
+
/** Grid of knowledge-center categories that also owns its loading, error and empty states and emits category/retry/ticket actions. */
|
|
11873
12070
|
class SceKnowledgeCenterCategoryGridComponent {
|
|
11874
12071
|
categories = input([], ...(ngDevMode ? [{ debugName: "categories" }] : /* istanbul ignore next */ []));
|
|
11875
12072
|
isLoadingCategories = input(false, ...(ngDevMode ? [{ debugName: "isLoadingCategories" }] : /* istanbul ignore next */ []));
|
|
@@ -11886,6 +12083,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11886
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"] }]
|
|
11887
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"] }] } });
|
|
11888
12085
|
|
|
12086
|
+
/** Read-only contact details panel rendering working hours, response time, phone number, email link and Instagram/Twitter links. */
|
|
11889
12087
|
class SceContactInfoPanelComponent {
|
|
11890
12088
|
workingHoursValue = input('', ...(ngDevMode ? [{ debugName: "workingHoursValue" }] : /* istanbul ignore next */ []));
|
|
11891
12089
|
responseValue = input('', ...(ngDevMode ? [{ debugName: "responseValue" }] : /* istanbul ignore next */ []));
|
|
@@ -11902,6 +12100,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11902
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"] }]
|
|
11903
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 }] }] } });
|
|
11904
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. */
|
|
11905
12104
|
class SceContactFormPanelComponent {
|
|
11906
12105
|
dir = input('rtl', ...(ngDevMode ? [{ debugName: "dir" }] : /* istanbul ignore next */ []));
|
|
11907
12106
|
fullName = input.required(...(ngDevMode ? [{ debugName: "fullName" }] : /* istanbul ignore next */ []));
|
|
@@ -11941,6 +12140,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11941
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"] }]
|
|
11942
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"] }] } });
|
|
11943
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). */
|
|
11944
12144
|
class ScePlatformSettingsFieldsComponent {
|
|
11945
12145
|
viewFields = input.required(...(ngDevMode ? [{ debugName: "viewFields" }] : /* istanbul ignore next */ []));
|
|
11946
12146
|
isEditMode = input(false, ...(ngDevMode ? [{ debugName: "isEditMode" }] : /* istanbul ignore next */ []));
|
|
@@ -11959,6 +12159,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11959
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"] }]
|
|
11960
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"] }] } });
|
|
11961
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. */
|
|
11962
12163
|
class SceEntityProfileEditFormComponent {
|
|
11963
12164
|
form = input.required(...(ngDevMode ? [{ debugName: "form" }] : /* istanbul ignore next */ []));
|
|
11964
12165
|
dir = input('rtl', ...(ngDevMode ? [{ debugName: "dir" }] : /* istanbul ignore next */ []));
|
|
@@ -11993,6 +12194,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
11993
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"] }]
|
|
11994
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"] }] } });
|
|
11995
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. */
|
|
11996
12198
|
class SceAccountUsersTabsBarComponent {
|
|
11997
12199
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
11998
12200
|
activeTab = input.required(...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
|
|
@@ -12008,6 +12210,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12008
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"] }]
|
|
12009
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"] }] } });
|
|
12010
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. */
|
|
12011
12214
|
class SceAccountUserVerifyDialogComponent {
|
|
12012
12215
|
visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
12013
12216
|
locale = input.required(...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
|
|
@@ -12030,6 +12233,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12030
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"] }]
|
|
12031
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"] }] } });
|
|
12032
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`. */
|
|
12033
12237
|
class SceAccountUserAssignDialogComponent {
|
|
12034
12238
|
visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
12035
12239
|
locale = input.required(...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
|
|
@@ -12058,6 +12262,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12058
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"] }]
|
|
12059
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"] }] } });
|
|
12060
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`. */
|
|
12061
12266
|
class SceAccountUserEditDialogComponent {
|
|
12062
12267
|
visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
12063
12268
|
locale = input.required(...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
|
|
@@ -12084,6 +12289,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12084
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"] }]
|
|
12085
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"] }] } });
|
|
12086
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. */
|
|
12087
12293
|
class SceAccountUserDetailHeaderComponent {
|
|
12088
12294
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
12089
12295
|
statusTags = input([], ...(ngDevMode ? [{ debugName: "statusTags" }] : /* istanbul ignore next */ []));
|
|
@@ -12099,6 +12305,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12099
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"] }]
|
|
12100
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"] }] } });
|
|
12101
12307
|
|
|
12308
|
+
/** Titled grid of read-only personal-detail `fields` for an account user; labels and values arrive already translated and formatted. */
|
|
12102
12309
|
class SceAccountUserPersonalSectionComponent {
|
|
12103
12310
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
12104
12311
|
fields = input.required(...(ngDevMode ? [{ debugName: "fields" }] : /* istanbul ignore next */ []));
|
|
@@ -12110,6 +12317,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12110
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"] }]
|
|
12111
12318
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], fields: [{ type: i0.Input, args: [{ isSignal: true, alias: "fields", required: true }] }] } });
|
|
12112
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`. */
|
|
12113
12321
|
class SceAccountUserPermissionsSectionComponent {
|
|
12114
12322
|
sectionTitle = input.required(...(ngDevMode ? [{ debugName: "sectionTitle" }] : /* istanbul ignore next */ []));
|
|
12115
12323
|
permissionsLabel = input.required(...(ngDevMode ? [{ debugName: "permissionsLabel" }] : /* istanbul ignore next */ []));
|
|
@@ -12124,6 +12332,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12124
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"] }]
|
|
12125
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 }] }] } });
|
|
12126
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. */
|
|
12127
12336
|
class SceInternalUserVerifySectionComponent {
|
|
12128
12337
|
nationalId = input.required(...(ngDevMode ? [{ debugName: "nationalId" }] : /* istanbul ignore next */ []));
|
|
12129
12338
|
birthDate = input.required(...(ngDevMode ? [{ debugName: "birthDate" }] : /* istanbul ignore next */ []));
|
|
@@ -12143,6 +12352,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12143
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"] }]
|
|
12144
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"] }] } });
|
|
12145
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). */
|
|
12146
12356
|
class SceInternalUserFormFieldsComponent {
|
|
12147
12357
|
mode = input.required(...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
12148
12358
|
nationalId = input('', ...(ngDevMode ? [{ debugName: "nationalId" }] : /* istanbul ignore next */ []));
|
|
@@ -12162,6 +12372,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12162
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"] }]
|
|
12163
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"] }] } });
|
|
12164
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. */
|
|
12165
12376
|
class SceInternalUserPermissionsSectionComponent {
|
|
12166
12377
|
roleOptions = input([], ...(ngDevMode ? [{ debugName: "roleOptions" }] : /* istanbul ignore next */ []));
|
|
12167
12378
|
selectedRoleNumbers = input([], ...(ngDevMode ? [{ debugName: "selectedRoleNumbers" }] : /* istanbul ignore next */ []));
|
|
@@ -12177,6 +12388,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12177
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"] }]
|
|
12178
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"] }] } });
|
|
12179
12390
|
|
|
12391
|
+
/** Segmented grid/list/map switch for the offices browser; fully controlled — it reports `viewModeChange` rather than holding the mode itself. */
|
|
12180
12392
|
class SceOfficesViewToggleComponent {
|
|
12181
12393
|
viewMode = input.required(...(ngDevMode ? [{ debugName: "viewMode" }] : /* istanbul ignore next */ []));
|
|
12182
12394
|
viewModeChange = output();
|
|
@@ -12188,6 +12400,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12188
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"] }]
|
|
12189
12401
|
}], propDecorators: { viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: true }] }], viewModeChange: [{ type: i0.Output, args: ["viewModeChange"] }] } });
|
|
12190
12402
|
|
|
12403
|
+
/** Paginated grid/list of engineering-office cards with skeleton and empty states; `viewMode` switches the layout and `skeletonCount` is floored at 4. */
|
|
12191
12404
|
class SceOfficesGridPanelComponent {
|
|
12192
12405
|
cards = input.required(...(ngDevMode ? [{ debugName: "cards" }] : /* istanbul ignore next */ []));
|
|
12193
12406
|
isLoading = input.required(...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
|
|
@@ -12223,6 +12436,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12223
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"] }]
|
|
12224
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"] }] } });
|
|
12225
12438
|
|
|
12439
|
+
/** Wraps the OSM offices map with a fallback link shown when `mapLoadFailed`; emits `selectOffice` when a marker is picked. */
|
|
12226
12440
|
class SceOfficesMapPanelComponent {
|
|
12227
12441
|
mapPoints = input.required(...(ngDevMode ? [{ debugName: "mapPoints" }] : /* istanbul ignore next */ []));
|
|
12228
12442
|
mapLoadFailed = input.required(...(ngDevMode ? [{ debugName: "mapLoadFailed" }] : /* istanbul ignore next */ []));
|
|
@@ -12282,6 +12496,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12282
12496
|
}]
|
|
12283
12497
|
}], ctorParameters: () => [], propDecorators: { sceSliderValuenow: [{ type: i0.Input, args: [{ isSignal: true, alias: "sceSliderValuenow", required: false }] }] } });
|
|
12284
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. */
|
|
12285
12500
|
class SceOfficesFiltersSidebarComponent {
|
|
12286
12501
|
/** Current draft sort/filter values */
|
|
12287
12502
|
draftSort = input.required(...(ngDevMode ? [{ debugName: "draftSort" }] : /* istanbul ignore next */ []));
|
|
@@ -13013,6 +13228,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
13013
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"] }]
|
|
13014
13229
|
}], propDecorators: { panelId: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelId", required: true }] }], activeId: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeId", required: false }] }] } });
|
|
13015
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. */
|
|
13016
13232
|
class SceBasicCardComponent {
|
|
13017
13233
|
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
13018
13234
|
value = input.required(...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
@@ -13029,6 +13245,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
13029
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"] }]
|
|
13030
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 }] }] } });
|
|
13031
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. */
|
|
13032
13249
|
class SceNavCardsListComponent {
|
|
13033
13250
|
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
13034
13251
|
/** Maps an item slug to a router link. Kept as an input so the organism stays route-agnostic. */
|
|
@@ -13131,6 +13348,7 @@ function hasObservationFor(item) {
|
|
|
13131
13348
|
return Boolean(observation.notes || observation.reasonLabel || observation.attachments?.length);
|
|
13132
13349
|
}
|
|
13133
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. */
|
|
13134
13352
|
class SceEntitySummaryCardComponent {
|
|
13135
13353
|
logo = input.required(...(ngDevMode ? [{ debugName: "logo" }] : /* istanbul ignore next */ []));
|
|
13136
13354
|
name = input.required(...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
@@ -13721,6 +13939,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
13721
13939
|
|
|
13722
13940
|
/** Tags without an explicit variant cycle through these, so a tag cloud stays visually varied. */
|
|
13723
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. */
|
|
13724
13943
|
class SceArticleTagsListComponent {
|
|
13725
13944
|
items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
13726
13945
|
titleKey = input('knowledge.tags', ...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
|