@elasticias/ui 1.0.38 → 1.0.40
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.
|
@@ -570,6 +570,37 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
570
570
|
args: [{ transform: booleanAttribute }]
|
|
571
571
|
}] } });
|
|
572
572
|
|
|
573
|
+
/**
|
|
574
|
+
* Scopes a read-only state to every descendant `ef-*` form control.
|
|
575
|
+
*
|
|
576
|
+
* Drop it on the container that wraps a form and bind whether the current
|
|
577
|
+
* user lacks write access; descendant controls fold it into their effective
|
|
578
|
+
* disabled state, so no per-field `[disabled]` binding is needed:
|
|
579
|
+
*
|
|
580
|
+
* ```html
|
|
581
|
+
* <div class="detail-grid" [efReadOnly]="!canWrite()">
|
|
582
|
+
* <ef-input-text name="companyName" ... />
|
|
583
|
+
* <ef-select name="clientType" ... />
|
|
584
|
+
* </div>
|
|
585
|
+
* ```
|
|
586
|
+
*
|
|
587
|
+
* The input is a signal, so toggling it re-enables the controls under
|
|
588
|
+
* zoneless change detection (controls read it through `isDisabled`).
|
|
589
|
+
*/
|
|
590
|
+
class EfReadOnlyDirective {
|
|
591
|
+
/** When true, every descendant ef-* control renders disabled. */
|
|
592
|
+
readOnly = input(false, { ...(ngDevMode ? { debugName: "readOnly" } : /* istanbul ignore next */ {}), alias: 'efReadOnly', transform: booleanAttribute });
|
|
593
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfReadOnlyDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
594
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.11", type: EfReadOnlyDirective, isStandalone: true, selector: "[efReadOnly]", inputs: { readOnly: { classPropertyName: "readOnly", publicName: "efReadOnly", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
|
|
595
|
+
}
|
|
596
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfReadOnlyDirective, decorators: [{
|
|
597
|
+
type: Directive,
|
|
598
|
+
args: [{
|
|
599
|
+
selector: '[efReadOnly]',
|
|
600
|
+
standalone: true,
|
|
601
|
+
}]
|
|
602
|
+
}], propDecorators: { readOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "efReadOnly", required: false }] }] } });
|
|
603
|
+
|
|
573
604
|
/**
|
|
574
605
|
* Scopes a map of server/validation errors to its descendant `ef-*` form
|
|
575
606
|
* controls, which auto-link by their `name` — no per-field `[errors]`
|
|
@@ -702,14 +733,16 @@ class AbstractEfFormControl {
|
|
|
702
733
|
required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
703
734
|
readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
704
735
|
/** The `[disabled]` input. The **effective** disabled (input OR
|
|
705
|
-
* form-driven via CVA) is {@link isDisabled} — bind that in templates. */
|
|
736
|
+
* form-driven via CVA, or an enclosing `[efReadOnly]` scope) is {@link isDisabled} — bind that in templates. */
|
|
706
737
|
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
707
738
|
/** Form-driven disabled set by CVA `setDisabledState`, merged with the
|
|
708
739
|
* `[disabled]` input. Writable signal (the input itself is read-only). */
|
|
709
740
|
_cvaDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_cvaDisabled" }] : /* istanbul ignore next */ []));
|
|
710
741
|
/** Effective disabled state — the `[disabled]` input OR a reactive-form
|
|
711
742
|
* `disable()`. Templates/logic should use this, not `disabled()`. */
|
|
712
|
-
isDisabled = computed(() => this.disabled() || this._cvaDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
743
|
+
isDisabled = computed(() => this.disabled() || this._cvaDisabled() || (this.readOnlyScope?.readOnly() ?? false), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
744
|
+
/** Optional enclosing `[efReadOnly]` scope — disables the control when set. */
|
|
745
|
+
readOnlyScope = inject(EfReadOnlyDirective, { optional: true });
|
|
713
746
|
/** CVA hook for subclasses: `setDisabledState(d) { this.updateDisabledState(d); }`. */
|
|
714
747
|
updateDisabledState(disabled) {
|
|
715
748
|
this._cvaDisabled.set(disabled);
|
|
@@ -2604,6 +2637,12 @@ class EfQuantityStepperComponent {
|
|
|
2604
2637
|
* When present, it specifies that the component should be disabled
|
|
2605
2638
|
*/
|
|
2606
2639
|
disabled = false;
|
|
2640
|
+
/** Optional enclosing `[efReadOnly]` scope. */
|
|
2641
|
+
readOnlyScope = inject(EfReadOnlyDirective, { optional: true });
|
|
2642
|
+
/** Effective disabled: the input / CVA state OR a read-only scope. */
|
|
2643
|
+
get isDisabled() {
|
|
2644
|
+
return this.disabled || (this.readOnlyScope?.readOnly() ?? false);
|
|
2645
|
+
}
|
|
2607
2646
|
/**
|
|
2608
2647
|
* Callback to invoke when the value changes
|
|
2609
2648
|
*/
|
|
@@ -2675,7 +2714,7 @@ class EfQuantityStepperComponent {
|
|
|
2675
2714
|
useExisting: forwardRef(() => EfQuantityStepperComponent),
|
|
2676
2715
|
multi: true,
|
|
2677
2716
|
},
|
|
2678
|
-
], ngImport: i0, template: "<div\n class=\"flex h-12 items-center text-center justify-center gap-2 rounded-full !border !border-gray-200 bg-gray-100 dark:bg-slate-500 p-2\"\n>\n <ef-inputnumber\n [(ngModel)]=\"value\"\n [min]=\"min\"\n [max]=\"max\"\n [step]=\"step\"\n [minFractionDigits]=\"minFractionDigits\"\n [maxFractionDigits]=\"maxFractionDigits\"\n [locale]=\"locale\"\n [disabled]=\"
|
|
2717
|
+
], ngImport: i0, template: "<div\n class=\"flex h-12 items-center text-center justify-center gap-2 rounded-full !border !border-gray-200 bg-gray-100 dark:bg-slate-500 p-2\"\n>\n <ef-inputnumber\n [(ngModel)]=\"value\"\n [min]=\"min\"\n [max]=\"max\"\n [step]=\"step\"\n [minFractionDigits]=\"minFractionDigits\"\n [maxFractionDigits]=\"maxFractionDigits\"\n [locale]=\"locale\"\n [disabled]=\"isDisabled\"\n [showButtons]=\"true\"\n buttonLayout=\"horizontal\"\n decrementButtonIcon=\"-\"\n incrementButtonIcon=\"+\"\n [pt]=\"ptConfig\"\n (ngModelChange)=\"handleValueChange($event)\"\n (blurEvent)=\"handleBlur()\"\n >\n </ef-inputnumber>\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: EfInputNumberComponent, selector: "ef-inputnumber", inputs: ["value", "invalid", "format", "showButtons", "buttonLayout", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "prefix", "suffix", "currency", "currencyDisplay", "locale", "localeMatcher", "mode", "useGrouping", "minFractionDigits", "maxFractionDigits", "min", "max", "step", "allowEmpty", "inputSize", "size", "maxlength", "minlength", "pattern", "tabindex", "title", "ariaLabelledBy", "inputStyle", "inputStyleClass", "style", "styleClass", "primeNgVariant", "autofocus", "autocomplete", "fluid", "inline", "variant", "pt", "ptOptions", "dt", "unstyled"], outputs: ["inputEvent", "valueChangeEvent", "focusEvent", "blurEvent", "keyDownEvent", "clearEvent"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2679
2718
|
}
|
|
2680
2719
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfQuantityStepperComponent, decorators: [{
|
|
2681
2720
|
type: Component,
|
|
@@ -2685,7 +2724,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
2685
2724
|
useExisting: forwardRef(() => EfQuantityStepperComponent),
|
|
2686
2725
|
multi: true,
|
|
2687
2726
|
},
|
|
2688
|
-
], template: "<div\n class=\"flex h-12 items-center text-center justify-center gap-2 rounded-full !border !border-gray-200 bg-gray-100 dark:bg-slate-500 p-2\"\n>\n <ef-inputnumber\n [(ngModel)]=\"value\"\n [min]=\"min\"\n [max]=\"max\"\n [step]=\"step\"\n [minFractionDigits]=\"minFractionDigits\"\n [maxFractionDigits]=\"maxFractionDigits\"\n [locale]=\"locale\"\n [disabled]=\"
|
|
2727
|
+
], template: "<div\n class=\"flex h-12 items-center text-center justify-center gap-2 rounded-full !border !border-gray-200 bg-gray-100 dark:bg-slate-500 p-2\"\n>\n <ef-inputnumber\n [(ngModel)]=\"value\"\n [min]=\"min\"\n [max]=\"max\"\n [step]=\"step\"\n [minFractionDigits]=\"minFractionDigits\"\n [maxFractionDigits]=\"maxFractionDigits\"\n [locale]=\"locale\"\n [disabled]=\"isDisabled\"\n [showButtons]=\"true\"\n buttonLayout=\"horizontal\"\n decrementButtonIcon=\"-\"\n incrementButtonIcon=\"+\"\n [pt]=\"ptConfig\"\n (ngModelChange)=\"handleValueChange($event)\"\n (blurEvent)=\"handleBlur()\"\n >\n </ef-inputnumber>\n</div>\n" }]
|
|
2689
2728
|
}], propDecorators: { value: [{
|
|
2690
2729
|
type: Input
|
|
2691
2730
|
}], min: [{
|
|
@@ -4280,8 +4319,12 @@ class EfRowActionsComponent {
|
|
|
4280
4319
|
return true;
|
|
4281
4320
|
if (action.visible === false)
|
|
4282
4321
|
return false;
|
|
4283
|
-
if (action.permission && ctx
|
|
4284
|
-
|
|
4322
|
+
if (action.permission && ctx) {
|
|
4323
|
+
// Array.isArray does not narrow a ReadonlyArray out of the union.
|
|
4324
|
+
const required = typeof action.permission === 'string' ? [action.permission] : action.permission;
|
|
4325
|
+
if (!required.every(p => ctx.isGranted(p)))
|
|
4326
|
+
return false;
|
|
4327
|
+
}
|
|
4285
4328
|
return true;
|
|
4286
4329
|
}
|
|
4287
4330
|
/** Stable trackBy across renders. */
|
|
@@ -4881,7 +4924,10 @@ class EfDataCardComponent {
|
|
|
4881
4924
|
labelKey: 'common_duplicate',
|
|
4882
4925
|
icon: 'pi pi-copy',
|
|
4883
4926
|
kbd: formatShortcut('mod+d'),
|
|
4884
|
-
|
|
4927
|
+
// Saved through create: without Create the row would open
|
|
4928
|
+
// a duplicate form the user cannot save. Hiding the item
|
|
4929
|
+
// also disarms mod+d, which only runs visible items.
|
|
4930
|
+
permission: [Permissions.Duplicate, Permissions.Create],
|
|
4885
4931
|
command: () => this.rowAction.emit({ action: 'duplicate', row }),
|
|
4886
4932
|
});
|
|
4887
4933
|
}
|
|
@@ -7273,7 +7319,8 @@ class EfModuleSideComponent {
|
|
|
7273
7319
|
return m.navSections
|
|
7274
7320
|
.map(section => ({
|
|
7275
7321
|
...section,
|
|
7276
|
-
items: section.items.filter(item => this.perms.can(m.id, item.requiredAction ?? 'read')
|
|
7322
|
+
items: section.items.filter(item => this.perms.can(m.id, item.requiredAction ?? 'read') &&
|
|
7323
|
+
(!item.screenCode || this.perms.canScreen(item.screenCode))),
|
|
7277
7324
|
}))
|
|
7278
7325
|
.filter(section => section.items.length > 0);
|
|
7279
7326
|
}, ...(ngDevMode ? [{ debugName: "visibleSections" }] : /* istanbul ignore next */ []));
|
|
@@ -7530,7 +7577,8 @@ class EfAppShellComponent {
|
|
|
7530
7577
|
return m.navSections
|
|
7531
7578
|
.map(section => ({
|
|
7532
7579
|
...section,
|
|
7533
|
-
items: section.items.filter(item => this.perms.can(m.id, item.requiredAction ?? 'read')
|
|
7580
|
+
items: section.items.filter(item => this.perms.can(m.id, item.requiredAction ?? 'read') &&
|
|
7581
|
+
(!item.screenCode || this.perms.canScreen(item.screenCode))),
|
|
7534
7582
|
}))
|
|
7535
7583
|
.filter(section => section.items.length > 0);
|
|
7536
7584
|
}, ...(ngDevMode ? [{ debugName: "moduleSections" }] : /* istanbul ignore next */ []));
|
|
@@ -7562,7 +7610,7 @@ class EfAppShellComponent {
|
|
|
7562
7610
|
this.switcherOpen.set(false);
|
|
7563
7611
|
}
|
|
7564
7612
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfAppShellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7565
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfAppShellComponent, isStandalone: true, selector: "ef-app-shell", inputs: { stripe: "stripe" }, host: { properties: { "attr.data-viewport": "viewport()" } }, ngImport: i0, template: "<!-- One layout, one declaration per slot.\n Angular binds projected content to the LAST matching <ng-content> in a\n template, so declaring the same selector once per viewport branch meant the\n branch that was actually rendered on a phone received nothing \u2014 every\n screen came up blank inside working chrome. The layouts differ by CSS and\n by which chrome is rendered, never by where the content is declared. -->\n\n<ef-module-rail class=\"ef-app-shell__rail\">\n <ng-content select=\"[logo]\" logo></ng-content>\n\n <!-- Shows or hides the side panel. In the rail rather than the top bar\n because the rail never folds: the button keeps one position whether\n the panel is open or closed, so a second click needs no search.\n Drawn inline because PrimeIcons has no panel glyph; the divider\n marks the panel, so it is there while the panel is. -->\n @if (showSide()) {\n <button\n rail-footer\n type=\"button\"\n class=\"ef-app-shell__side-toggle\"\n aria-controls=\"ef-app-shell-side\"\n [attr.aria-expanded]=\"!sideCollapsed()\"\n [attr.aria-label]=\"(sideCollapsed() ? 'common_sidebar_show' : 'common_sidebar_hide') | translate\"\n [pTooltip]=\"((sideCollapsed() ? 'common_sidebar_show' : 'common_sidebar_hide') | translate) + ' \u00B7 ' + shortcutHint\"\n tooltipPosition=\"right\"\n (click)=\"toggleSide()\"\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\n stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"16\" rx=\"3.5\" />\n @if (!sideCollapsed()) {\n <path d=\"M12 4v16\" />\n }\n </svg>\n </button>\n }\n</ef-module-rail>\n\n@if (showSide()) {\n <!-- Folded by class rather than by @if: the side-footer slot (identity\n menu) is projected into it, and the panel animates closed. `inert`\n takes the hidden links out of the tab order and the a11y tree. -->\n <ef-module-side\n id=\"ef-app-shell-side\"\n class=\"ef-app-shell__side\"\n [class.is-collapsed]=\"sideCollapsed()\"\n [attr.inert]=\"sideCollapsed() ? '' : null\"\n >\n <ng-content select=\"[side-header-meta]\" side-header-meta></ng-content>\n <ng-content select=\"[side-footer]\" side-footer></ng-content>\n </ef-module-side>\n}\n\n<div class=\"ef-app-shell__column\">\n <ef-app-top>\n <!-- The menu takes the breadcrumb's slot on a phone: the breadcrumb is\n hidden there (ef-app-top), so this is the leading position, which is\n where a menu button belongs and where a thumb reaches. -->\n @if (isMobile()) {\n <button\n breadcrumb\n type=\"button\"\n class=\"ef-app-shell__menu\"\n (click)=\"openSwitcher()\"\n [attr.aria-label]=\"'common_modules' | translate\"\n >\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </button>\n }\n <ng-content select=\"[breadcrumb]\" breadcrumb></ng-content>\n <ng-content select=\"[search]\" search></ng-content>\n <ng-content select=\"[actions]\" actions></ng-content>\n </ef-app-top>\n\n <ef-app-main [stripe]=\"stripe\">\n <ng-content></ng-content>\n </ef-app-main>\n\n @if (isMobile()) {\n <nav class=\"ef-app-shell__tabs\" [attr.aria-label]=\"'common_modules' | translate\">\n @for (module of tabs(); track module.id) {\n <button\n type=\"button\"\n class=\"ef-app-shell__tab\"\n [class.is-active]=\"activeId() === module.id\"\n [attr.data-module]=\"module.id\"\n [attr.aria-current]=\"activeId() === module.id ? 'page' : null\"\n (click)=\"onSelect(module)\"\n >\n <i class=\"ef-app-shell__tab-icon\" [class]=\"module.icon\" aria-hidden=\"true\"></i>\n <span class=\"ef-app-shell__tab-label\">{{ module.labelKey | translate }}</span>\n </button>\n }\n </nav>\n }\n</div>\n\n<ng-content select=\"[fab]\"></ng-content>\n\n@if (isMobile()) {\n <ef-bottom-sheet [open]=\"switcherOpen()\" (openChange)=\"onSwitcherChange($event)\">\n <!-- The screens first: the tab bar already switches modules, so this is\n the only way to reach anything but a module's default screen. -->\n @for (section of moduleSections(); track section.id) {\n @if (section.labelKey) {\n <h2 class=\"ef-app-shell__sheet-title\">{{ section.labelKey | translate }}</h2>\n }\n <ul class=\"ef-app-shell__sheet-list\">\n @for (item of section.items; track item.id) {\n <li>\n <a\n class=\"ef-app-shell__sheet-item\"\n [routerLink]=\"item.route\"\n routerLinkActive=\"is-active\"\n (click)=\"onNavigate(item)\"\n >\n @if (item.icon) {\n <i [class]=\"item.icon\" aria-hidden=\"true\"></i>\n }\n <span>{{ item.labelKey | translate }}</span>\n @if (item.badge !== undefined && item.badge !== null) {\n <span class=\"ef-app-shell__sheet-badge\">{{ item.badge }}</span>\n }\n </a>\n </li>\n }\n </ul>\n }\n\n <h2 class=\"ef-app-shell__sheet-title\">{{ 'common_modules' | translate }}</h2>\n <ul class=\"ef-app-shell__sheet-list\">\n @for (module of allVisible(); track module.id) {\n <li>\n <button\n type=\"button\"\n class=\"ef-app-shell__sheet-item\"\n [class.is-active]=\"activeId() === module.id\"\n [attr.data-module]=\"module.id\"\n (click)=\"onSelect(module)\"\n >\n <i [class]=\"module.icon\" aria-hidden=\"true\"></i>\n <span>{{ module.labelKey | translate }}</span>\n </button>\n </li>\n }\n </ul>\n\n <!-- App-level entries that live in the rail on a desktop and have nowhere\n else to go on a phone: this sheet is the phone's menu. Declared only\n in the mobile branch, so a desktop simply drops what is projected. -->\n <div class=\"ef-app-shell__sheet-footer\">\n <ng-content select=\"[sheet-footer]\" sheet-footer></ng-content>\n </div>\n </ef-bottom-sheet>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:row;width:100%;height:100vh;background:var(--paper);color:var(--text);overflow:hidden}.ef-app-shell__column{display:flex;flex-direction:column;flex:1 1 auto;min-width:0;min-height:0;overflow:hidden}.ef-app-shell__side{overflow:hidden;transition:flex-basis var(--t-fast) var(--ease-out),width var(--t-fast) var(--ease-out)}.ef-app-shell__side.is-collapsed{flex-basis:0;width:0;border-right-width:0}.ef-app-shell__side-toggle{display:grid;place-items:center;flex:0 0 auto;width:44px;height:44px;padding:0;background:transparent;border:0;border-radius:var(--r-md);color:var(--rail-fg-mute);cursor:pointer;transition:background-color var(--t-fast) var(--ease-out),color var(--t-fast) var(--ease-out)}.ef-app-shell__side-toggle:hover{background:var(--rail-hover);color:#fff}.ef-app-shell__side-toggle:focus-visible{outline:2px solid color-mix(in srgb,var(--tenant-300, #b87a99) 80%,transparent);outline-offset:2px}@media(prefers-reduced-motion:reduce){.ef-app-shell__side{transition:none}}.ef-app-shell__menu{display:inline-flex;align-items:center;justify-content:center;width:var(--hit-touch);height:var(--hit-touch);background:transparent;border:0;border-radius:var(--r-md);color:var(--text);cursor:pointer;font-size:18px}.ef-app-shell__menu:hover{background:var(--paper-alt)}.ef-app-shell__tabs{flex:0 0 auto;display:flex;align-items:stretch;height:64px;padding-bottom:env(safe-area-inset-bottom);background:var(--paper);border-top:1px solid var(--rule)}.ef-app-shell__tab{position:relative;flex:1 1 0;min-width:0;display:inline-flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;background:transparent;border:0;color:var(--text-mute);cursor:pointer;padding:6px 4px;transition:color var(--t-fast) var(--ease-out)}.ef-app-shell__tab.is-active{color:var(--text)}.ef-app-shell__tab.is-active:after{content:\"\";position:absolute;top:0;left:50%;transform:translate(-50%);width:28px;height:3px;background:var(--module);border-radius:0 0 var(--r-sm) var(--r-sm)}.ef-app-shell__tab-icon{font-size:18px;line-height:1}.ef-app-shell__tab-label{font-family:var(--font-ui);font-size:10.5px;font-weight:600;letter-spacing:-.005em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.ef-app-shell__sheet-title{font-size:11.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--text-mute);margin:0 0 10px;padding-top:16px;border-top:1px solid var(--rule)}.ef-app-shell__sheet-title:first-child{padding-top:0;border-top:0}.ef-app-shell__sheet-list{list-style:none;margin:0 0 4px;padding:0;display:grid;grid-template-columns:repeat(2,1fr);gap:8px}.ef-app-shell__sheet-list+.ef-app-shell__sheet-title{margin-top:8px}.ef-app-shell__sheet-item{display:flex;align-items:center;gap:12px;width:100%;height:var(--hit-touch);padding:0 16px;background:var(--paper-alt);border:0;border-radius:var(--r-md);text-decoration:none;color:var(--text);cursor:pointer;font-family:var(--font-ui);font-size:14px;font-weight:500;text-align:left;transition:background-color var(--t-fast) var(--ease-out)}.ef-app-shell__sheet-item:hover{background:var(--rule)}.ef-app-shell__sheet-item.is-active{border-left:3px solid var(--module);padding-left:13px}@media(max-width:767px){.ef-app-shell__rail{display:none}}.ef-app-shell__sheet-badge{margin-inline-start:auto;font-size:11px;font-weight:700;color:var(--text-mute)}.ef-app-shell__sheet-item.is-active{background:var(--paper);color:var(--text);font-weight:700}.ef-app-shell__sheet-footer{display:grid;gap:8px;margin-top:16px;padding-top:16px;border-top:1px solid var(--rule)}.ef-app-shell__sheet-footer:empty{display:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: EfModuleRailComponent, selector: "ef-module-rail", inputs: ["badges"] }, { kind: "component", type: EfModuleSideComponent, selector: "ef-module-side" }, { kind: "component", type: EfAppTopComponent, selector: "ef-app-top", inputs: ["themeToggle", "logout"] }, { kind: "component", type: EfAppMainComponent, selector: "ef-app-main", inputs: ["stripe"] }, { kind: "component", type: EfBottomSheetComponent, selector: "ef-bottom-sheet", inputs: ["open", "dismissOnBackdrop"], outputs: ["openChange"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i1$5.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7613
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfAppShellComponent, isStandalone: true, selector: "ef-app-shell", inputs: { stripe: "stripe" }, host: { properties: { "attr.data-viewport": "viewport()" } }, ngImport: i0, template: "<!-- One layout, one declaration per slot.\n Angular binds projected content to the LAST matching <ng-content> in a\n template, so declaring the same selector once per viewport branch meant the\n branch that was actually rendered on a phone received nothing \u2014 every\n screen came up blank inside working chrome. The layouts differ by CSS and\n by which chrome is rendered, never by where the content is declared. -->\n\n<ef-module-rail class=\"ef-app-shell__rail\">\n <ng-content select=\"[logo]\" logo></ng-content>\n\n <!-- Shows or hides the side panel. In the rail rather than the top bar\n because the rail never folds: the button keeps one position whether\n the panel is open or closed, so a second click needs no search.\n Drawn inline because PrimeIcons has no panel glyph: the frame with\n the panel's edge, and a chevron for what a click will do. -->\n @if (showSide()) {\n <button\n rail-footer\n type=\"button\"\n class=\"ef-app-shell__side-toggle\"\n aria-controls=\"ef-app-shell-side\"\n [attr.aria-expanded]=\"!sideCollapsed()\"\n [attr.aria-label]=\"(sideCollapsed() ? 'common_sidebar_show' : 'common_sidebar_hide') | translate\"\n [pTooltip]=\"((sideCollapsed() ? 'common_sidebar_show' : 'common_sidebar_hide') | translate) + ' \u00B7 ' + shortcutHint\"\n tooltipPosition=\"right\"\n (click)=\"toggleSide()\"\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\n stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"16\" rx=\"3\" />\n <path d=\"M9 4v16\" />\n @if (sideCollapsed()) {\n <path d=\"m13.5 9.5 2.5 2.5-2.5 2.5\" />\n } @else {\n <path d=\"m16 9.5-2.5 2.5 2.5 2.5\" />\n }\n </svg>\n </button>\n }\n</ef-module-rail>\n\n@if (showSide()) {\n <!-- Folded by class rather than by @if: the side-footer slot (identity\n menu) is projected into it, and the panel animates closed. `inert`\n takes the hidden links out of the tab order and the a11y tree. -->\n <ef-module-side\n id=\"ef-app-shell-side\"\n class=\"ef-app-shell__side\"\n [class.is-collapsed]=\"sideCollapsed()\"\n [attr.inert]=\"sideCollapsed() ? '' : null\"\n >\n <ng-content select=\"[side-header-meta]\" side-header-meta></ng-content>\n <ng-content select=\"[side-footer]\" side-footer></ng-content>\n </ef-module-side>\n}\n\n<div class=\"ef-app-shell__column\">\n <ef-app-top>\n <!-- The menu takes the breadcrumb's slot on a phone: the breadcrumb is\n hidden there (ef-app-top), so this is the leading position, which is\n where a menu button belongs and where a thumb reaches. -->\n @if (isMobile()) {\n <button\n breadcrumb\n type=\"button\"\n class=\"ef-app-shell__menu\"\n (click)=\"openSwitcher()\"\n [attr.aria-label]=\"'common_modules' | translate\"\n >\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </button>\n }\n <ng-content select=\"[breadcrumb]\" breadcrumb></ng-content>\n <ng-content select=\"[search]\" search></ng-content>\n <ng-content select=\"[actions]\" actions></ng-content>\n </ef-app-top>\n\n <ef-app-main [stripe]=\"stripe\">\n <ng-content></ng-content>\n </ef-app-main>\n\n @if (isMobile()) {\n <nav class=\"ef-app-shell__tabs\" [attr.aria-label]=\"'common_modules' | translate\">\n @for (module of tabs(); track module.id) {\n <button\n type=\"button\"\n class=\"ef-app-shell__tab\"\n [class.is-active]=\"activeId() === module.id\"\n [attr.data-module]=\"module.id\"\n [attr.aria-current]=\"activeId() === module.id ? 'page' : null\"\n (click)=\"onSelect(module)\"\n >\n <i class=\"ef-app-shell__tab-icon\" [class]=\"module.icon\" aria-hidden=\"true\"></i>\n <span class=\"ef-app-shell__tab-label\">{{ module.labelKey | translate }}</span>\n </button>\n }\n </nav>\n }\n</div>\n\n<ng-content select=\"[fab]\"></ng-content>\n\n@if (isMobile()) {\n <ef-bottom-sheet [open]=\"switcherOpen()\" (openChange)=\"onSwitcherChange($event)\">\n <!-- The screens first: the tab bar already switches modules, so this is\n the only way to reach anything but a module's default screen. -->\n @for (section of moduleSections(); track section.id) {\n @if (section.labelKey) {\n <h2 class=\"ef-app-shell__sheet-title\">{{ section.labelKey | translate }}</h2>\n }\n <ul class=\"ef-app-shell__sheet-list\">\n @for (item of section.items; track item.id) {\n <li>\n <a\n class=\"ef-app-shell__sheet-item\"\n [routerLink]=\"item.route\"\n routerLinkActive=\"is-active\"\n (click)=\"onNavigate(item)\"\n >\n @if (item.icon) {\n <i [class]=\"item.icon\" aria-hidden=\"true\"></i>\n }\n <span>{{ item.labelKey | translate }}</span>\n @if (item.badge !== undefined && item.badge !== null) {\n <span class=\"ef-app-shell__sheet-badge\">{{ item.badge }}</span>\n }\n </a>\n </li>\n }\n </ul>\n }\n\n <h2 class=\"ef-app-shell__sheet-title\">{{ 'common_modules' | translate }}</h2>\n <ul class=\"ef-app-shell__sheet-list\">\n @for (module of allVisible(); track module.id) {\n <li>\n <button\n type=\"button\"\n class=\"ef-app-shell__sheet-item\"\n [class.is-active]=\"activeId() === module.id\"\n [attr.data-module]=\"module.id\"\n (click)=\"onSelect(module)\"\n >\n <i [class]=\"module.icon\" aria-hidden=\"true\"></i>\n <span>{{ module.labelKey | translate }}</span>\n </button>\n </li>\n }\n </ul>\n\n <!-- App-level entries that live in the rail on a desktop and have nowhere\n else to go on a phone: this sheet is the phone's menu. Declared only\n in the mobile branch, so a desktop simply drops what is projected. -->\n <div class=\"ef-app-shell__sheet-footer\">\n <ng-content select=\"[sheet-footer]\" sheet-footer></ng-content>\n </div>\n </ef-bottom-sheet>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:row;width:100%;height:100vh;background:var(--paper);color:var(--text);overflow:hidden}.ef-app-shell__column{display:flex;flex-direction:column;flex:1 1 auto;min-width:0;min-height:0;overflow:hidden}.ef-app-shell__side{overflow:hidden;transition:flex-basis var(--t-fast) var(--ease-out),width var(--t-fast) var(--ease-out)}.ef-app-shell__side.is-collapsed{flex-basis:0;width:0;border-right-width:0}.ef-app-shell__side-toggle{display:grid;place-items:center;flex:0 0 auto;width:44px;height:44px;padding:0;background:transparent;border:0;border-radius:var(--r-md);color:var(--rail-fg-mute);cursor:pointer;transition:background-color var(--t-fast) var(--ease-out),color var(--t-fast) var(--ease-out)}.ef-app-shell__side-toggle:hover{background:var(--rail-hover);color:#fff}.ef-app-shell__side-toggle:focus-visible{outline:2px solid color-mix(in srgb,var(--tenant-300, #b87a99) 80%,transparent);outline-offset:2px}@media(prefers-reduced-motion:reduce){.ef-app-shell__side{transition:none}}.ef-app-shell__menu{display:inline-flex;align-items:center;justify-content:center;width:var(--hit-touch);height:var(--hit-touch);background:transparent;border:0;border-radius:var(--r-md);color:var(--text);cursor:pointer;font-size:18px}.ef-app-shell__menu:hover{background:var(--paper-alt)}.ef-app-shell__tabs{flex:0 0 auto;display:flex;align-items:stretch;height:64px;padding-bottom:env(safe-area-inset-bottom);background:var(--paper);border-top:1px solid var(--rule)}.ef-app-shell__tab{position:relative;flex:1 1 0;min-width:0;display:inline-flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;background:transparent;border:0;color:var(--text-mute);cursor:pointer;padding:6px 4px;transition:color var(--t-fast) var(--ease-out)}.ef-app-shell__tab.is-active{color:var(--text)}.ef-app-shell__tab.is-active:after{content:\"\";position:absolute;top:0;left:50%;transform:translate(-50%);width:28px;height:3px;background:var(--module);border-radius:0 0 var(--r-sm) var(--r-sm)}.ef-app-shell__tab-icon{font-size:18px;line-height:1}.ef-app-shell__tab-label{font-family:var(--font-ui);font-size:10.5px;font-weight:600;letter-spacing:-.005em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.ef-app-shell__sheet-title{font-size:11.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--text-mute);margin:0 0 10px;padding-top:16px;border-top:1px solid var(--rule)}.ef-app-shell__sheet-title:first-child{padding-top:0;border-top:0}.ef-app-shell__sheet-list{list-style:none;margin:0 0 4px;padding:0;display:grid;grid-template-columns:repeat(2,1fr);gap:8px}.ef-app-shell__sheet-list+.ef-app-shell__sheet-title{margin-top:8px}.ef-app-shell__sheet-item{display:flex;align-items:center;gap:12px;width:100%;height:var(--hit-touch);padding:0 16px;background:var(--paper-alt);border:0;border-radius:var(--r-md);text-decoration:none;color:var(--text);cursor:pointer;font-family:var(--font-ui);font-size:14px;font-weight:500;text-align:left;transition:background-color var(--t-fast) var(--ease-out)}.ef-app-shell__sheet-item:hover{background:var(--rule)}.ef-app-shell__sheet-item.is-active{border-left:3px solid var(--module);padding-left:13px}@media(max-width:767px){.ef-app-shell__rail{display:none}}.ef-app-shell__sheet-badge{margin-inline-start:auto;font-size:11px;font-weight:700;color:var(--text-mute)}.ef-app-shell__sheet-item.is-active{background:var(--paper);color:var(--text);font-weight:700}.ef-app-shell__sheet-footer{display:grid;gap:8px;margin-top:16px;padding-top:16px;border-top:1px solid var(--rule)}.ef-app-shell__sheet-footer:empty{display:none}:host-context([dir=rtl]) .ef-app-shell__side-toggle svg{transform:scaleX(-1)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: EfModuleRailComponent, selector: "ef-module-rail", inputs: ["badges"] }, { kind: "component", type: EfModuleSideComponent, selector: "ef-module-side" }, { kind: "component", type: EfAppTopComponent, selector: "ef-app-top", inputs: ["themeToggle", "logout"] }, { kind: "component", type: EfAppMainComponent, selector: "ef-app-main", inputs: ["stripe"] }, { kind: "component", type: EfBottomSheetComponent, selector: "ef-bottom-sheet", inputs: ["open", "dismissOnBackdrop"], outputs: ["openChange"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i1$5.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7566
7614
|
}
|
|
7567
7615
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfAppShellComponent, decorators: [{
|
|
7568
7616
|
type: Component,
|
|
@@ -7578,7 +7626,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
7578
7626
|
RouterLink,
|
|
7579
7627
|
], host: {
|
|
7580
7628
|
'[attr.data-viewport]': 'viewport()',
|
|
7581
|
-
}, template: "<!-- One layout, one declaration per slot.\n Angular binds projected content to the LAST matching <ng-content> in a\n template, so declaring the same selector once per viewport branch meant the\n branch that was actually rendered on a phone received nothing \u2014 every\n screen came up blank inside working chrome. The layouts differ by CSS and\n by which chrome is rendered, never by where the content is declared. -->\n\n<ef-module-rail class=\"ef-app-shell__rail\">\n <ng-content select=\"[logo]\" logo></ng-content>\n\n <!-- Shows or hides the side panel. In the rail rather than the top bar\n because the rail never folds: the button keeps one position whether\n the panel is open or closed, so a second click needs no search.\n Drawn inline because PrimeIcons has no panel glyph; the divider\n marks the panel, so it is there while the panel is. -->\n @if (showSide()) {\n <button\n rail-footer\n type=\"button\"\n class=\"ef-app-shell__side-toggle\"\n aria-controls=\"ef-app-shell-side\"\n [attr.aria-expanded]=\"!sideCollapsed()\"\n [attr.aria-label]=\"(sideCollapsed() ? 'common_sidebar_show' : 'common_sidebar_hide') | translate\"\n [pTooltip]=\"((sideCollapsed() ? 'common_sidebar_show' : 'common_sidebar_hide') | translate) + ' \u00B7 ' + shortcutHint\"\n tooltipPosition=\"right\"\n (click)=\"toggleSide()\"\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\n stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"16\" rx=\"3.5\" />\n @if (!sideCollapsed()) {\n <path d=\"M12 4v16\" />\n }\n </svg>\n </button>\n }\n</ef-module-rail>\n\n@if (showSide()) {\n <!-- Folded by class rather than by @if: the side-footer slot (identity\n menu) is projected into it, and the panel animates closed. `inert`\n takes the hidden links out of the tab order and the a11y tree. -->\n <ef-module-side\n id=\"ef-app-shell-side\"\n class=\"ef-app-shell__side\"\n [class.is-collapsed]=\"sideCollapsed()\"\n [attr.inert]=\"sideCollapsed() ? '' : null\"\n >\n <ng-content select=\"[side-header-meta]\" side-header-meta></ng-content>\n <ng-content select=\"[side-footer]\" side-footer></ng-content>\n </ef-module-side>\n}\n\n<div class=\"ef-app-shell__column\">\n <ef-app-top>\n <!-- The menu takes the breadcrumb's slot on a phone: the breadcrumb is\n hidden there (ef-app-top), so this is the leading position, which is\n where a menu button belongs and where a thumb reaches. -->\n @if (isMobile()) {\n <button\n breadcrumb\n type=\"button\"\n class=\"ef-app-shell__menu\"\n (click)=\"openSwitcher()\"\n [attr.aria-label]=\"'common_modules' | translate\"\n >\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </button>\n }\n <ng-content select=\"[breadcrumb]\" breadcrumb></ng-content>\n <ng-content select=\"[search]\" search></ng-content>\n <ng-content select=\"[actions]\" actions></ng-content>\n </ef-app-top>\n\n <ef-app-main [stripe]=\"stripe\">\n <ng-content></ng-content>\n </ef-app-main>\n\n @if (isMobile()) {\n <nav class=\"ef-app-shell__tabs\" [attr.aria-label]=\"'common_modules' | translate\">\n @for (module of tabs(); track module.id) {\n <button\n type=\"button\"\n class=\"ef-app-shell__tab\"\n [class.is-active]=\"activeId() === module.id\"\n [attr.data-module]=\"module.id\"\n [attr.aria-current]=\"activeId() === module.id ? 'page' : null\"\n (click)=\"onSelect(module)\"\n >\n <i class=\"ef-app-shell__tab-icon\" [class]=\"module.icon\" aria-hidden=\"true\"></i>\n <span class=\"ef-app-shell__tab-label\">{{ module.labelKey | translate }}</span>\n </button>\n }\n </nav>\n }\n</div>\n\n<ng-content select=\"[fab]\"></ng-content>\n\n@if (isMobile()) {\n <ef-bottom-sheet [open]=\"switcherOpen()\" (openChange)=\"onSwitcherChange($event)\">\n <!-- The screens first: the tab bar already switches modules, so this is\n the only way to reach anything but a module's default screen. -->\n @for (section of moduleSections(); track section.id) {\n @if (section.labelKey) {\n <h2 class=\"ef-app-shell__sheet-title\">{{ section.labelKey | translate }}</h2>\n }\n <ul class=\"ef-app-shell__sheet-list\">\n @for (item of section.items; track item.id) {\n <li>\n <a\n class=\"ef-app-shell__sheet-item\"\n [routerLink]=\"item.route\"\n routerLinkActive=\"is-active\"\n (click)=\"onNavigate(item)\"\n >\n @if (item.icon) {\n <i [class]=\"item.icon\" aria-hidden=\"true\"></i>\n }\n <span>{{ item.labelKey | translate }}</span>\n @if (item.badge !== undefined && item.badge !== null) {\n <span class=\"ef-app-shell__sheet-badge\">{{ item.badge }}</span>\n }\n </a>\n </li>\n }\n </ul>\n }\n\n <h2 class=\"ef-app-shell__sheet-title\">{{ 'common_modules' | translate }}</h2>\n <ul class=\"ef-app-shell__sheet-list\">\n @for (module of allVisible(); track module.id) {\n <li>\n <button\n type=\"button\"\n class=\"ef-app-shell__sheet-item\"\n [class.is-active]=\"activeId() === module.id\"\n [attr.data-module]=\"module.id\"\n (click)=\"onSelect(module)\"\n >\n <i [class]=\"module.icon\" aria-hidden=\"true\"></i>\n <span>{{ module.labelKey | translate }}</span>\n </button>\n </li>\n }\n </ul>\n\n <!-- App-level entries that live in the rail on a desktop and have nowhere\n else to go on a phone: this sheet is the phone's menu. Declared only\n in the mobile branch, so a desktop simply drops what is projected. -->\n <div class=\"ef-app-shell__sheet-footer\">\n <ng-content select=\"[sheet-footer]\" sheet-footer></ng-content>\n </div>\n </ef-bottom-sheet>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:row;width:100%;height:100vh;background:var(--paper);color:var(--text);overflow:hidden}.ef-app-shell__column{display:flex;flex-direction:column;flex:1 1 auto;min-width:0;min-height:0;overflow:hidden}.ef-app-shell__side{overflow:hidden;transition:flex-basis var(--t-fast) var(--ease-out),width var(--t-fast) var(--ease-out)}.ef-app-shell__side.is-collapsed{flex-basis:0;width:0;border-right-width:0}.ef-app-shell__side-toggle{display:grid;place-items:center;flex:0 0 auto;width:44px;height:44px;padding:0;background:transparent;border:0;border-radius:var(--r-md);color:var(--rail-fg-mute);cursor:pointer;transition:background-color var(--t-fast) var(--ease-out),color var(--t-fast) var(--ease-out)}.ef-app-shell__side-toggle:hover{background:var(--rail-hover);color:#fff}.ef-app-shell__side-toggle:focus-visible{outline:2px solid color-mix(in srgb,var(--tenant-300, #b87a99) 80%,transparent);outline-offset:2px}@media(prefers-reduced-motion:reduce){.ef-app-shell__side{transition:none}}.ef-app-shell__menu{display:inline-flex;align-items:center;justify-content:center;width:var(--hit-touch);height:var(--hit-touch);background:transparent;border:0;border-radius:var(--r-md);color:var(--text);cursor:pointer;font-size:18px}.ef-app-shell__menu:hover{background:var(--paper-alt)}.ef-app-shell__tabs{flex:0 0 auto;display:flex;align-items:stretch;height:64px;padding-bottom:env(safe-area-inset-bottom);background:var(--paper);border-top:1px solid var(--rule)}.ef-app-shell__tab{position:relative;flex:1 1 0;min-width:0;display:inline-flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;background:transparent;border:0;color:var(--text-mute);cursor:pointer;padding:6px 4px;transition:color var(--t-fast) var(--ease-out)}.ef-app-shell__tab.is-active{color:var(--text)}.ef-app-shell__tab.is-active:after{content:\"\";position:absolute;top:0;left:50%;transform:translate(-50%);width:28px;height:3px;background:var(--module);border-radius:0 0 var(--r-sm) var(--r-sm)}.ef-app-shell__tab-icon{font-size:18px;line-height:1}.ef-app-shell__tab-label{font-family:var(--font-ui);font-size:10.5px;font-weight:600;letter-spacing:-.005em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.ef-app-shell__sheet-title{font-size:11.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--text-mute);margin:0 0 10px;padding-top:16px;border-top:1px solid var(--rule)}.ef-app-shell__sheet-title:first-child{padding-top:0;border-top:0}.ef-app-shell__sheet-list{list-style:none;margin:0 0 4px;padding:0;display:grid;grid-template-columns:repeat(2,1fr);gap:8px}.ef-app-shell__sheet-list+.ef-app-shell__sheet-title{margin-top:8px}.ef-app-shell__sheet-item{display:flex;align-items:center;gap:12px;width:100%;height:var(--hit-touch);padding:0 16px;background:var(--paper-alt);border:0;border-radius:var(--r-md);text-decoration:none;color:var(--text);cursor:pointer;font-family:var(--font-ui);font-size:14px;font-weight:500;text-align:left;transition:background-color var(--t-fast) var(--ease-out)}.ef-app-shell__sheet-item:hover{background:var(--rule)}.ef-app-shell__sheet-item.is-active{border-left:3px solid var(--module);padding-left:13px}@media(max-width:767px){.ef-app-shell__rail{display:none}}.ef-app-shell__sheet-badge{margin-inline-start:auto;font-size:11px;font-weight:700;color:var(--text-mute)}.ef-app-shell__sheet-item.is-active{background:var(--paper);color:var(--text);font-weight:700}.ef-app-shell__sheet-footer{display:grid;gap:8px;margin-top:16px;padding-top:16px;border-top:1px solid var(--rule)}.ef-app-shell__sheet-footer:empty{display:none}\n"] }]
|
|
7629
|
+
}, template: "<!-- One layout, one declaration per slot.\n Angular binds projected content to the LAST matching <ng-content> in a\n template, so declaring the same selector once per viewport branch meant the\n branch that was actually rendered on a phone received nothing \u2014 every\n screen came up blank inside working chrome. The layouts differ by CSS and\n by which chrome is rendered, never by where the content is declared. -->\n\n<ef-module-rail class=\"ef-app-shell__rail\">\n <ng-content select=\"[logo]\" logo></ng-content>\n\n <!-- Shows or hides the side panel. In the rail rather than the top bar\n because the rail never folds: the button keeps one position whether\n the panel is open or closed, so a second click needs no search.\n Drawn inline because PrimeIcons has no panel glyph: the frame with\n the panel's edge, and a chevron for what a click will do. -->\n @if (showSide()) {\n <button\n rail-footer\n type=\"button\"\n class=\"ef-app-shell__side-toggle\"\n aria-controls=\"ef-app-shell-side\"\n [attr.aria-expanded]=\"!sideCollapsed()\"\n [attr.aria-label]=\"(sideCollapsed() ? 'common_sidebar_show' : 'common_sidebar_hide') | translate\"\n [pTooltip]=\"((sideCollapsed() ? 'common_sidebar_show' : 'common_sidebar_hide') | translate) + ' \u00B7 ' + shortcutHint\"\n tooltipPosition=\"right\"\n (click)=\"toggleSide()\"\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\n stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"16\" rx=\"3\" />\n <path d=\"M9 4v16\" />\n @if (sideCollapsed()) {\n <path d=\"m13.5 9.5 2.5 2.5-2.5 2.5\" />\n } @else {\n <path d=\"m16 9.5-2.5 2.5 2.5 2.5\" />\n }\n </svg>\n </button>\n }\n</ef-module-rail>\n\n@if (showSide()) {\n <!-- Folded by class rather than by @if: the side-footer slot (identity\n menu) is projected into it, and the panel animates closed. `inert`\n takes the hidden links out of the tab order and the a11y tree. -->\n <ef-module-side\n id=\"ef-app-shell-side\"\n class=\"ef-app-shell__side\"\n [class.is-collapsed]=\"sideCollapsed()\"\n [attr.inert]=\"sideCollapsed() ? '' : null\"\n >\n <ng-content select=\"[side-header-meta]\" side-header-meta></ng-content>\n <ng-content select=\"[side-footer]\" side-footer></ng-content>\n </ef-module-side>\n}\n\n<div class=\"ef-app-shell__column\">\n <ef-app-top>\n <!-- The menu takes the breadcrumb's slot on a phone: the breadcrumb is\n hidden there (ef-app-top), so this is the leading position, which is\n where a menu button belongs and where a thumb reaches. -->\n @if (isMobile()) {\n <button\n breadcrumb\n type=\"button\"\n class=\"ef-app-shell__menu\"\n (click)=\"openSwitcher()\"\n [attr.aria-label]=\"'common_modules' | translate\"\n >\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </button>\n }\n <ng-content select=\"[breadcrumb]\" breadcrumb></ng-content>\n <ng-content select=\"[search]\" search></ng-content>\n <ng-content select=\"[actions]\" actions></ng-content>\n </ef-app-top>\n\n <ef-app-main [stripe]=\"stripe\">\n <ng-content></ng-content>\n </ef-app-main>\n\n @if (isMobile()) {\n <nav class=\"ef-app-shell__tabs\" [attr.aria-label]=\"'common_modules' | translate\">\n @for (module of tabs(); track module.id) {\n <button\n type=\"button\"\n class=\"ef-app-shell__tab\"\n [class.is-active]=\"activeId() === module.id\"\n [attr.data-module]=\"module.id\"\n [attr.aria-current]=\"activeId() === module.id ? 'page' : null\"\n (click)=\"onSelect(module)\"\n >\n <i class=\"ef-app-shell__tab-icon\" [class]=\"module.icon\" aria-hidden=\"true\"></i>\n <span class=\"ef-app-shell__tab-label\">{{ module.labelKey | translate }}</span>\n </button>\n }\n </nav>\n }\n</div>\n\n<ng-content select=\"[fab]\"></ng-content>\n\n@if (isMobile()) {\n <ef-bottom-sheet [open]=\"switcherOpen()\" (openChange)=\"onSwitcherChange($event)\">\n <!-- The screens first: the tab bar already switches modules, so this is\n the only way to reach anything but a module's default screen. -->\n @for (section of moduleSections(); track section.id) {\n @if (section.labelKey) {\n <h2 class=\"ef-app-shell__sheet-title\">{{ section.labelKey | translate }}</h2>\n }\n <ul class=\"ef-app-shell__sheet-list\">\n @for (item of section.items; track item.id) {\n <li>\n <a\n class=\"ef-app-shell__sheet-item\"\n [routerLink]=\"item.route\"\n routerLinkActive=\"is-active\"\n (click)=\"onNavigate(item)\"\n >\n @if (item.icon) {\n <i [class]=\"item.icon\" aria-hidden=\"true\"></i>\n }\n <span>{{ item.labelKey | translate }}</span>\n @if (item.badge !== undefined && item.badge !== null) {\n <span class=\"ef-app-shell__sheet-badge\">{{ item.badge }}</span>\n }\n </a>\n </li>\n }\n </ul>\n }\n\n <h2 class=\"ef-app-shell__sheet-title\">{{ 'common_modules' | translate }}</h2>\n <ul class=\"ef-app-shell__sheet-list\">\n @for (module of allVisible(); track module.id) {\n <li>\n <button\n type=\"button\"\n class=\"ef-app-shell__sheet-item\"\n [class.is-active]=\"activeId() === module.id\"\n [attr.data-module]=\"module.id\"\n (click)=\"onSelect(module)\"\n >\n <i [class]=\"module.icon\" aria-hidden=\"true\"></i>\n <span>{{ module.labelKey | translate }}</span>\n </button>\n </li>\n }\n </ul>\n\n <!-- App-level entries that live in the rail on a desktop and have nowhere\n else to go on a phone: this sheet is the phone's menu. Declared only\n in the mobile branch, so a desktop simply drops what is projected. -->\n <div class=\"ef-app-shell__sheet-footer\">\n <ng-content select=\"[sheet-footer]\" sheet-footer></ng-content>\n </div>\n </ef-bottom-sheet>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:row;width:100%;height:100vh;background:var(--paper);color:var(--text);overflow:hidden}.ef-app-shell__column{display:flex;flex-direction:column;flex:1 1 auto;min-width:0;min-height:0;overflow:hidden}.ef-app-shell__side{overflow:hidden;transition:flex-basis var(--t-fast) var(--ease-out),width var(--t-fast) var(--ease-out)}.ef-app-shell__side.is-collapsed{flex-basis:0;width:0;border-right-width:0}.ef-app-shell__side-toggle{display:grid;place-items:center;flex:0 0 auto;width:44px;height:44px;padding:0;background:transparent;border:0;border-radius:var(--r-md);color:var(--rail-fg-mute);cursor:pointer;transition:background-color var(--t-fast) var(--ease-out),color var(--t-fast) var(--ease-out)}.ef-app-shell__side-toggle:hover{background:var(--rail-hover);color:#fff}.ef-app-shell__side-toggle:focus-visible{outline:2px solid color-mix(in srgb,var(--tenant-300, #b87a99) 80%,transparent);outline-offset:2px}@media(prefers-reduced-motion:reduce){.ef-app-shell__side{transition:none}}.ef-app-shell__menu{display:inline-flex;align-items:center;justify-content:center;width:var(--hit-touch);height:var(--hit-touch);background:transparent;border:0;border-radius:var(--r-md);color:var(--text);cursor:pointer;font-size:18px}.ef-app-shell__menu:hover{background:var(--paper-alt)}.ef-app-shell__tabs{flex:0 0 auto;display:flex;align-items:stretch;height:64px;padding-bottom:env(safe-area-inset-bottom);background:var(--paper);border-top:1px solid var(--rule)}.ef-app-shell__tab{position:relative;flex:1 1 0;min-width:0;display:inline-flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;background:transparent;border:0;color:var(--text-mute);cursor:pointer;padding:6px 4px;transition:color var(--t-fast) var(--ease-out)}.ef-app-shell__tab.is-active{color:var(--text)}.ef-app-shell__tab.is-active:after{content:\"\";position:absolute;top:0;left:50%;transform:translate(-50%);width:28px;height:3px;background:var(--module);border-radius:0 0 var(--r-sm) var(--r-sm)}.ef-app-shell__tab-icon{font-size:18px;line-height:1}.ef-app-shell__tab-label{font-family:var(--font-ui);font-size:10.5px;font-weight:600;letter-spacing:-.005em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.ef-app-shell__sheet-title{font-size:11.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--text-mute);margin:0 0 10px;padding-top:16px;border-top:1px solid var(--rule)}.ef-app-shell__sheet-title:first-child{padding-top:0;border-top:0}.ef-app-shell__sheet-list{list-style:none;margin:0 0 4px;padding:0;display:grid;grid-template-columns:repeat(2,1fr);gap:8px}.ef-app-shell__sheet-list+.ef-app-shell__sheet-title{margin-top:8px}.ef-app-shell__sheet-item{display:flex;align-items:center;gap:12px;width:100%;height:var(--hit-touch);padding:0 16px;background:var(--paper-alt);border:0;border-radius:var(--r-md);text-decoration:none;color:var(--text);cursor:pointer;font-family:var(--font-ui);font-size:14px;font-weight:500;text-align:left;transition:background-color var(--t-fast) var(--ease-out)}.ef-app-shell__sheet-item:hover{background:var(--rule)}.ef-app-shell__sheet-item.is-active{border-left:3px solid var(--module);padding-left:13px}@media(max-width:767px){.ef-app-shell__rail{display:none}}.ef-app-shell__sheet-badge{margin-inline-start:auto;font-size:11px;font-weight:700;color:var(--text-mute)}.ef-app-shell__sheet-item.is-active{background:var(--paper);color:var(--text);font-weight:700}.ef-app-shell__sheet-footer{display:grid;gap:8px;margin-top:16px;padding-top:16px;border-top:1px solid var(--rule)}.ef-app-shell__sheet-footer:empty{display:none}:host-context([dir=rtl]) .ef-app-shell__side-toggle svg{transform:scaleX(-1)}\n"] }]
|
|
7582
7630
|
}], ctorParameters: () => [], propDecorators: { stripe: [{
|
|
7583
7631
|
type: Input
|
|
7584
7632
|
}] } });
|
|
@@ -8601,6 +8649,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
8601
8649
|
* Custom actions can declare `permission` and `visible` like
|
|
8602
8650
|
* `EfRowAction`. With `[context]` bound, the toolbar filters them
|
|
8603
8651
|
* against `ScreenContext.isGranted()` automatically.
|
|
8652
|
+
*
|
|
8653
|
+
* Save and actions flagged `requiresWrite` follow `context.canWrite`,
|
|
8654
|
+
* which `AbstractDetailScreenV2` sets from its own `canWrite()` (Edit on
|
|
8655
|
+
* an existing record, Create on a new one or a duplicate). Binding
|
|
8656
|
+
* `[context]="context"` is all a screen does; it does not pass
|
|
8657
|
+
* `[showSaveAction]` for permissions. Without a context, or with one that
|
|
8658
|
+
* carries no `canWrite`, Save behaves as `[showSaveAction]` alone says.
|
|
8604
8659
|
*/
|
|
8605
8660
|
class EfDetailToolbarComponent {
|
|
8606
8661
|
/* ── Inputs ─────────────────────────────────────────────────── */
|
|
@@ -8638,12 +8693,17 @@ class EfDetailToolbarComponent {
|
|
|
8638
8693
|
/** Custom actions after permission + `visible` filtering. */
|
|
8639
8694
|
visibleCustomActions = computed(() => {
|
|
8640
8695
|
const ctx = this.context();
|
|
8641
|
-
|
|
8696
|
+
const canWrite = this.canWrite();
|
|
8697
|
+
return this.customActions().filter((a) => this.isCustomVisible(a, ctx, canWrite));
|
|
8642
8698
|
}, ...(ngDevMode ? [{ debugName: "visibleCustomActions" }] : /* istanbul ignore next */ []));
|
|
8643
8699
|
canPrint = computed(() => this.checkStandard(this.showPrintAction(), Permissions.Print), ...(ngDevMode ? [{ debugName: "canPrint" }] : /* istanbul ignore next */ []));
|
|
8644
8700
|
canDuplicate = computed(() => this.checkStandard(this.showDuplicateAction(), Permissions.Duplicate), ...(ngDevMode ? [{ debugName: "canDuplicate" }] : /* istanbul ignore next */ []));
|
|
8645
8701
|
canDelete = computed(() => this.checkStandard(this.showDeleteAction(), Permissions.Delete), ...(ngDevMode ? [{ debugName: "canDelete" }] : /* istanbul ignore next */ []));
|
|
8646
|
-
|
|
8702
|
+
/** The bound screen's write state; `true` when unknown (no context,
|
|
8703
|
+
* or a context no detail abstract has stamped), which keeps the
|
|
8704
|
+
* toolbar's behaviour for those callers what it always was. */
|
|
8705
|
+
canWrite = computed(() => this.context()?.canWrite?.() ?? true, ...(ngDevMode ? [{ debugName: "canWrite" }] : /* istanbul ignore next */ []));
|
|
8706
|
+
canSave = computed(() => this.showSaveAction() && this.canWrite(), ...(ngDevMode ? [{ debugName: "canSave" }] : /* istanbul ignore next */ []));
|
|
8647
8707
|
hasStandardActions = computed(() => this.canPrint() ||
|
|
8648
8708
|
this.canDuplicate() ||
|
|
8649
8709
|
this.canDelete() ||
|
|
@@ -8659,9 +8719,11 @@ class EfDetailToolbarComponent {
|
|
|
8659
8719
|
this.customAction.emit(action);
|
|
8660
8720
|
}
|
|
8661
8721
|
/* ── Internals ──────────────────────────────────────────────── */
|
|
8662
|
-
isCustomVisible(action, ctx) {
|
|
8722
|
+
isCustomVisible(action, ctx, canWrite) {
|
|
8663
8723
|
if (action.visible === false)
|
|
8664
8724
|
return false;
|
|
8725
|
+
if (action.requiresWrite && !canWrite)
|
|
8726
|
+
return false;
|
|
8665
8727
|
if (action.permission && ctx && !ctx.isGranted(action.permission))
|
|
8666
8728
|
return false;
|
|
8667
8729
|
return true;
|
|
@@ -8678,7 +8740,9 @@ class EfDetailToolbarComponent {
|
|
|
8678
8740
|
case Permissions.Print:
|
|
8679
8741
|
return ctx.hasPrintPermission;
|
|
8680
8742
|
case Permissions.Duplicate:
|
|
8681
|
-
|
|
8743
|
+
// A duplicate is saved through create, and duplicate() refuses
|
|
8744
|
+
// without Create; showing it on Duplicate alone gave a dead button.
|
|
8745
|
+
return ctx.hasDuplicatePermission && ctx.hasCreatePermission;
|
|
8682
8746
|
case Permissions.Delete:
|
|
8683
8747
|
return ctx.hasDeletePermission;
|
|
8684
8748
|
}
|
|
@@ -9541,11 +9605,11 @@ class EfCheckboxComponent extends AbstractEfFormControl {
|
|
|
9541
9605
|
this.onTouched();
|
|
9542
9606
|
}
|
|
9543
9607
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfCheckboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9544
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfCheckboxComponent, isStandalone: true, selector: "ef-checkbox", inputs: { value: "value", binary: ["binary", "binary", booleanAttribute], variant: "variant", inline: ["inline", "inline", booleanAttribute], checked: "checked" }, outputs: { checkedChange: "checkedChange" }, host: { properties: { "class.ef-stacked": "this.isStacked" } }, usesInheritance: true, ngImport: i0, template: "@if (!inline && hasLabel) {\n <ef-label [labelKey]=\"labelKey()\" [label]=\"label()\" [for]=\"effectiveId\" [required]=\"required()\" />\n}\n<div class=\"ef-checkbox-control\">\n @if (variant === 'comptoir') {\n <label class=\"ef-checkbox-native\" [class.is-disabled]=\"
|
|
9608
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfCheckboxComponent, isStandalone: true, selector: "ef-checkbox", inputs: { value: "value", binary: ["binary", "binary", booleanAttribute], variant: "variant", inline: ["inline", "inline", booleanAttribute], checked: "checked" }, outputs: { checkedChange: "checkedChange" }, host: { properties: { "class.ef-stacked": "this.isStacked" } }, usesInheritance: true, ngImport: i0, template: "@if (!inline && hasLabel) {\n <ef-label [labelKey]=\"labelKey()\" [label]=\"label()\" [for]=\"effectiveId\" [required]=\"required()\" />\n}\n<div class=\"ef-checkbox-control\">\n @if (variant === 'comptoir') {\n <label class=\"ef-checkbox-native\" [class.is-disabled]=\"isDisabled()\">\n <input\n type=\"checkbox\"\n [id]=\"effectiveId\"\n [attr.name]=\"name() || null\"\n [checked]=\"!!checked\"\n [disabled]=\"isDisabled()\"\n [class.is-invalid]=\"isInvalid\"\n [attr.aria-label]=\"effectiveAriaLabel\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : null\"\n [attr.aria-describedby]=\"(showRequired || serverErrors) ? errorsId : null\"\n (change)=\"handleNativeChange($any($event.target).checked)\"\n />\n <span class=\"ef-checkbox-box\" aria-hidden=\"true\"></span>\n @if (inline && hasLabel) {\n <span class=\"ef-checkbox-label\">\n {{ labelKey() ? (labelKey() | translate) : label() }}\n @if (required()) {\n <span class=\"ef-checkbox-required\" aria-hidden=\"true\">*</span>\n }\n </span>\n }\n </label>\n } @else {\n <p-checkbox\n [inputId]=\"effectiveId\"\n [name]=\"name()\"\n [ngModel]=\"checked\"\n [ngModelOptions]=\"{standalone: true}\"\n (onChange)=\"handleChange($event)\"\n [value]=\"value\"\n [binary]=\"binary\"\n [disabled]=\"isDisabled()\"\n [ariaLabel]=\"effectiveAriaLabel || undefined\"\n />\n @if (inline && hasLabel) {\n <ef-label [labelKey]=\"labelKey()\" [label]=\"label()\" [for]=\"effectiveId\" styleClass=\"form-label-left cursor-pointer\" />\n }\n }\n</div>\n@if (showRequired || serverErrors) {\n <div [id]=\"errorsId\" role=\"alert\" aria-live=\"polite\">\n @if (showRequired) {\n <small class=\"text-danger\">{{ 'validation.required' | translate }}</small>\n }\n @if (serverErrors; as errors) {\n @for (error of errors; track error) {\n <small class=\"text-danger block\">{{ error }}</small>\n }\n }\n </div>\n}\n", styles: [":host{display:inline-flex;flex-wrap:wrap;align-items:center;gap:.5rem;min-width:0}.ef-checkbox-control{display:inline-flex;align-items:center;gap:.5rem;min-width:0}:host(.ef-stacked){display:block}:host(.ef-stacked)>.ef-checkbox-control{display:flex;min-height:var(--hit-base)}\n"], dependencies: [{ kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i5.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["hostName", "value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: EfLabelComponent, selector: "ef-label", inputs: ["label", "labelKey", "for", "styleClass", "required"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
|
|
9545
9609
|
}
|
|
9546
9610
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfCheckboxComponent, decorators: [{
|
|
9547
9611
|
type: Component,
|
|
9548
|
-
args: [{ selector: 'ef-checkbox', standalone: true, imports: [CheckboxModule, FormsModule, TranslateModule, EfLabelComponent], template: "@if (!inline && hasLabel) {\n <ef-label [labelKey]=\"labelKey()\" [label]=\"label()\" [for]=\"effectiveId\" [required]=\"required()\" />\n}\n<div class=\"ef-checkbox-control\">\n @if (variant === 'comptoir') {\n <label class=\"ef-checkbox-native\" [class.is-disabled]=\"
|
|
9612
|
+
args: [{ selector: 'ef-checkbox', standalone: true, imports: [CheckboxModule, FormsModule, TranslateModule, EfLabelComponent], template: "@if (!inline && hasLabel) {\n <ef-label [labelKey]=\"labelKey()\" [label]=\"label()\" [for]=\"effectiveId\" [required]=\"required()\" />\n}\n<div class=\"ef-checkbox-control\">\n @if (variant === 'comptoir') {\n <label class=\"ef-checkbox-native\" [class.is-disabled]=\"isDisabled()\">\n <input\n type=\"checkbox\"\n [id]=\"effectiveId\"\n [attr.name]=\"name() || null\"\n [checked]=\"!!checked\"\n [disabled]=\"isDisabled()\"\n [class.is-invalid]=\"isInvalid\"\n [attr.aria-label]=\"effectiveAriaLabel\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : null\"\n [attr.aria-describedby]=\"(showRequired || serverErrors) ? errorsId : null\"\n (change)=\"handleNativeChange($any($event.target).checked)\"\n />\n <span class=\"ef-checkbox-box\" aria-hidden=\"true\"></span>\n @if (inline && hasLabel) {\n <span class=\"ef-checkbox-label\">\n {{ labelKey() ? (labelKey() | translate) : label() }}\n @if (required()) {\n <span class=\"ef-checkbox-required\" aria-hidden=\"true\">*</span>\n }\n </span>\n }\n </label>\n } @else {\n <p-checkbox\n [inputId]=\"effectiveId\"\n [name]=\"name()\"\n [ngModel]=\"checked\"\n [ngModelOptions]=\"{standalone: true}\"\n (onChange)=\"handleChange($event)\"\n [value]=\"value\"\n [binary]=\"binary\"\n [disabled]=\"isDisabled()\"\n [ariaLabel]=\"effectiveAriaLabel || undefined\"\n />\n @if (inline && hasLabel) {\n <ef-label [labelKey]=\"labelKey()\" [label]=\"label()\" [for]=\"effectiveId\" styleClass=\"form-label-left cursor-pointer\" />\n }\n }\n</div>\n@if (showRequired || serverErrors) {\n <div [id]=\"errorsId\" role=\"alert\" aria-live=\"polite\">\n @if (showRequired) {\n <small class=\"text-danger\">{{ 'validation.required' | translate }}</small>\n }\n @if (serverErrors; as errors) {\n @for (error of errors; track error) {\n <small class=\"text-danger block\">{{ error }}</small>\n }\n }\n </div>\n}\n", styles: [":host{display:inline-flex;flex-wrap:wrap;align-items:center;gap:.5rem;min-width:0}.ef-checkbox-control{display:inline-flex;align-items:center;gap:.5rem;min-width:0}:host(.ef-stacked){display:block}:host(.ef-stacked)>.ef-checkbox-control{display:flex;min-height:var(--hit-base)}\n"] }]
|
|
9549
9613
|
}], ctorParameters: () => [], propDecorators: { value: [{
|
|
9550
9614
|
type: Input
|
|
9551
9615
|
}], binary: [{
|
|
@@ -9708,6 +9772,12 @@ class EfDatepickerComponent {
|
|
|
9708
9772
|
showButtonBar = false;
|
|
9709
9773
|
minDate;
|
|
9710
9774
|
maxDate;
|
|
9775
|
+
/** Optional enclosing `[efReadOnly]` scope. */
|
|
9776
|
+
readOnlyScope = inject(EfReadOnlyDirective, { optional: true });
|
|
9777
|
+
/** Effective disabled: the input / CVA state OR a read-only scope. */
|
|
9778
|
+
get isDisabled() {
|
|
9779
|
+
return this.disabled || (this.readOnlyScope?.readOnly() ?? false);
|
|
9780
|
+
}
|
|
9711
9781
|
/**
|
|
9712
9782
|
* Take focus on load. Bound explicitly rather than left unset: PrimeNG's
|
|
9713
9783
|
* AutoFocus directive tests `autofocus === false`, and the control declares
|
|
@@ -9767,11 +9837,11 @@ class EfDatepickerComponent {
|
|
|
9767
9837
|
this.onTouched();
|
|
9768
9838
|
}
|
|
9769
9839
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfDatepickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9770
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfDatepickerComponent, isStandalone: true, selector: "ef-datepicker", inputs: { label: "label", labelKey: "labelKey", inputId: "inputId", name: "name", placeholder: "placeholder", placeholderKey: "placeholderKey", size: "size", required: ["required", "required", booleanAttribute], fluid: ["fluid", "fluid", booleanAttribute], inline: ["inline", "inline", booleanAttribute], disabled: ["disabled", "disabled", booleanAttribute], showIcon: ["showIcon", "showIcon", booleanAttribute], iconDisplay: "iconDisplay", selectionMode: "selectionMode", dateFormat: "dateFormat", appendTo: "appendTo", showTime: ["showTime", "showTime", booleanAttribute], showButtonBar: ["showButtonBar", "showButtonBar", booleanAttribute], minDate: "minDate", maxDate: "maxDate", autofocus: ["autofocus", "autofocus", booleanAttribute] }, outputs: { dateSelectEvent: "dateSelectEvent" }, host: { properties: { "class.ef-inline": "this.isInline" } }, ngImport: i0, template: "@if (labelKey || label) {\n <ef-label [labelKey]=\"labelKey\" [label]=\"label\" [for]=\"effectiveId\" [required]=\"required\" />\n}\n<div class=\"ef-field-control\">\n <p-datepicker\n [autofocus]=\"autofocus\"\n [inputId]=\"effectiveId\"\n [name]=\"name\"\n [ngModel]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n (ngModelChange)=\"handleChange($event)\"\n (onBlur)=\"handleBlur()\"\n [placeholder]=\"effectivePlaceholder\"\n [size]=\"size\"\n [disabled]=\"
|
|
9840
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfDatepickerComponent, isStandalone: true, selector: "ef-datepicker", inputs: { label: "label", labelKey: "labelKey", inputId: "inputId", name: "name", placeholder: "placeholder", placeholderKey: "placeholderKey", size: "size", required: ["required", "required", booleanAttribute], fluid: ["fluid", "fluid", booleanAttribute], inline: ["inline", "inline", booleanAttribute], disabled: ["disabled", "disabled", booleanAttribute], showIcon: ["showIcon", "showIcon", booleanAttribute], iconDisplay: "iconDisplay", selectionMode: "selectionMode", dateFormat: "dateFormat", appendTo: "appendTo", showTime: ["showTime", "showTime", booleanAttribute], showButtonBar: ["showButtonBar", "showButtonBar", booleanAttribute], minDate: "minDate", maxDate: "maxDate", autofocus: ["autofocus", "autofocus", booleanAttribute] }, outputs: { dateSelectEvent: "dateSelectEvent" }, host: { properties: { "class.ef-inline": "this.isInline" } }, ngImport: i0, template: "@if (labelKey || label) {\n <ef-label [labelKey]=\"labelKey\" [label]=\"label\" [for]=\"effectiveId\" [required]=\"required\" />\n}\n<div class=\"ef-field-control\">\n <p-datepicker\n [autofocus]=\"autofocus\"\n [inputId]=\"effectiveId\"\n [name]=\"name\"\n [ngModel]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n (ngModelChange)=\"handleChange($event)\"\n (onBlur)=\"handleBlur()\"\n [placeholder]=\"effectivePlaceholder\"\n [size]=\"size\"\n [disabled]=\"isDisabled\"\n [showIcon]=\"showIcon\"\n [iconDisplay]=\"iconDisplay\"\n [selectionMode]=\"selectionMode\"\n [dateFormat]=\"dateFormat\"\n [appendTo]=\"appendTo\"\n [showTime]=\"showTime\"\n [showButtonBar]=\"showButtonBar\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n [fluid]=\"fluid\"\n [class.ng-invalid]=\"isInvalid\"\n [class.ng-touched]=\"ngControl?.touched\"\n />\n @if (showRequired) {\n <small class=\"text-danger\">{{ 'validation.required' | translate }}</small>\n }\n @if (serverErrors; as errors) {\n @for (error of errors; track error) {\n <small class=\"text-danger block\">{{ error }}</small>\n }\n }\n</div>\n", styles: [":host{display:block}:host(.ef-inline){display:flex;align-items:baseline;gap:.5rem}:host(.ef-inline)>label{white-space:nowrap;flex-shrink:0}:host(.ef-inline)>.ef-field-control{flex:1;min-width:0}\n"], dependencies: [{ kind: "ngmodule", type: DatePickerModule }, { kind: "component", type: i1$d.DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "styleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "readonlyInput", "shortYearCutoff", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "minDate", "maxDate", "disabledDates", "disabledDays", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "view", "defaultDate", "appendTo", "motionOptions"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: EfLabelComponent, selector: "ef-label", inputs: ["label", "labelKey", "for", "styleClass", "required"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
|
|
9771
9841
|
}
|
|
9772
9842
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfDatepickerComponent, decorators: [{
|
|
9773
9843
|
type: Component,
|
|
9774
|
-
args: [{ selector: 'ef-datepicker', standalone: true, imports: [DatePickerModule, FormsModule, TranslateModule, EfLabelComponent], template: "@if (labelKey || label) {\n <ef-label [labelKey]=\"labelKey\" [label]=\"label\" [for]=\"effectiveId\" [required]=\"required\" />\n}\n<div class=\"ef-field-control\">\n <p-datepicker\n [autofocus]=\"autofocus\"\n [inputId]=\"effectiveId\"\n [name]=\"name\"\n [ngModel]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n (ngModelChange)=\"handleChange($event)\"\n (onBlur)=\"handleBlur()\"\n [placeholder]=\"effectivePlaceholder\"\n [size]=\"size\"\n [disabled]=\"
|
|
9844
|
+
args: [{ selector: 'ef-datepicker', standalone: true, imports: [DatePickerModule, FormsModule, TranslateModule, EfLabelComponent], template: "@if (labelKey || label) {\n <ef-label [labelKey]=\"labelKey\" [label]=\"label\" [for]=\"effectiveId\" [required]=\"required\" />\n}\n<div class=\"ef-field-control\">\n <p-datepicker\n [autofocus]=\"autofocus\"\n [inputId]=\"effectiveId\"\n [name]=\"name\"\n [ngModel]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n (ngModelChange)=\"handleChange($event)\"\n (onBlur)=\"handleBlur()\"\n [placeholder]=\"effectivePlaceholder\"\n [size]=\"size\"\n [disabled]=\"isDisabled\"\n [showIcon]=\"showIcon\"\n [iconDisplay]=\"iconDisplay\"\n [selectionMode]=\"selectionMode\"\n [dateFormat]=\"dateFormat\"\n [appendTo]=\"appendTo\"\n [showTime]=\"showTime\"\n [showButtonBar]=\"showButtonBar\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n [fluid]=\"fluid\"\n [class.ng-invalid]=\"isInvalid\"\n [class.ng-touched]=\"ngControl?.touched\"\n />\n @if (showRequired) {\n <small class=\"text-danger\">{{ 'validation.required' | translate }}</small>\n }\n @if (serverErrors; as errors) {\n @for (error of errors; track error) {\n <small class=\"text-danger block\">{{ error }}</small>\n }\n }\n</div>\n", styles: [":host{display:block}:host(.ef-inline){display:flex;align-items:baseline;gap:.5rem}:host(.ef-inline)>label{white-space:nowrap;flex-shrink:0}:host(.ef-inline)>.ef-field-control{flex:1;min-width:0}\n"] }]
|
|
9775
9845
|
}], ctorParameters: () => [], propDecorators: { label: [{
|
|
9776
9846
|
type: Input
|
|
9777
9847
|
}], labelKey: [{
|
|
@@ -12088,5 +12158,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
12088
12158
|
* Generated bundle index. Do not edit.
|
|
12089
12159
|
*/
|
|
12090
12160
|
|
|
12091
|
-
export { EF_BADGE_BG_COLORS, EF_BADGE_BG_LIGHT_COLORS, EF_BADGE_BORDER_COLORS, EF_BADGE_DEFAULTS, EF_BADGE_TEXT_COLORS, EF_CHART_PALETTE, EF_DATATABLE_ACTIONS_DEFAULTS, EF_DATATABLE_COLUMN_DEFAULTS, EF_DATATABLE_DEFAULTS, EF_DATA_CARD_MOBILE_LAYOUT, EF_STATUS_COLORS, EF_STATUS_COLOR_ALIASES, EfAboutDialogComponent, EfActivationFilterComponent, EfAppMainComponent, EfAppShellComponent, EfAppShellMobileComponent, EfAppTopComponent, EfBadgeComponent, EfBlockUiComponent, EfBlockableDivComponent, EfBottomSheetComponent, EfBuildStampComponent, EfBulkBarComponent, EfButtonComponent, EfButtonGroupComponent, EfCardComponent, EfChangeHistoryComponent, EfChangePasswordComponent, EfChartComponent, EfCheckboxComponent, EfClearButtonComponent, EfColumnHeaderTemplateDirective, EfColumnTemplateDirective, EfCompactPipe, EfConfirmDialogComponent, EfCurrencyPipe, EfDataCardComponent, EfDatatableActionBarComponent, EfDatatableComponent, EfDatepickerAdvancedComponent, EfDatepickerComponent, EfDetailToolbarComponent, EfDialogComponent, EfEmailMetricsCardComponent, EfEmptyStateComponent, EfFabComponent, EfFieldsetComponent, EfFilterDrawerComponent, EfFilterPillComponent, EfFormGridComponent, EfInputNumberComponent, EfInputTextComponent, EfKpiCardComponent, EfLabelComponent, EfModuleRailComponent, EfModuleSideComponent, EfMultiSelectComponent, EfOrderBuilderComponent, EfOrderSummaryComponent, EfOverflowTooltipDirective, EfPagerComponent, EfPasswordComponent, EfPdfPreviewComponent, EfPillGroupComponent, EfPresetPillComponent, EfPriceDisplayComponent, EfProductCatalogueComponent, EfProductCatalogueFilterComponent, EfProductTypeaheadComponent, EfProfileChipComponent, EfProfileMenuComponent, EfPulseComponent, EfQuantitySelectorComponent, EfQuantityStepperComponent, EfRadioComponent, EfRankListComponent, EfRowActionsComponent, EfSearchToolbarComponent, EfSelectButtonComponent, EfSelectComponent, EfServerErrorsDirective, EfShortcutsDialogComponent, EfSkeletonComponent, EfSmartBarComponent, EfStatsComponent, EfStatusChipComponent, EfTabPanelDirective, EfTabsComponent, EfTextareaComponent, EfThemeConfiguratorComponent, EfThemeToggleComponent, EfTimelineComponent, EfToastRegionComponent, EfToggleSwitchComponent, EfToolbarComponent, EfTooltipDirective, EfTotalsComponent, OrderEntityHelper, OrderLineItemHelper, TruncatePipe, buildChartConfig, getColumnAlignment, mergeColumnDefaults, resolveEfStatusColor };
|
|
12161
|
+
export { EF_BADGE_BG_COLORS, EF_BADGE_BG_LIGHT_COLORS, EF_BADGE_BORDER_COLORS, EF_BADGE_DEFAULTS, EF_BADGE_TEXT_COLORS, EF_CHART_PALETTE, EF_DATATABLE_ACTIONS_DEFAULTS, EF_DATATABLE_COLUMN_DEFAULTS, EF_DATATABLE_DEFAULTS, EF_DATA_CARD_MOBILE_LAYOUT, EF_STATUS_COLORS, EF_STATUS_COLOR_ALIASES, EfAboutDialogComponent, EfActivationFilterComponent, EfAppMainComponent, EfAppShellComponent, EfAppShellMobileComponent, EfAppTopComponent, EfBadgeComponent, EfBlockUiComponent, EfBlockableDivComponent, EfBottomSheetComponent, EfBuildStampComponent, EfBulkBarComponent, EfButtonComponent, EfButtonGroupComponent, EfCardComponent, EfChangeHistoryComponent, EfChangePasswordComponent, EfChartComponent, EfCheckboxComponent, EfClearButtonComponent, EfColumnHeaderTemplateDirective, EfColumnTemplateDirective, EfCompactPipe, EfConfirmDialogComponent, EfCurrencyPipe, EfDataCardComponent, EfDatatableActionBarComponent, EfDatatableComponent, EfDatepickerAdvancedComponent, EfDatepickerComponent, EfDetailToolbarComponent, EfDialogComponent, EfEmailMetricsCardComponent, EfEmptyStateComponent, EfFabComponent, EfFieldsetComponent, EfFilterDrawerComponent, EfFilterPillComponent, EfFormGridComponent, EfInputNumberComponent, EfInputTextComponent, EfKpiCardComponent, EfLabelComponent, EfModuleRailComponent, EfModuleSideComponent, EfMultiSelectComponent, EfOrderBuilderComponent, EfOrderSummaryComponent, EfOverflowTooltipDirective, EfPagerComponent, EfPasswordComponent, EfPdfPreviewComponent, EfPillGroupComponent, EfPresetPillComponent, EfPriceDisplayComponent, EfProductCatalogueComponent, EfProductCatalogueFilterComponent, EfProductTypeaheadComponent, EfProfileChipComponent, EfProfileMenuComponent, EfPulseComponent, EfQuantitySelectorComponent, EfQuantityStepperComponent, EfRadioComponent, EfRankListComponent, EfReadOnlyDirective, EfRowActionsComponent, EfSearchToolbarComponent, EfSelectButtonComponent, EfSelectComponent, EfServerErrorsDirective, EfShortcutsDialogComponent, EfSkeletonComponent, EfSmartBarComponent, EfStatsComponent, EfStatusChipComponent, EfTabPanelDirective, EfTabsComponent, EfTextareaComponent, EfThemeConfiguratorComponent, EfThemeToggleComponent, EfTimelineComponent, EfToastRegionComponent, EfToggleSwitchComponent, EfToolbarComponent, EfTooltipDirective, EfTotalsComponent, OrderEntityHelper, OrderLineItemHelper, TruncatePipe, buildChartConfig, getColumnAlignment, mergeColumnDefaults, resolveEfStatusColor };
|
|
12092
12162
|
//# sourceMappingURL=elasticias-ui.mjs.map
|