@frame-kit/ui-ng 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DEVELOPMENT_GUIDE.md +15 -0
- package/fesm2022/frame-kit-ui-ng-forms.mjs +71 -21
- package/fesm2022/frame-kit-ui-ng-forms.mjs.map +1 -1
- package/fesm2022/frame-kit-ui-ng-ui-editable-field.mjs +2 -3
- package/fesm2022/frame-kit-ui-ng-ui-editable-field.mjs.map +1 -1
- package/fesm2022/frame-kit-ui-ng-ui-list-editor.mjs +2 -4
- package/fesm2022/frame-kit-ui-ng-ui-list-editor.mjs.map +1 -1
- package/fesm2022/frame-kit-ui-ng-ui-menu-item.mjs +39 -9
- package/fesm2022/frame-kit-ui-ng-ui-menu-item.mjs.map +1 -1
- package/fesm2022/frame-kit-ui-ng-ui-node-tree.mjs +14 -9
- package/fesm2022/frame-kit-ui-ng-ui-node-tree.mjs.map +1 -1
- package/fesm2022/frame-kit-ui-ng-ui-pagination.mjs +2 -3
- package/fesm2022/frame-kit-ui-ng-ui-pagination.mjs.map +1 -1
- package/fesm2022/frame-kit-ui-ng-ui-timeline.mjs +7 -4
- package/fesm2022/frame-kit-ui-ng-ui-timeline.mjs.map +1 -1
- package/fesm2022/frame-kit-ui-ng-ui-user-menu.mjs +13 -4
- package/fesm2022/frame-kit-ui-ng-ui-user-menu.mjs.map +1 -1
- package/package.json +1 -1
- package/types/frame-kit-ui-ng-forms.d.ts +47 -9
- package/types/frame-kit-ui-ng-ui-menu-item.d.ts +29 -13
- package/types/frame-kit-ui-ng-ui-node-tree.d.ts +12 -2
- package/types/frame-kit-ui-ng-ui-timeline.d.ts +7 -1
- package/types/frame-kit-ui-ng-ui-user-menu.d.ts +16 -1
- package/ui/dropdown-menu/README.md +13 -14
- package/ui/menu-item/README.md +27 -14
- package/ui/node-tree/README.md +25 -10
- package/ui/timeline/README.md +20 -12
- package/ui/user-menu/README.md +36 -26
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import { NgTemplateOutlet } from '@angular/common';
|
|
1
2
|
import * as i0 from '@angular/core';
|
|
2
3
|
import { input, computed, HostBinding, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
-
import { IconComponent } from '@frame-kit/ui-ng/core/icon';
|
|
4
4
|
|
|
5
5
|
class TimelineComponent {
|
|
6
6
|
// ===== INPUTS =====
|
|
7
7
|
/** Array of timeline item data objects rendered in order. */
|
|
8
8
|
items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
9
|
+
/** Optional template rendering each item's marker icon (the app owns the icon
|
|
10
|
+
* system). Receives the item as `$implicit`; render it from `item.icon`. */
|
|
11
|
+
iconTemplate = input(undefined, ...(ngDevMode ? [{ debugName: "iconTemplate" }] : /* istanbul ignore next */ []));
|
|
9
12
|
/** Direction the timeline runs — vertical stacks items top-to-bottom, horizontal left-to-right. */
|
|
10
13
|
orientation = input('vertical', ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
|
|
11
14
|
/** Alignment of the item content relative to the connector line. */
|
|
@@ -51,12 +54,12 @@ class TimelineComponent {
|
|
|
51
54
|
return this.id();
|
|
52
55
|
}
|
|
53
56
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TimelineComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
54
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: TimelineComponent, isStandalone: true, selector: "fk-timeline", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, reverse: { classPropertyName: "reverse", publicName: "reverse", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClass", "attr.role": "this.hostRole", "attr.aria-label": "this.hostAriaLabel", "attr.aria-orientation": "this.hostAriaOrientation", "attr.id": "this.hostId" } }, ngImport: i0, template: "@for (item of orderedItems(); track item.id ?? $index; let last = $last) {\n <div\n class=\"fk-timeline__item\"\n [class.fk-timeline__item--active]=\"item.status === 'active'\"\n [class.fk-timeline__item--completed]=\"item.status === 'completed'\"\n [class.fk-timeline__item--error]=\"item.status === 'error'\"\n [class.fk-timeline__item--warning]=\"item.status === 'warning'\"\n role=\"listitem\"\n >\n <div class=\"fk-timeline__separator\">\n <div class=\"fk-timeline__marker\">\n @if (item.icon) {\n <
|
|
57
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: TimelineComponent, isStandalone: true, selector: "fk-timeline", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, iconTemplate: { classPropertyName: "iconTemplate", publicName: "iconTemplate", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, reverse: { classPropertyName: "reverse", publicName: "reverse", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClass", "attr.role": "this.hostRole", "attr.aria-label": "this.hostAriaLabel", "attr.aria-orientation": "this.hostAriaOrientation", "attr.id": "this.hostId" } }, ngImport: i0, template: "@for (item of orderedItems(); track item.id ?? $index; let last = $last) {\n <div\n class=\"fk-timeline__item\"\n [class.fk-timeline__item--active]=\"item.status === 'active'\"\n [class.fk-timeline__item--completed]=\"item.status === 'completed'\"\n [class.fk-timeline__item--error]=\"item.status === 'error'\"\n [class.fk-timeline__item--warning]=\"item.status === 'warning'\"\n role=\"listitem\"\n >\n <div class=\"fk-timeline__separator\">\n <div class=\"fk-timeline__marker\">\n @if (item.icon && iconTemplate(); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n />\n }\n </div>\n\n @if (!last) {\n <div class=\"fk-timeline__connector\"></div>\n }\n </div>\n\n <div class=\"fk-timeline__content\">\n @if (item.title) {\n <span class=\"fk-timeline__title\">{{ item.title }}</span>\n }\n\n @if (item.description) {\n <span class=\"fk-timeline__description\">{{ item.description }}</span>\n }\n\n @if (item.timestamp) {\n <span class=\"fk-timeline__timestamp\">{{ item.timestamp }}</span>\n }\n </div>\n </div>\n}\n\n<ng-content />\n", styles: [":host{display:flex;gap:var(--fk-timeline-gap, 0)}:host.fk-timeline--vertical{flex-direction:column}:host.fk-timeline--horizontal{flex-direction:row;overflow-x:auto}.fk-timeline__item{display:flex;position:relative}.fk-timeline__separator{display:flex;flex-shrink:0;align-items:flex-start}.fk-timeline__marker{display:flex;align-items:center;justify-content:center;flex-shrink:0;border-radius:50%;background:var(--fk-timeline-marker-bg, var(--fk-color-surface, #ffffff));border:var(--fk-timeline-marker-border-width, 2px) solid var(--fk-timeline-marker-border-color, var(--fk-color-border, #d9e2ee));color:var(--fk-timeline-marker-color, var(--fk-color-muted, #8a98a8));overflow:hidden;z-index:1}.fk-timeline__connector{background:var(--fk-timeline-connector-color, var(--fk-color-border, #d9e2ee));flex-shrink:0}.fk-timeline__content{display:flex;flex-direction:column;gap:var(--fk-timeline-content-gap, var(--fk-rhythm-1, .25rem));min-width:0}.fk-timeline__title{font-size:var(--fk-timeline-title-font-size, var(--fk-typography-body-font-size, .9375rem));font-weight:var(--fk-timeline-title-font-weight, var(--fk-font-weight-medium, 500));color:var(--fk-timeline-title-color, var(--fk-color-text, #1f2d3d))}.fk-timeline__description{font-size:var(--fk-timeline-description-font-size, var(--fk-typography-small-font-size, .8125rem));color:var(--fk-timeline-description-color, var(--fk-color-muted, #8a98a8))}.fk-timeline__timestamp{font-size:var(--fk-timeline-timestamp-font-size, var(--fk-typography-caption-font-size, .6875rem));color:var(--fk-timeline-timestamp-color, var(--fk-color-muted, #8a98a8))}.fk-timeline__item--active .fk-timeline__marker{background:var(--fk-timeline-marker-active, var(--fk-color-primary, #0a84ff));border-color:var(--fk-timeline-marker-active, var(--fk-color-primary, #0a84ff));color:var(--fk-color-surface, #ffffff)}.fk-timeline__item--completed .fk-timeline__marker{background:var(--fk-timeline-marker-completed, var(--fk-color-success, #10b981));border-color:var(--fk-timeline-marker-completed, var(--fk-color-success, #10b981));color:var(--fk-color-surface, #ffffff)}.fk-timeline__item--error .fk-timeline__marker{background:var(--fk-timeline-marker-error, var(--fk-color-danger, #e02424));border-color:var(--fk-timeline-marker-error, var(--fk-color-danger, #e02424));color:var(--fk-color-surface, #ffffff)}.fk-timeline__item--warning .fk-timeline__marker{background:var(--fk-timeline-marker-warning, var(--fk-color-warning, #f59e0b));border-color:var(--fk-timeline-marker-warning, var(--fk-color-warning, #f59e0b));color:var(--fk-color-surface, #ffffff)}:host.fk-timeline--vertical .fk-timeline__item{flex-direction:row;align-items:stretch}:host.fk-timeline--vertical .fk-timeline__separator{flex-direction:column;align-items:center;flex-shrink:0}:host.fk-timeline--vertical .fk-timeline__connector{width:var(--fk-timeline-connector-width, 2px);flex:1;min-height:var(--fk-rhythm-2, .5rem)}:host.fk-timeline--vertical .fk-timeline__content{padding-bottom:var(--fk-timeline-item-gap, var(--fk-rhythm-3, .75rem))}:host.fk-timeline--vertical.fk-timeline--sm .fk-timeline__marker{width:var(--fk-timeline-marker-size-sm, 1rem);height:var(--fk-timeline-marker-size-sm, 1rem)}:host.fk-timeline--vertical.fk-timeline--sm .fk-timeline__content{padding-left:var(--fk-rhythm-2, .5rem);padding-top:0}:host.fk-timeline--vertical.fk-timeline--md .fk-timeline__marker{width:var(--fk-timeline-marker-size-md, 1.5rem);height:var(--fk-timeline-marker-size-md, 1.5rem)}:host.fk-timeline--vertical.fk-timeline--md .fk-timeline__content{padding-left:var(--fk-rhythm-3, .75rem);padding-top:.125rem}:host.fk-timeline--vertical.fk-timeline--lg .fk-timeline__marker{width:var(--fk-timeline-marker-size-lg, 2rem);height:var(--fk-timeline-marker-size-lg, 2rem)}:host.fk-timeline--vertical.fk-timeline--lg .fk-timeline__content{padding-left:var(--fk-rhythm-3, .75rem);padding-top:.25rem}:host.fk-timeline--vertical.fk-timeline--end .fk-timeline__item{flex-direction:row-reverse}:host.fk-timeline--vertical.fk-timeline--end .fk-timeline__content{padding-left:0;padding-right:var(--fk-rhythm-3, .75rem);text-align:right}:host.fk-timeline--vertical.fk-timeline--alternate .fk-timeline__item{display:grid;grid-template-columns:1fr auto 1fr}:host.fk-timeline--vertical.fk-timeline--alternate .fk-timeline__separator{grid-column:2}:host.fk-timeline--vertical.fk-timeline--alternate .fk-timeline__item:nth-child(odd) .fk-timeline__content{grid-column:3;padding-left:var(--fk-rhythm-3, .75rem);padding-right:0;text-align:left}:host.fk-timeline--vertical.fk-timeline--alternate .fk-timeline__item:nth-child(2n) .fk-timeline__content{grid-column:1;grid-row:1;padding-left:0;padding-right:var(--fk-rhythm-3, .75rem);text-align:right}:host.fk-timeline--vertical.fk-timeline--alternate .fk-timeline__item:nth-child(2n) .fk-timeline__separator{grid-row:1}:host.fk-timeline--horizontal .fk-timeline__item{display:flex;flex-direction:column;align-items:center;flex:1 1 0;min-width:0}:host.fk-timeline--horizontal .fk-timeline__item:last-child{flex:0 0 auto}:host.fk-timeline--horizontal .fk-timeline__separator{flex-direction:row;align-items:center;width:100%}:host.fk-timeline--horizontal .fk-timeline__connector{height:var(--fk-timeline-connector-width, 2px);flex:1;min-width:var(--fk-rhythm-3, .75rem)}:host.fk-timeline--horizontal .fk-timeline__content{align-items:center;text-align:center;padding-top:var(--fk-rhythm-2, .5rem);max-width:8rem}:host.fk-timeline--horizontal.fk-timeline--sm .fk-timeline__marker{width:var(--fk-timeline-marker-size-sm, 1rem);height:var(--fk-timeline-marker-size-sm, 1rem)}:host.fk-timeline--horizontal.fk-timeline--md .fk-timeline__marker{width:var(--fk-timeline-marker-size-md, 1.5rem);height:var(--fk-timeline-marker-size-md, 1.5rem)}:host.fk-timeline--horizontal.fk-timeline--lg .fk-timeline__marker{width:var(--fk-timeline-marker-size-lg, 2rem);height:var(--fk-timeline-marker-size-lg, 2rem)}@media(prefers-reduced-motion:reduce){.fk-timeline__connector,.fk-timeline__marker{transition:none}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
55
58
|
}
|
|
56
59
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TimelineComponent, decorators: [{
|
|
57
60
|
type: Component,
|
|
58
|
-
args: [{ selector: 'fk-timeline', standalone: true, imports: [
|
|
59
|
-
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], reverse: [{ type: i0.Input, args: [{ isSignal: true, alias: "reverse", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], hostClass: [{
|
|
61
|
+
args: [{ selector: 'fk-timeline', standalone: true, imports: [NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "@for (item of orderedItems(); track item.id ?? $index; let last = $last) {\n <div\n class=\"fk-timeline__item\"\n [class.fk-timeline__item--active]=\"item.status === 'active'\"\n [class.fk-timeline__item--completed]=\"item.status === 'completed'\"\n [class.fk-timeline__item--error]=\"item.status === 'error'\"\n [class.fk-timeline__item--warning]=\"item.status === 'warning'\"\n role=\"listitem\"\n >\n <div class=\"fk-timeline__separator\">\n <div class=\"fk-timeline__marker\">\n @if (item.icon && iconTemplate(); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n />\n }\n </div>\n\n @if (!last) {\n <div class=\"fk-timeline__connector\"></div>\n }\n </div>\n\n <div class=\"fk-timeline__content\">\n @if (item.title) {\n <span class=\"fk-timeline__title\">{{ item.title }}</span>\n }\n\n @if (item.description) {\n <span class=\"fk-timeline__description\">{{ item.description }}</span>\n }\n\n @if (item.timestamp) {\n <span class=\"fk-timeline__timestamp\">{{ item.timestamp }}</span>\n }\n </div>\n </div>\n}\n\n<ng-content />\n", styles: [":host{display:flex;gap:var(--fk-timeline-gap, 0)}:host.fk-timeline--vertical{flex-direction:column}:host.fk-timeline--horizontal{flex-direction:row;overflow-x:auto}.fk-timeline__item{display:flex;position:relative}.fk-timeline__separator{display:flex;flex-shrink:0;align-items:flex-start}.fk-timeline__marker{display:flex;align-items:center;justify-content:center;flex-shrink:0;border-radius:50%;background:var(--fk-timeline-marker-bg, var(--fk-color-surface, #ffffff));border:var(--fk-timeline-marker-border-width, 2px) solid var(--fk-timeline-marker-border-color, var(--fk-color-border, #d9e2ee));color:var(--fk-timeline-marker-color, var(--fk-color-muted, #8a98a8));overflow:hidden;z-index:1}.fk-timeline__connector{background:var(--fk-timeline-connector-color, var(--fk-color-border, #d9e2ee));flex-shrink:0}.fk-timeline__content{display:flex;flex-direction:column;gap:var(--fk-timeline-content-gap, var(--fk-rhythm-1, .25rem));min-width:0}.fk-timeline__title{font-size:var(--fk-timeline-title-font-size, var(--fk-typography-body-font-size, .9375rem));font-weight:var(--fk-timeline-title-font-weight, var(--fk-font-weight-medium, 500));color:var(--fk-timeline-title-color, var(--fk-color-text, #1f2d3d))}.fk-timeline__description{font-size:var(--fk-timeline-description-font-size, var(--fk-typography-small-font-size, .8125rem));color:var(--fk-timeline-description-color, var(--fk-color-muted, #8a98a8))}.fk-timeline__timestamp{font-size:var(--fk-timeline-timestamp-font-size, var(--fk-typography-caption-font-size, .6875rem));color:var(--fk-timeline-timestamp-color, var(--fk-color-muted, #8a98a8))}.fk-timeline__item--active .fk-timeline__marker{background:var(--fk-timeline-marker-active, var(--fk-color-primary, #0a84ff));border-color:var(--fk-timeline-marker-active, var(--fk-color-primary, #0a84ff));color:var(--fk-color-surface, #ffffff)}.fk-timeline__item--completed .fk-timeline__marker{background:var(--fk-timeline-marker-completed, var(--fk-color-success, #10b981));border-color:var(--fk-timeline-marker-completed, var(--fk-color-success, #10b981));color:var(--fk-color-surface, #ffffff)}.fk-timeline__item--error .fk-timeline__marker{background:var(--fk-timeline-marker-error, var(--fk-color-danger, #e02424));border-color:var(--fk-timeline-marker-error, var(--fk-color-danger, #e02424));color:var(--fk-color-surface, #ffffff)}.fk-timeline__item--warning .fk-timeline__marker{background:var(--fk-timeline-marker-warning, var(--fk-color-warning, #f59e0b));border-color:var(--fk-timeline-marker-warning, var(--fk-color-warning, #f59e0b));color:var(--fk-color-surface, #ffffff)}:host.fk-timeline--vertical .fk-timeline__item{flex-direction:row;align-items:stretch}:host.fk-timeline--vertical .fk-timeline__separator{flex-direction:column;align-items:center;flex-shrink:0}:host.fk-timeline--vertical .fk-timeline__connector{width:var(--fk-timeline-connector-width, 2px);flex:1;min-height:var(--fk-rhythm-2, .5rem)}:host.fk-timeline--vertical .fk-timeline__content{padding-bottom:var(--fk-timeline-item-gap, var(--fk-rhythm-3, .75rem))}:host.fk-timeline--vertical.fk-timeline--sm .fk-timeline__marker{width:var(--fk-timeline-marker-size-sm, 1rem);height:var(--fk-timeline-marker-size-sm, 1rem)}:host.fk-timeline--vertical.fk-timeline--sm .fk-timeline__content{padding-left:var(--fk-rhythm-2, .5rem);padding-top:0}:host.fk-timeline--vertical.fk-timeline--md .fk-timeline__marker{width:var(--fk-timeline-marker-size-md, 1.5rem);height:var(--fk-timeline-marker-size-md, 1.5rem)}:host.fk-timeline--vertical.fk-timeline--md .fk-timeline__content{padding-left:var(--fk-rhythm-3, .75rem);padding-top:.125rem}:host.fk-timeline--vertical.fk-timeline--lg .fk-timeline__marker{width:var(--fk-timeline-marker-size-lg, 2rem);height:var(--fk-timeline-marker-size-lg, 2rem)}:host.fk-timeline--vertical.fk-timeline--lg .fk-timeline__content{padding-left:var(--fk-rhythm-3, .75rem);padding-top:.25rem}:host.fk-timeline--vertical.fk-timeline--end .fk-timeline__item{flex-direction:row-reverse}:host.fk-timeline--vertical.fk-timeline--end .fk-timeline__content{padding-left:0;padding-right:var(--fk-rhythm-3, .75rem);text-align:right}:host.fk-timeline--vertical.fk-timeline--alternate .fk-timeline__item{display:grid;grid-template-columns:1fr auto 1fr}:host.fk-timeline--vertical.fk-timeline--alternate .fk-timeline__separator{grid-column:2}:host.fk-timeline--vertical.fk-timeline--alternate .fk-timeline__item:nth-child(odd) .fk-timeline__content{grid-column:3;padding-left:var(--fk-rhythm-3, .75rem);padding-right:0;text-align:left}:host.fk-timeline--vertical.fk-timeline--alternate .fk-timeline__item:nth-child(2n) .fk-timeline__content{grid-column:1;grid-row:1;padding-left:0;padding-right:var(--fk-rhythm-3, .75rem);text-align:right}:host.fk-timeline--vertical.fk-timeline--alternate .fk-timeline__item:nth-child(2n) .fk-timeline__separator{grid-row:1}:host.fk-timeline--horizontal .fk-timeline__item{display:flex;flex-direction:column;align-items:center;flex:1 1 0;min-width:0}:host.fk-timeline--horizontal .fk-timeline__item:last-child{flex:0 0 auto}:host.fk-timeline--horizontal .fk-timeline__separator{flex-direction:row;align-items:center;width:100%}:host.fk-timeline--horizontal .fk-timeline__connector{height:var(--fk-timeline-connector-width, 2px);flex:1;min-width:var(--fk-rhythm-3, .75rem)}:host.fk-timeline--horizontal .fk-timeline__content{align-items:center;text-align:center;padding-top:var(--fk-rhythm-2, .5rem);max-width:8rem}:host.fk-timeline--horizontal.fk-timeline--sm .fk-timeline__marker{width:var(--fk-timeline-marker-size-sm, 1rem);height:var(--fk-timeline-marker-size-sm, 1rem)}:host.fk-timeline--horizontal.fk-timeline--md .fk-timeline__marker{width:var(--fk-timeline-marker-size-md, 1.5rem);height:var(--fk-timeline-marker-size-md, 1.5rem)}:host.fk-timeline--horizontal.fk-timeline--lg .fk-timeline__marker{width:var(--fk-timeline-marker-size-lg, 2rem);height:var(--fk-timeline-marker-size-lg, 2rem)}@media(prefers-reduced-motion:reduce){.fk-timeline__connector,.fk-timeline__marker{transition:none}}\n"] }]
|
|
62
|
+
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], iconTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconTemplate", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], reverse: [{ type: i0.Input, args: [{ isSignal: true, alias: "reverse", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], hostClass: [{
|
|
60
63
|
type: HostBinding,
|
|
61
64
|
args: ['class']
|
|
62
65
|
}], hostRole: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frame-kit-ui-ng-ui-timeline.mjs","sources":["../../../../packages/ui-ng/ui/timeline/timeline.component.ts","../../../../packages/ui-ng/ui/timeline/timeline.component.html","../../../../packages/ui-ng/ui/timeline/frame-kit-ui-ng-ui-timeline.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n} from '@angular/core';\n\nimport
|
|
1
|
+
{"version":3,"file":"frame-kit-ui-ng-ui-timeline.mjs","sources":["../../../../packages/ui-ng/ui/timeline/timeline.component.ts","../../../../packages/ui-ng/ui/timeline/timeline.component.html","../../../../packages/ui-ng/ui/timeline/frame-kit-ui-ng-ui-timeline.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n TemplateRef,\n} from '@angular/core';\n\nimport type {\n TimelineAlign,\n TimelineItemData,\n TimelineOrientation,\n TimelineSize,\n} from './timeline.types';\n\n@Component({\n selector: 'fk-timeline',\n standalone: true,\n imports: [NgTemplateOutlet],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './timeline.component.html',\n styleUrl: './timeline.component.scss',\n})\nexport class TimelineComponent {\n // ===== INPUTS =====\n /** Array of timeline item data objects rendered in order. */\n readonly items = input<TimelineItemData[]>([]);\n /** Optional template rendering each item's marker icon (the app owns the icon\n * system). Receives the item as `$implicit`; render it from `item.icon`. */\n readonly iconTemplate = input<\n TemplateRef<{ $implicit: TimelineItemData }> | undefined\n >(undefined);\n /** Direction the timeline runs — vertical stacks items top-to-bottom, horizontal left-to-right. */\n readonly orientation = input<TimelineOrientation>('vertical');\n /** Alignment of the item content relative to the connector line. */\n readonly align = input<TimelineAlign>('start');\n /** Size variant controlling the dot and spacing of each item. */\n readonly size = input<TimelineSize>('md');\n /** When true, the items array is rendered in reverse order. */\n readonly reverse = input<boolean>(false);\n\n // ===== BASE PROPS =====\n readonly ariaLabel = input<string | null>(null);\n readonly className = input<string>('');\n readonly id = input<string | null>(null);\n\n // ===== COMPUTED =====\n readonly orderedItems = computed(() => {\n const list = this.items();\n\n return this.reverse() ? [...list].reverse() : list;\n });\n\n readonly classes = computed(() => {\n return [\n 'fk-timeline',\n `fk-timeline--${this.orientation()}`,\n `fk-timeline--${this.align()}`,\n `fk-timeline--${this.size()}`,\n this.className(),\n ]\n .filter(Boolean)\n .join(' ');\n });\n\n // ===== HOST BINDINGS =====\n @HostBinding('class')\n get hostClass() {\n return this.classes();\n }\n\n @HostBinding('attr.role')\n get hostRole() {\n return 'list';\n }\n\n @HostBinding('attr.aria-label')\n get hostAriaLabel() {\n return this.ariaLabel();\n }\n\n @HostBinding('attr.aria-orientation')\n get hostAriaOrientation() {\n return this.orientation();\n }\n\n @HostBinding('attr.id')\n get hostId() {\n return this.id();\n }\n}\n","@for (item of orderedItems(); track item.id ?? $index; let last = $last) {\n <div\n class=\"fk-timeline__item\"\n [class.fk-timeline__item--active]=\"item.status === 'active'\"\n [class.fk-timeline__item--completed]=\"item.status === 'completed'\"\n [class.fk-timeline__item--error]=\"item.status === 'error'\"\n [class.fk-timeline__item--warning]=\"item.status === 'warning'\"\n role=\"listitem\"\n >\n <div class=\"fk-timeline__separator\">\n <div class=\"fk-timeline__marker\">\n @if (item.icon && iconTemplate(); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n />\n }\n </div>\n\n @if (!last) {\n <div class=\"fk-timeline__connector\"></div>\n }\n </div>\n\n <div class=\"fk-timeline__content\">\n @if (item.title) {\n <span class=\"fk-timeline__title\">{{ item.title }}</span>\n }\n\n @if (item.description) {\n <span class=\"fk-timeline__description\">{{ item.description }}</span>\n }\n\n @if (item.timestamp) {\n <span class=\"fk-timeline__timestamp\">{{ item.timestamp }}</span>\n }\n </div>\n </div>\n}\n\n<ng-content />\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { NgTemplateOutlet } from '@angular/common';
|
|
1
2
|
import * as i0 from '@angular/core';
|
|
2
3
|
import { input, output, viewChild, computed, HostBinding, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
4
|
import { AvatarComponent } from '@frame-kit/ui-ng/ui/avatar';
|
|
4
5
|
import { DropdownMenuComponent, DropdownTriggerDirective, DropdownPanelDirective } from '@frame-kit/ui-ng/ui/dropdown-menu';
|
|
5
|
-
import { MenuItemComponent, MenuSeparatorComponent } from '@frame-kit/ui-ng/ui/menu-item';
|
|
6
|
+
import { MenuItemComponent, MenuSeparatorComponent, FkMenuItemIconDirective } from '@frame-kit/ui-ng/ui/menu-item';
|
|
6
7
|
|
|
7
8
|
class UserMenuComponent {
|
|
8
9
|
// ===== IDENTITY =====
|
|
@@ -24,6 +25,12 @@ class UserMenuComponent {
|
|
|
24
25
|
// ===== MENU =====
|
|
25
26
|
/** Array of menu item configurations rendered in the dropdown. */
|
|
26
27
|
menuItems = input([], ...(ngDevMode ? [{ debugName: "menuItems" }] : /* istanbul ignore next */ []));
|
|
28
|
+
/**
|
|
29
|
+
* Optional template used to render each item's leading icon (the app owns the
|
|
30
|
+
* icon system). Receives the `MenuItem` as `$implicit`; render the icon from
|
|
31
|
+
* `item.icon`. When omitted, items render without an icon.
|
|
32
|
+
*/
|
|
33
|
+
iconTemplate = input(null, ...(ngDevMode ? [{ debugName: "iconTemplate" }] : /* istanbul ignore next */ []));
|
|
27
34
|
/** Preferred placement of the dropdown panel relative to the trigger. */
|
|
28
35
|
placement = input('bottom-end', ...(ngDevMode ? [{ debugName: "placement" }] : /* istanbul ignore next */ []));
|
|
29
36
|
// ===== DISPLAY =====
|
|
@@ -115,19 +122,21 @@ class UserMenuComponent {
|
|
|
115
122
|
this.dropdownRef()?.toggle();
|
|
116
123
|
}
|
|
117
124
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: UserMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
118
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: UserMenuComponent, isStandalone: true, selector: "fk-user-menu", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, email: { classPropertyName: "email", publicName: "email", isSignal: true, isRequired: false, transformFunction: null }, avatarUrl: { classPropertyName: "avatarUrl", publicName: "avatarUrl", isSignal: true, isRequired: false, transformFunction: null }, initials: { classPropertyName: "initials", publicName: "initials", isSignal: true, isRequired: false, transformFunction: null }, userId: { classPropertyName: "userId", publicName: "userId", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, showStatus: { classPropertyName: "showStatus", publicName: "showStatus", isSignal: true, isRequired: false, transformFunction: null }, menuItems: { classPropertyName: "menuItems", publicName: "menuItems", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, showName: { classPropertyName: "showName", publicName: "showName", isSignal: true, isRequired: false, transformFunction: null }, showEmail: { classPropertyName: "showEmail", publicName: "showEmail", isSignal: true, isRequired: false, transformFunction: null }, showChevron: { classPropertyName: "showChevron", publicName: "showChevron", isSignal: true, isRequired: false, transformFunction: null }, infoPlacement: { classPropertyName: "infoPlacement", publicName: "infoPlacement", isSignal: true, isRequired: false, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { avatarClick: "avatarClick", menuOpen: "menuOpen", menuClose: "menuClose", menuItemClick: "menuItemClick", logoutClick: "logoutClick" }, host: { properties: { "class": "this.hostClass", "attr.id": "this.hostId" } }, viewQueries: [{ propertyName: "dropdownRef", first: true, predicate: DropdownMenuComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<fk-dropdown-menu\n [placement]=\"placement()\"\n [disabled]=\"disabled() || loading()\"\n [ariaLabel]=\"'Menu for ' + name()\"\n (menuOpen)=\"onMenuOpen()\"\n (menuClose)=\"onMenuClose()\"\n>\n <!-- Trigger button -->\n <button\n fkDropdownTrigger\n class=\"fk-user-menu__trigger\"\n type=\"button\"\n [disabled]=\"disabled() || loading()\"\n [attr.aria-label]=\"ariaLabel() ?? 'User menu for ' + name()\"\n >\n <!-- Avatar -->\n <fk-avatar\n [name]=\"name()\"\n [avatarUrl]=\"avatarUrl()\"\n [initials]=\"initials()\"\n [size]=\"size()\"\n [status]=\"status()\"\n [showStatus]=\"showStatus()\"\n />\n\n <!-- Name & email block -->\n @if (showName() || showEmail()) {\n <span class=\"fk-user-menu__info\">\n @if (showName()) {\n <span class=\"fk-user-menu__name\">{{ name() }}</span>\n }\n @if (showEmail() && email()) {\n <span class=\"fk-user-menu__email\">{{ email() }}</span>\n }\n </span>\n }\n\n <!-- Badge -->\n @if (badge()) {\n <span class=\"fk-user-menu__badge\">{{ badge() }}</span>\n }\n\n <!-- Chevron -->\n @if (showChevron()) {\n <span\n class=\"fk-user-menu__chevron\"\n [class.fk-user-menu__chevron--open]=\"isOpen()\"\n aria-hidden=\"true\"\n >\n <svg\n class=\"fk-user-menu__chevron-svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 18 18\"\n >\n <path\n d=\"M4.5 6.75L9 11.25L13.5 6.75\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n fill=\"none\"\n />\n </svg>\n </span>\n }\n </button>\n\n <!-- Panel content -->\n <ng-template fkDropdownPanel>\n <!-- User header inside panel (popover variant) -->\n @if (variant() === 'popover') {\n <div class=\"fk-user-menu__panel-header\">\n <span class=\"fk-user-menu__panel-name\">{{ name() }}</span>\n @if (email()) {\n <span class=\"fk-user-menu__panel-email\">{{ email() }}</span>\n }\n </div>\n }\n\n <!-- Menu items -->\n @for (item of menuItems(); track item.value) {\n @if (item.separator) {\n <fk-menu-separator />\n } @else {\n <fk-menu-item\n [icon]=\"item.icon ?? null\"\n [danger]=\"item.danger ?? false\"\n [disabled]=\"item.disabled ?? false\"\n (itemClick)=\"selectItem(item)\"\n >\n {{ item.label }}\n </fk-menu-item>\n }\n }\n </ng-template>\n</fk-dropdown-menu>\n", styles: [":host{display:inline-block;position:relative;--fk-dropdown-menu-panel-z: var(--fk-user-menu-panel-z, 100);--fk-dropdown-menu-panel-min-width: var( --fk-user-menu-panel-min-width, 12rem );--fk-dropdown-menu-panel-padding: var( --fk-user-menu-panel-padding, var(--fk-rhythm-1, .25rem) );--fk-dropdown-menu-panel-radius: var( --fk-user-menu-panel-radius, var(--fk-radius-lg, .75rem) );--fk-dropdown-menu-panel-bg: var( --fk-user-menu-panel-bg, var(--fk-color-surface, #ffffff) );--fk-dropdown-menu-panel-border: var( --fk-user-menu-panel-border, var(--fk-color-border, #d9e2ee) );--fk-dropdown-menu-panel-shadow: var( --fk-user-menu-panel-shadow, 0 4px 16px rgba(0, 0, 0, .08), 0 1px 4px rgba(0, 0, 0, .04) );--fk-menu-item-gap: var(--fk-user-menu-item-gap, var(--fk-rhythm-2, .5rem));--fk-menu-item-padding: var( --fk-user-menu-item-padding, var(--fk-rhythm-2, .5rem) var(--fk-rhythm-3, .75rem) );--fk-menu-item-radius: var( --fk-user-menu-item-radius, var(--fk-radius-md, .375rem) );--fk-menu-item-font-family: var( --fk-user-menu-item-font-family, var(--fk-font-family-base) );--fk-menu-item-font-size: var(--fk-user-menu-item-font-size, .875rem);--fk-menu-item-color: var( --fk-user-menu-item-color, var(--fk-color-text, #1f2d3d) );--fk-menu-item-bg-hover: var( --fk-user-menu-item-bg-hover, var(--fk-color-surface-muted, #f7f9fb) );--fk-menu-item-danger-color: var( --fk-user-menu-item-danger-color, var(--fk-color-danger, #e02424) );--fk-menu-item-danger-bg-hover: var( --fk-user-menu-item-danger-bg-hover, #fef2f2 );--fk-menu-item-focus-ring: var( --fk-user-menu-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)) );--fk-menu-separator-color: var( --fk-user-menu-separator-color, var(--fk-color-border, #d9e2ee) )}.fk-user-menu__trigger{display:inline-flex;align-items:center;gap:var(--fk-user-menu-trigger-gap, var(--fk-rhythm-2, .5rem));padding:var(--fk-user-menu-trigger-padding, var(--fk-rhythm-1, .25rem));border:none;border-radius:var(--fk-user-menu-trigger-radius, var(--fk-radius-md, .375rem));background:var(--fk-user-menu-trigger-bg, transparent);cursor:pointer;transition:background-color .15s ease}.fk-user-menu__trigger:hover{background-color:var(--fk-user-menu-trigger-bg-hover, var(--fk-color-surface-muted, #f7f9fb))}.fk-user-menu__trigger:focus-visible{outline:none;box-shadow:var(--fk-user-menu-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)))}.fk-user-menu__trigger:disabled{opacity:var(--fk-user-menu-opacity-disabled, .6);cursor:not-allowed}.fk-user-menu__info{display:flex;flex-direction:column;align-items:flex-start;text-align:left;line-height:1.3}.fk-user-menu__name{font-family:var(--fk-user-menu-name-font-family, var(--fk-font-family-base));font-size:var(--fk-user-menu-name-font-size, .875rem);font-weight:var(--fk-user-menu-name-font-weight, var(--fk-font-weight-semibold, 600));color:var(--fk-user-menu-name-color, var(--fk-color-text, #1f2d3d))}.fk-user-menu__email{font-family:var(--fk-user-menu-email-font-family, var(--fk-font-family-base));font-size:var(--fk-user-menu-email-font-size, .75rem);color:var(--fk-user-menu-email-color, var(--fk-color-muted, #8a98a8))}.fk-user-menu__badge{display:inline-flex;align-items:center;padding:.125rem .5rem;border-radius:var(--fk-user-menu-badge-radius, var(--fk-radius-full, 9999px));background-color:var(--fk-user-menu-badge-bg, var(--fk-color-primary, #0a84ff));color:var(--fk-user-menu-badge-color, var(--fk-color-surface, #ffffff));font-family:var(--fk-user-menu-badge-font-family, var(--fk-font-family-base));font-size:var(--fk-user-menu-badge-font-size, .625rem);font-weight:var(--fk-user-menu-badge-font-weight, var(--fk-font-weight-semibold, 600));text-transform:uppercase;letter-spacing:.04em;line-height:1.4}.fk-user-menu__chevron{display:inline-flex;color:var(--fk-user-menu-chevron-color, var(--fk-color-muted, #8a98a8));transition:transform .15s ease}.fk-user-menu__chevron--open{transform:rotate(180deg)}.fk-user-menu__chevron-svg{display:block}.fk-user-menu__panel-header{display:flex;flex-direction:column;padding:var(--fk-rhythm-3, .75rem) var(--fk-rhythm-3, .75rem) var(--fk-rhythm-2, .5rem);border-bottom:1px solid var(--fk-user-menu-separator-color, var(--fk-color-border, #d9e2ee));margin-bottom:var(--fk-rhythm-1, .25rem)}.fk-user-menu__panel-name{font-family:var(--fk-user-menu-name-font-family, var(--fk-font-family-base));font-size:var(--fk-user-menu-name-font-size, .875rem);font-weight:var(--fk-user-menu-name-font-weight, var(--fk-font-weight-semibold, 600));color:var(--fk-user-menu-name-color, var(--fk-color-text, #1f2d3d))}.fk-user-menu__panel-email{font-family:var(--fk-user-menu-email-font-family, var(--fk-font-family-base));font-size:var(--fk-user-menu-email-font-size, .75rem);color:var(--fk-user-menu-email-color, var(--fk-color-muted, #8a98a8));margin-top:.125rem}:host.fk-user-menu--info-start .fk-user-menu__info{order:-1;align-items:flex-end;text-align:right}:host.fk-user-menu--disabled{pointer-events:none}\n"], dependencies: [{ kind: "component", type: AvatarComponent, selector: "fk-avatar", inputs: ["name", "avatarUrl", "initials", "status", "showStatus", "size", "className", "id", "ariaLabel"] }, { kind: "component", type: DropdownMenuComponent, selector: "fk-dropdown-menu", inputs: ["placement", "disabled", "portal", "panelClass", "ariaLabel", "className", "id"], outputs: ["menuOpen", "menuClose"] }, { kind: "directive", type: DropdownTriggerDirective, selector: "[fkDropdownTrigger]" }, { kind: "directive", type: DropdownPanelDirective, selector: "[fkDropdownPanel]" }, { kind: "component", type: MenuItemComponent, selector: "fk-menu-item", inputs: ["icon", "danger", "disabled"], outputs: ["itemClick"] }, { kind: "component", type: MenuSeparatorComponent, selector: "fk-menu-separator" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
125
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: UserMenuComponent, isStandalone: true, selector: "fk-user-menu", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, email: { classPropertyName: "email", publicName: "email", isSignal: true, isRequired: false, transformFunction: null }, avatarUrl: { classPropertyName: "avatarUrl", publicName: "avatarUrl", isSignal: true, isRequired: false, transformFunction: null }, initials: { classPropertyName: "initials", publicName: "initials", isSignal: true, isRequired: false, transformFunction: null }, userId: { classPropertyName: "userId", publicName: "userId", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, showStatus: { classPropertyName: "showStatus", publicName: "showStatus", isSignal: true, isRequired: false, transformFunction: null }, menuItems: { classPropertyName: "menuItems", publicName: "menuItems", isSignal: true, isRequired: false, transformFunction: null }, iconTemplate: { classPropertyName: "iconTemplate", publicName: "iconTemplate", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, showName: { classPropertyName: "showName", publicName: "showName", isSignal: true, isRequired: false, transformFunction: null }, showEmail: { classPropertyName: "showEmail", publicName: "showEmail", isSignal: true, isRequired: false, transformFunction: null }, showChevron: { classPropertyName: "showChevron", publicName: "showChevron", isSignal: true, isRequired: false, transformFunction: null }, infoPlacement: { classPropertyName: "infoPlacement", publicName: "infoPlacement", isSignal: true, isRequired: false, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { avatarClick: "avatarClick", menuOpen: "menuOpen", menuClose: "menuClose", menuItemClick: "menuItemClick", logoutClick: "logoutClick" }, host: { properties: { "class": "this.hostClass", "attr.id": "this.hostId" } }, viewQueries: [{ propertyName: "dropdownRef", first: true, predicate: DropdownMenuComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<fk-dropdown-menu\n [placement]=\"placement()\"\n [disabled]=\"disabled() || loading()\"\n [ariaLabel]=\"'Menu for ' + name()\"\n (menuOpen)=\"onMenuOpen()\"\n (menuClose)=\"onMenuClose()\"\n>\n <!-- Trigger button -->\n <button\n fkDropdownTrigger\n class=\"fk-user-menu__trigger\"\n type=\"button\"\n [disabled]=\"disabled() || loading()\"\n [attr.aria-label]=\"ariaLabel() ?? 'User menu for ' + name()\"\n >\n <!-- Avatar -->\n <fk-avatar\n [name]=\"name()\"\n [avatarUrl]=\"avatarUrl()\"\n [initials]=\"initials()\"\n [size]=\"size()\"\n [status]=\"status()\"\n [showStatus]=\"showStatus()\"\n />\n\n <!-- Name & email block -->\n @if (showName() || showEmail()) {\n <span class=\"fk-user-menu__info\">\n @if (showName()) {\n <span class=\"fk-user-menu__name\">{{ name() }}</span>\n }\n @if (showEmail() && email()) {\n <span class=\"fk-user-menu__email\">{{ email() }}</span>\n }\n </span>\n }\n\n <!-- Badge -->\n @if (badge()) {\n <span class=\"fk-user-menu__badge\">{{ badge() }}</span>\n }\n\n <!-- Chevron -->\n @if (showChevron()) {\n <span\n class=\"fk-user-menu__chevron\"\n [class.fk-user-menu__chevron--open]=\"isOpen()\"\n aria-hidden=\"true\"\n >\n <svg\n class=\"fk-user-menu__chevron-svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 18 18\"\n >\n <path\n d=\"M4.5 6.75L9 11.25L13.5 6.75\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n fill=\"none\"\n />\n </svg>\n </span>\n }\n </button>\n\n <!-- Panel content -->\n <ng-template fkDropdownPanel>\n <!-- User header inside panel (popover variant) -->\n @if (variant() === 'popover') {\n <div class=\"fk-user-menu__panel-header\">\n <span class=\"fk-user-menu__panel-name\">{{ name() }}</span>\n @if (email()) {\n <span class=\"fk-user-menu__panel-email\">{{ email() }}</span>\n }\n </div>\n }\n\n <!-- Menu items -->\n @for (item of menuItems(); track item.value) {\n @if (item.separator) {\n <fk-menu-separator />\n } @else {\n <fk-menu-item\n [danger]=\"item.danger ?? false\"\n [disabled]=\"item.disabled ?? false\"\n (itemClick)=\"selectItem(item)\"\n >\n @if (item.icon && iconTemplate(); as tpl) {\n <span fkMenuItemIcon>\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n />\n </span>\n }\n {{ item.label }}\n </fk-menu-item>\n }\n }\n </ng-template>\n</fk-dropdown-menu>\n", styles: [":host{display:inline-block;position:relative;--fk-dropdown-menu-panel-z: var(--fk-user-menu-panel-z, 100);--fk-dropdown-menu-panel-min-width: var( --fk-user-menu-panel-min-width, 12rem );--fk-dropdown-menu-panel-padding: var( --fk-user-menu-panel-padding, var(--fk-rhythm-1, .25rem) );--fk-dropdown-menu-panel-radius: var( --fk-user-menu-panel-radius, var(--fk-radius-lg, .75rem) );--fk-dropdown-menu-panel-bg: var( --fk-user-menu-panel-bg, var(--fk-color-surface, #ffffff) );--fk-dropdown-menu-panel-border: var( --fk-user-menu-panel-border, var(--fk-color-border, #d9e2ee) );--fk-dropdown-menu-panel-shadow: var( --fk-user-menu-panel-shadow, 0 4px 16px rgba(0, 0, 0, .08), 0 1px 4px rgba(0, 0, 0, .04) );--fk-menu-item-gap: var(--fk-user-menu-item-gap, var(--fk-rhythm-2, .5rem));--fk-menu-item-padding: var( --fk-user-menu-item-padding, var(--fk-rhythm-2, .5rem) var(--fk-rhythm-3, .75rem) );--fk-menu-item-radius: var( --fk-user-menu-item-radius, var(--fk-radius-md, .375rem) );--fk-menu-item-font-family: var( --fk-user-menu-item-font-family, var(--fk-font-family-base) );--fk-menu-item-font-size: var(--fk-user-menu-item-font-size, .875rem);--fk-menu-item-color: var( --fk-user-menu-item-color, var(--fk-color-text, #1f2d3d) );--fk-menu-item-bg-hover: var( --fk-user-menu-item-bg-hover, var(--fk-color-surface-muted, #f7f9fb) );--fk-menu-item-danger-color: var( --fk-user-menu-item-danger-color, var(--fk-color-danger, #e02424) );--fk-menu-item-danger-bg-hover: var( --fk-user-menu-item-danger-bg-hover, #fef2f2 );--fk-menu-item-focus-ring: var( --fk-user-menu-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)) );--fk-menu-separator-color: var( --fk-user-menu-separator-color, var(--fk-color-border, #d9e2ee) )}.fk-user-menu__trigger{display:inline-flex;align-items:center;gap:var(--fk-user-menu-trigger-gap, var(--fk-rhythm-2, .5rem));padding:var(--fk-user-menu-trigger-padding, var(--fk-rhythm-1, .25rem));border:none;border-radius:var(--fk-user-menu-trigger-radius, var(--fk-radius-md, .375rem));background:var(--fk-user-menu-trigger-bg, transparent);cursor:pointer;transition:background-color .15s ease}.fk-user-menu__trigger:hover{background-color:var(--fk-user-menu-trigger-bg-hover, var(--fk-color-surface-muted, #f7f9fb))}.fk-user-menu__trigger:focus-visible{outline:none;box-shadow:var(--fk-user-menu-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)))}.fk-user-menu__trigger:disabled{opacity:var(--fk-user-menu-opacity-disabled, .6);cursor:not-allowed}.fk-user-menu__info{display:flex;flex-direction:column;align-items:flex-start;text-align:left;line-height:1.3}.fk-user-menu__name{font-family:var(--fk-user-menu-name-font-family, var(--fk-font-family-base));font-size:var(--fk-user-menu-name-font-size, .875rem);font-weight:var(--fk-user-menu-name-font-weight, var(--fk-font-weight-semibold, 600));color:var(--fk-user-menu-name-color, var(--fk-color-text, #1f2d3d))}.fk-user-menu__email{font-family:var(--fk-user-menu-email-font-family, var(--fk-font-family-base));font-size:var(--fk-user-menu-email-font-size, .75rem);color:var(--fk-user-menu-email-color, var(--fk-color-muted, #8a98a8))}.fk-user-menu__badge{display:inline-flex;align-items:center;padding:.125rem .5rem;border-radius:var(--fk-user-menu-badge-radius, var(--fk-radius-full, 9999px));background-color:var(--fk-user-menu-badge-bg, var(--fk-color-primary, #0a84ff));color:var(--fk-user-menu-badge-color, var(--fk-color-surface, #ffffff));font-family:var(--fk-user-menu-badge-font-family, var(--fk-font-family-base));font-size:var(--fk-user-menu-badge-font-size, .625rem);font-weight:var(--fk-user-menu-badge-font-weight, var(--fk-font-weight-semibold, 600));text-transform:uppercase;letter-spacing:.04em;line-height:1.4}.fk-user-menu__chevron{display:inline-flex;color:var(--fk-user-menu-chevron-color, var(--fk-color-muted, #8a98a8));transition:transform .15s ease}.fk-user-menu__chevron--open{transform:rotate(180deg)}.fk-user-menu__chevron-svg{display:block}.fk-user-menu__panel-header{display:flex;flex-direction:column;padding:var(--fk-rhythm-3, .75rem) var(--fk-rhythm-3, .75rem) var(--fk-rhythm-2, .5rem);border-bottom:1px solid var(--fk-user-menu-separator-color, var(--fk-color-border, #d9e2ee));margin-bottom:var(--fk-rhythm-1, .25rem)}.fk-user-menu__panel-name{font-family:var(--fk-user-menu-name-font-family, var(--fk-font-family-base));font-size:var(--fk-user-menu-name-font-size, .875rem);font-weight:var(--fk-user-menu-name-font-weight, var(--fk-font-weight-semibold, 600));color:var(--fk-user-menu-name-color, var(--fk-color-text, #1f2d3d))}.fk-user-menu__panel-email{font-family:var(--fk-user-menu-email-font-family, var(--fk-font-family-base));font-size:var(--fk-user-menu-email-font-size, .75rem);color:var(--fk-user-menu-email-color, var(--fk-color-muted, #8a98a8));margin-top:.125rem}:host.fk-user-menu--info-start .fk-user-menu__info{order:-1;align-items:flex-end;text-align:right}:host.fk-user-menu--disabled{pointer-events:none}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: AvatarComponent, selector: "fk-avatar", inputs: ["name", "avatarUrl", "initials", "status", "showStatus", "size", "className", "id", "ariaLabel"] }, { kind: "component", type: DropdownMenuComponent, selector: "fk-dropdown-menu", inputs: ["placement", "disabled", "portal", "panelClass", "ariaLabel", "className", "id"], outputs: ["menuOpen", "menuClose"] }, { kind: "directive", type: DropdownTriggerDirective, selector: "[fkDropdownTrigger]" }, { kind: "directive", type: DropdownPanelDirective, selector: "[fkDropdownPanel]" }, { kind: "component", type: MenuItemComponent, selector: "fk-menu-item", inputs: ["danger", "disabled"], outputs: ["itemClick"] }, { kind: "component", type: MenuSeparatorComponent, selector: "fk-menu-separator" }, { kind: "directive", type: FkMenuItemIconDirective, selector: "[fkMenuItemIcon]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
119
126
|
}
|
|
120
127
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: UserMenuComponent, decorators: [{
|
|
121
128
|
type: Component,
|
|
122
129
|
args: [{ selector: 'fk-user-menu', standalone: true, imports: [
|
|
130
|
+
NgTemplateOutlet,
|
|
123
131
|
AvatarComponent,
|
|
124
132
|
DropdownMenuComponent,
|
|
125
133
|
DropdownTriggerDirective,
|
|
126
134
|
DropdownPanelDirective,
|
|
127
135
|
MenuItemComponent,
|
|
128
136
|
MenuSeparatorComponent,
|
|
129
|
-
|
|
130
|
-
|
|
137
|
+
FkMenuItemIconDirective,
|
|
138
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<fk-dropdown-menu\n [placement]=\"placement()\"\n [disabled]=\"disabled() || loading()\"\n [ariaLabel]=\"'Menu for ' + name()\"\n (menuOpen)=\"onMenuOpen()\"\n (menuClose)=\"onMenuClose()\"\n>\n <!-- Trigger button -->\n <button\n fkDropdownTrigger\n class=\"fk-user-menu__trigger\"\n type=\"button\"\n [disabled]=\"disabled() || loading()\"\n [attr.aria-label]=\"ariaLabel() ?? 'User menu for ' + name()\"\n >\n <!-- Avatar -->\n <fk-avatar\n [name]=\"name()\"\n [avatarUrl]=\"avatarUrl()\"\n [initials]=\"initials()\"\n [size]=\"size()\"\n [status]=\"status()\"\n [showStatus]=\"showStatus()\"\n />\n\n <!-- Name & email block -->\n @if (showName() || showEmail()) {\n <span class=\"fk-user-menu__info\">\n @if (showName()) {\n <span class=\"fk-user-menu__name\">{{ name() }}</span>\n }\n @if (showEmail() && email()) {\n <span class=\"fk-user-menu__email\">{{ email() }}</span>\n }\n </span>\n }\n\n <!-- Badge -->\n @if (badge()) {\n <span class=\"fk-user-menu__badge\">{{ badge() }}</span>\n }\n\n <!-- Chevron -->\n @if (showChevron()) {\n <span\n class=\"fk-user-menu__chevron\"\n [class.fk-user-menu__chevron--open]=\"isOpen()\"\n aria-hidden=\"true\"\n >\n <svg\n class=\"fk-user-menu__chevron-svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 18 18\"\n >\n <path\n d=\"M4.5 6.75L9 11.25L13.5 6.75\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n fill=\"none\"\n />\n </svg>\n </span>\n }\n </button>\n\n <!-- Panel content -->\n <ng-template fkDropdownPanel>\n <!-- User header inside panel (popover variant) -->\n @if (variant() === 'popover') {\n <div class=\"fk-user-menu__panel-header\">\n <span class=\"fk-user-menu__panel-name\">{{ name() }}</span>\n @if (email()) {\n <span class=\"fk-user-menu__panel-email\">{{ email() }}</span>\n }\n </div>\n }\n\n <!-- Menu items -->\n @for (item of menuItems(); track item.value) {\n @if (item.separator) {\n <fk-menu-separator />\n } @else {\n <fk-menu-item\n [danger]=\"item.danger ?? false\"\n [disabled]=\"item.disabled ?? false\"\n (itemClick)=\"selectItem(item)\"\n >\n @if (item.icon && iconTemplate(); as tpl) {\n <span fkMenuItemIcon>\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n />\n </span>\n }\n {{ item.label }}\n </fk-menu-item>\n }\n }\n </ng-template>\n</fk-dropdown-menu>\n", styles: [":host{display:inline-block;position:relative;--fk-dropdown-menu-panel-z: var(--fk-user-menu-panel-z, 100);--fk-dropdown-menu-panel-min-width: var( --fk-user-menu-panel-min-width, 12rem );--fk-dropdown-menu-panel-padding: var( --fk-user-menu-panel-padding, var(--fk-rhythm-1, .25rem) );--fk-dropdown-menu-panel-radius: var( --fk-user-menu-panel-radius, var(--fk-radius-lg, .75rem) );--fk-dropdown-menu-panel-bg: var( --fk-user-menu-panel-bg, var(--fk-color-surface, #ffffff) );--fk-dropdown-menu-panel-border: var( --fk-user-menu-panel-border, var(--fk-color-border, #d9e2ee) );--fk-dropdown-menu-panel-shadow: var( --fk-user-menu-panel-shadow, 0 4px 16px rgba(0, 0, 0, .08), 0 1px 4px rgba(0, 0, 0, .04) );--fk-menu-item-gap: var(--fk-user-menu-item-gap, var(--fk-rhythm-2, .5rem));--fk-menu-item-padding: var( --fk-user-menu-item-padding, var(--fk-rhythm-2, .5rem) var(--fk-rhythm-3, .75rem) );--fk-menu-item-radius: var( --fk-user-menu-item-radius, var(--fk-radius-md, .375rem) );--fk-menu-item-font-family: var( --fk-user-menu-item-font-family, var(--fk-font-family-base) );--fk-menu-item-font-size: var(--fk-user-menu-item-font-size, .875rem);--fk-menu-item-color: var( --fk-user-menu-item-color, var(--fk-color-text, #1f2d3d) );--fk-menu-item-bg-hover: var( --fk-user-menu-item-bg-hover, var(--fk-color-surface-muted, #f7f9fb) );--fk-menu-item-danger-color: var( --fk-user-menu-item-danger-color, var(--fk-color-danger, #e02424) );--fk-menu-item-danger-bg-hover: var( --fk-user-menu-item-danger-bg-hover, #fef2f2 );--fk-menu-item-focus-ring: var( --fk-user-menu-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)) );--fk-menu-separator-color: var( --fk-user-menu-separator-color, var(--fk-color-border, #d9e2ee) )}.fk-user-menu__trigger{display:inline-flex;align-items:center;gap:var(--fk-user-menu-trigger-gap, var(--fk-rhythm-2, .5rem));padding:var(--fk-user-menu-trigger-padding, var(--fk-rhythm-1, .25rem));border:none;border-radius:var(--fk-user-menu-trigger-radius, var(--fk-radius-md, .375rem));background:var(--fk-user-menu-trigger-bg, transparent);cursor:pointer;transition:background-color .15s ease}.fk-user-menu__trigger:hover{background-color:var(--fk-user-menu-trigger-bg-hover, var(--fk-color-surface-muted, #f7f9fb))}.fk-user-menu__trigger:focus-visible{outline:none;box-shadow:var(--fk-user-menu-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)))}.fk-user-menu__trigger:disabled{opacity:var(--fk-user-menu-opacity-disabled, .6);cursor:not-allowed}.fk-user-menu__info{display:flex;flex-direction:column;align-items:flex-start;text-align:left;line-height:1.3}.fk-user-menu__name{font-family:var(--fk-user-menu-name-font-family, var(--fk-font-family-base));font-size:var(--fk-user-menu-name-font-size, .875rem);font-weight:var(--fk-user-menu-name-font-weight, var(--fk-font-weight-semibold, 600));color:var(--fk-user-menu-name-color, var(--fk-color-text, #1f2d3d))}.fk-user-menu__email{font-family:var(--fk-user-menu-email-font-family, var(--fk-font-family-base));font-size:var(--fk-user-menu-email-font-size, .75rem);color:var(--fk-user-menu-email-color, var(--fk-color-muted, #8a98a8))}.fk-user-menu__badge{display:inline-flex;align-items:center;padding:.125rem .5rem;border-radius:var(--fk-user-menu-badge-radius, var(--fk-radius-full, 9999px));background-color:var(--fk-user-menu-badge-bg, var(--fk-color-primary, #0a84ff));color:var(--fk-user-menu-badge-color, var(--fk-color-surface, #ffffff));font-family:var(--fk-user-menu-badge-font-family, var(--fk-font-family-base));font-size:var(--fk-user-menu-badge-font-size, .625rem);font-weight:var(--fk-user-menu-badge-font-weight, var(--fk-font-weight-semibold, 600));text-transform:uppercase;letter-spacing:.04em;line-height:1.4}.fk-user-menu__chevron{display:inline-flex;color:var(--fk-user-menu-chevron-color, var(--fk-color-muted, #8a98a8));transition:transform .15s ease}.fk-user-menu__chevron--open{transform:rotate(180deg)}.fk-user-menu__chevron-svg{display:block}.fk-user-menu__panel-header{display:flex;flex-direction:column;padding:var(--fk-rhythm-3, .75rem) var(--fk-rhythm-3, .75rem) var(--fk-rhythm-2, .5rem);border-bottom:1px solid var(--fk-user-menu-separator-color, var(--fk-color-border, #d9e2ee));margin-bottom:var(--fk-rhythm-1, .25rem)}.fk-user-menu__panel-name{font-family:var(--fk-user-menu-name-font-family, var(--fk-font-family-base));font-size:var(--fk-user-menu-name-font-size, .875rem);font-weight:var(--fk-user-menu-name-font-weight, var(--fk-font-weight-semibold, 600));color:var(--fk-user-menu-name-color, var(--fk-color-text, #1f2d3d))}.fk-user-menu__panel-email{font-family:var(--fk-user-menu-email-font-family, var(--fk-font-family-base));font-size:var(--fk-user-menu-email-font-size, .75rem);color:var(--fk-user-menu-email-color, var(--fk-color-muted, #8a98a8));margin-top:.125rem}:host.fk-user-menu--info-start .fk-user-menu__info{order:-1;align-items:flex-end;text-align:right}:host.fk-user-menu--disabled{pointer-events:none}\n"] }]
|
|
139
|
+
}], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }], email: [{ type: i0.Input, args: [{ isSignal: true, alias: "email", required: false }] }], avatarUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarUrl", required: false }] }], initials: [{ type: i0.Input, args: [{ isSignal: true, alias: "initials", required: false }] }], userId: [{ type: i0.Input, args: [{ isSignal: true, alias: "userId", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], showStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "showStatus", required: false }] }], menuItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuItems", required: false }] }], iconTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconTemplate", required: false }] }], placement: [{ type: i0.Input, args: [{ isSignal: true, alias: "placement", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], showName: [{ type: i0.Input, args: [{ isSignal: true, alias: "showName", required: false }] }], showEmail: [{ type: i0.Input, args: [{ isSignal: true, alias: "showEmail", required: false }] }], showChevron: [{ type: i0.Input, args: [{ isSignal: true, alias: "showChevron", required: false }] }], infoPlacement: [{ type: i0.Input, args: [{ isSignal: true, alias: "infoPlacement", required: false }] }], badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], avatarClick: [{ type: i0.Output, args: ["avatarClick"] }], menuOpen: [{ type: i0.Output, args: ["menuOpen"] }], menuClose: [{ type: i0.Output, args: ["menuClose"] }], menuItemClick: [{ type: i0.Output, args: ["menuItemClick"] }], logoutClick: [{ type: i0.Output, args: ["logoutClick"] }], dropdownRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => DropdownMenuComponent), { isSignal: true }] }], hostClass: [{
|
|
131
140
|
type: HostBinding,
|
|
132
141
|
args: ['class']
|
|
133
142
|
}], hostId: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frame-kit-ui-ng-ui-user-menu.mjs","sources":["../../../../packages/ui-ng/ui/user-menu/user-menu.component.ts","../../../../packages/ui-ng/ui/user-menu/user-menu.component.html","../../../../packages/ui-ng/ui/user-menu/frame-kit-ui-ng-ui-user-menu.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n output,\n viewChild,\n} from '@angular/core';\n\nimport { AvatarComponent } from '@frame-kit/ui-ng/ui/avatar';\nimport type { AvatarSize, AvatarStatus } from '@frame-kit/ui-ng/ui/avatar';\nimport { DropdownMenuComponent } from '@frame-kit/ui-ng/ui/dropdown-menu';\nimport { DropdownPanelDirective } from '@frame-kit/ui-ng/ui/dropdown-menu';\nimport { DropdownTriggerDirective } from '@frame-kit/ui-ng/ui/dropdown-menu';\nimport { MenuItemComponent } from '@frame-kit/ui-ng/ui/menu-item';\nimport { MenuSeparatorComponent } from '@frame-kit/ui-ng/ui/menu-item';\nimport type {\n InfoPlacement,\n MenuItem,\n MenuPlacement,\n UserMenuVariant,\n} from './user-menu.types';\n\n@Component({\n selector: 'fk-user-menu',\n standalone: true,\n imports: [\n AvatarComponent,\n DropdownMenuComponent,\n DropdownTriggerDirective,\n DropdownPanelDirective,\n MenuItemComponent,\n MenuSeparatorComponent,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './user-menu.component.html',\n styleUrl: './user-menu.component.scss',\n})\nexport class UserMenuComponent {\n // ===== IDENTITY =====\n /** Full display name of the user shown in the avatar and optional info section. */\n readonly name = input.required<string>();\n /** User's email address shown in the optional info section. */\n readonly email = input<string | null>(null);\n /** URL of the user's avatar image. */\n readonly avatarUrl = input<string | null>(null);\n /** Explicit two-character initials that override the name-derived fallback. */\n readonly initials = input<string | null>(null);\n /** Optional user ID displayed in the info section for debugging or display. */\n readonly userId = input<string | null>(null);\n\n // ===== STATUS =====\n /** Online/offline/away status reflected on the avatar indicator dot. */\n readonly status = input<AvatarStatus | null>(null);\n /** When true, renders the status indicator dot on the avatar. */\n readonly showStatus = input<boolean>(false);\n\n // ===== MENU =====\n /** Array of menu item configurations rendered in the dropdown. */\n readonly menuItems = input<MenuItem[]>([]);\n /** Preferred placement of the dropdown panel relative to the trigger. */\n readonly placement = input<MenuPlacement>('bottom-end');\n\n // ===== DISPLAY =====\n /** Size of the avatar trigger. */\n readonly size = input<AvatarSize>('md');\n /** Layout variant — \"dropdown\" renders a full avatar menu, \"compact\" renders a minimal trigger. */\n readonly variant = input<UserMenuVariant>('dropdown');\n /** When true, renders the user's display name next to the avatar. */\n readonly showName = input<boolean>(false);\n /** When true, renders the user's email next to the avatar. */\n readonly showEmail = input<boolean>(false);\n /** When true, renders a chevron indicator showing the menu is expandable. */\n readonly showChevron = input<boolean>(true);\n /** Side where the name/email info block appears relative to the avatar. */\n readonly infoPlacement = input<InfoPlacement>('end');\n /** Optional badge text overlaid on the avatar. */\n readonly badge = input<string | null>(null);\n /** When true, prevents the menu from opening. */\n readonly disabled = input<boolean>(false);\n /** When true, shows a loading state on the trigger. */\n readonly loading = input<boolean>(false);\n\n // ===== BASE PROPS =====\n readonly className = input<string>('');\n readonly id = input<string | null>(null);\n readonly ariaLabel = input<string | null>(null);\n\n // ===== OUTPUTS =====\n /** Fires when the user clicks the avatar trigger to open the menu. */\n readonly avatarClick = output<void>();\n /** Fires when the dropdown menu opens. */\n readonly menuOpen = output<void>();\n /** Fires when the dropdown menu closes. */\n readonly menuClose = output<void>();\n /** Fires when the user selects a menu item, emitting the selected `MenuItem`. */\n readonly menuItemClick = output<MenuItem>();\n /** Fires when the user selects the item with `value === \"logout\"`. */\n readonly logoutClick = output<void>();\n\n // ===== REFS =====\n readonly dropdownRef = viewChild(DropdownMenuComponent);\n\n // ===== COMPUTED =====\n\n readonly isOpen = computed(() => this.dropdownRef()?.isOpen() ?? false);\n\n readonly classes = computed(() => {\n return [\n 'fk-user-menu',\n `fk-user-menu--${this.size()}`,\n `fk-user-menu--${this.variant()}`,\n this.infoPlacement() === 'start' ? 'fk-user-menu--info-start' : '',\n this.isOpen() ? 'fk-user-menu--open' : '',\n this.disabled() ? 'fk-user-menu--disabled' : '',\n this.loading() ? 'fk-user-menu--loading' : '',\n this.className(),\n ]\n .filter(Boolean)\n .join(' ');\n });\n\n @HostBinding('class')\n get hostClass() {\n return this.classes();\n }\n\n @HostBinding('attr.id')\n get hostId(): string | null {\n return this.id();\n }\n\n // ===== ACTIONS =====\n\n /** Emits `menuItemClick` (and `logoutClick` when applicable) for the given menu item. */\n selectItem(item: MenuItem): void {\n if (item.disabled) {\n return;\n }\n\n this.menuItemClick.emit(item);\n\n if (item.value === 'logout') {\n this.logoutClick.emit();\n }\n }\n\n onMenuOpen(): void {\n this.avatarClick.emit();\n this.menuOpen.emit();\n }\n\n onMenuClose(): void {\n this.menuClose.emit();\n }\n\n /** Opens the user-menu dropdown programmatically. */\n open(): void {\n this.dropdownRef()?.open();\n }\n\n /** Closes the user-menu dropdown programmatically. */\n close(): void {\n this.dropdownRef()?.close();\n }\n\n /** Toggles the user-menu dropdown programmatically. */\n toggle(): void {\n this.dropdownRef()?.toggle();\n }\n}\n","<fk-dropdown-menu\n [placement]=\"placement()\"\n [disabled]=\"disabled() || loading()\"\n [ariaLabel]=\"'Menu for ' + name()\"\n (menuOpen)=\"onMenuOpen()\"\n (menuClose)=\"onMenuClose()\"\n>\n <!-- Trigger button -->\n <button\n fkDropdownTrigger\n class=\"fk-user-menu__trigger\"\n type=\"button\"\n [disabled]=\"disabled() || loading()\"\n [attr.aria-label]=\"ariaLabel() ?? 'User menu for ' + name()\"\n >\n <!-- Avatar -->\n <fk-avatar\n [name]=\"name()\"\n [avatarUrl]=\"avatarUrl()\"\n [initials]=\"initials()\"\n [size]=\"size()\"\n [status]=\"status()\"\n [showStatus]=\"showStatus()\"\n />\n\n <!-- Name & email block -->\n @if (showName() || showEmail()) {\n <span class=\"fk-user-menu__info\">\n @if (showName()) {\n <span class=\"fk-user-menu__name\">{{ name() }}</span>\n }\n @if (showEmail() && email()) {\n <span class=\"fk-user-menu__email\">{{ email() }}</span>\n }\n </span>\n }\n\n <!-- Badge -->\n @if (badge()) {\n <span class=\"fk-user-menu__badge\">{{ badge() }}</span>\n }\n\n <!-- Chevron -->\n @if (showChevron()) {\n <span\n class=\"fk-user-menu__chevron\"\n [class.fk-user-menu__chevron--open]=\"isOpen()\"\n aria-hidden=\"true\"\n >\n <svg\n class=\"fk-user-menu__chevron-svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 18 18\"\n >\n <path\n d=\"M4.5 6.75L9 11.25L13.5 6.75\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n fill=\"none\"\n />\n </svg>\n </span>\n }\n </button>\n\n <!-- Panel content -->\n <ng-template fkDropdownPanel>\n <!-- User header inside panel (popover variant) -->\n @if (variant() === 'popover') {\n <div class=\"fk-user-menu__panel-header\">\n <span class=\"fk-user-menu__panel-name\">{{ name() }}</span>\n @if (email()) {\n <span class=\"fk-user-menu__panel-email\">{{ email() }}</span>\n }\n </div>\n }\n\n <!-- Menu items -->\n @for (item of menuItems(); track item.value) {\n @if (item.separator) {\n <fk-menu-separator />\n } @else {\n <fk-menu-item\n [icon]=\"item.icon ?? null\"\n [danger]=\"item.danger ?? false\"\n [disabled]=\"item.disabled ?? false\"\n (itemClick)=\"selectItem(item)\"\n >\n {{ item.label }}\n </fk-menu-item>\n }\n }\n </ng-template>\n</fk-dropdown-menu>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"frame-kit-ui-ng-ui-user-menu.mjs","sources":["../../../../packages/ui-ng/ui/user-menu/user-menu.component.ts","../../../../packages/ui-ng/ui/user-menu/user-menu.component.html","../../../../packages/ui-ng/ui/user-menu/frame-kit-ui-ng-ui-user-menu.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n output,\n TemplateRef,\n viewChild,\n} from '@angular/core';\n\nimport { AvatarComponent } from '@frame-kit/ui-ng/ui/avatar';\nimport type { AvatarSize, AvatarStatus } from '@frame-kit/ui-ng/ui/avatar';\nimport { DropdownMenuComponent } from '@frame-kit/ui-ng/ui/dropdown-menu';\nimport { DropdownPanelDirective } from '@frame-kit/ui-ng/ui/dropdown-menu';\nimport { DropdownTriggerDirective } from '@frame-kit/ui-ng/ui/dropdown-menu';\nimport { FkMenuItemIconDirective } from '@frame-kit/ui-ng/ui/menu-item';\nimport { MenuItemComponent } from '@frame-kit/ui-ng/ui/menu-item';\nimport { MenuSeparatorComponent } from '@frame-kit/ui-ng/ui/menu-item';\nimport type {\n InfoPlacement,\n MenuItem,\n MenuPlacement,\n UserMenuVariant,\n} from './user-menu.types';\n\n@Component({\n selector: 'fk-user-menu',\n standalone: true,\n imports: [\n NgTemplateOutlet,\n AvatarComponent,\n DropdownMenuComponent,\n DropdownTriggerDirective,\n DropdownPanelDirective,\n MenuItemComponent,\n MenuSeparatorComponent,\n FkMenuItemIconDirective,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './user-menu.component.html',\n styleUrl: './user-menu.component.scss',\n})\nexport class UserMenuComponent {\n // ===== IDENTITY =====\n /** Full display name of the user shown in the avatar and optional info section. */\n readonly name = input.required<string>();\n /** User's email address shown in the optional info section. */\n readonly email = input<string | null>(null);\n /** URL of the user's avatar image. */\n readonly avatarUrl = input<string | null>(null);\n /** Explicit two-character initials that override the name-derived fallback. */\n readonly initials = input<string | null>(null);\n /** Optional user ID displayed in the info section for debugging or display. */\n readonly userId = input<string | null>(null);\n\n // ===== STATUS =====\n /** Online/offline/away status reflected on the avatar indicator dot. */\n readonly status = input<AvatarStatus | null>(null);\n /** When true, renders the status indicator dot on the avatar. */\n readonly showStatus = input<boolean>(false);\n\n // ===== MENU =====\n /** Array of menu item configurations rendered in the dropdown. */\n readonly menuItems = input<MenuItem[]>([]);\n /**\n * Optional template used to render each item's leading icon (the app owns the\n * icon system). Receives the `MenuItem` as `$implicit`; render the icon from\n * `item.icon`. When omitted, items render without an icon.\n */\n readonly iconTemplate = input<TemplateRef<{ $implicit: MenuItem }> | null>(\n null,\n );\n /** Preferred placement of the dropdown panel relative to the trigger. */\n readonly placement = input<MenuPlacement>('bottom-end');\n\n // ===== DISPLAY =====\n /** Size of the avatar trigger. */\n readonly size = input<AvatarSize>('md');\n /** Layout variant — \"dropdown\" renders a full avatar menu, \"compact\" renders a minimal trigger. */\n readonly variant = input<UserMenuVariant>('dropdown');\n /** When true, renders the user's display name next to the avatar. */\n readonly showName = input<boolean>(false);\n /** When true, renders the user's email next to the avatar. */\n readonly showEmail = input<boolean>(false);\n /** When true, renders a chevron indicator showing the menu is expandable. */\n readonly showChevron = input<boolean>(true);\n /** Side where the name/email info block appears relative to the avatar. */\n readonly infoPlacement = input<InfoPlacement>('end');\n /** Optional badge text overlaid on the avatar. */\n readonly badge = input<string | null>(null);\n /** When true, prevents the menu from opening. */\n readonly disabled = input<boolean>(false);\n /** When true, shows a loading state on the trigger. */\n readonly loading = input<boolean>(false);\n\n // ===== BASE PROPS =====\n readonly className = input<string>('');\n readonly id = input<string | null>(null);\n readonly ariaLabel = input<string | null>(null);\n\n // ===== OUTPUTS =====\n /** Fires when the user clicks the avatar trigger to open the menu. */\n readonly avatarClick = output<void>();\n /** Fires when the dropdown menu opens. */\n readonly menuOpen = output<void>();\n /** Fires when the dropdown menu closes. */\n readonly menuClose = output<void>();\n /** Fires when the user selects a menu item, emitting the selected `MenuItem`. */\n readonly menuItemClick = output<MenuItem>();\n /** Fires when the user selects the item with `value === \"logout\"`. */\n readonly logoutClick = output<void>();\n\n // ===== REFS =====\n readonly dropdownRef = viewChild(DropdownMenuComponent);\n\n // ===== COMPUTED =====\n\n readonly isOpen = computed(() => this.dropdownRef()?.isOpen() ?? false);\n\n readonly classes = computed(() => {\n return [\n 'fk-user-menu',\n `fk-user-menu--${this.size()}`,\n `fk-user-menu--${this.variant()}`,\n this.infoPlacement() === 'start' ? 'fk-user-menu--info-start' : '',\n this.isOpen() ? 'fk-user-menu--open' : '',\n this.disabled() ? 'fk-user-menu--disabled' : '',\n this.loading() ? 'fk-user-menu--loading' : '',\n this.className(),\n ]\n .filter(Boolean)\n .join(' ');\n });\n\n @HostBinding('class')\n get hostClass() {\n return this.classes();\n }\n\n @HostBinding('attr.id')\n get hostId(): string | null {\n return this.id();\n }\n\n // ===== ACTIONS =====\n\n /** Emits `menuItemClick` (and `logoutClick` when applicable) for the given menu item. */\n selectItem(item: MenuItem): void {\n if (item.disabled) {\n return;\n }\n\n this.menuItemClick.emit(item);\n\n if (item.value === 'logout') {\n this.logoutClick.emit();\n }\n }\n\n onMenuOpen(): void {\n this.avatarClick.emit();\n this.menuOpen.emit();\n }\n\n onMenuClose(): void {\n this.menuClose.emit();\n }\n\n /** Opens the user-menu dropdown programmatically. */\n open(): void {\n this.dropdownRef()?.open();\n }\n\n /** Closes the user-menu dropdown programmatically. */\n close(): void {\n this.dropdownRef()?.close();\n }\n\n /** Toggles the user-menu dropdown programmatically. */\n toggle(): void {\n this.dropdownRef()?.toggle();\n }\n}\n","<fk-dropdown-menu\n [placement]=\"placement()\"\n [disabled]=\"disabled() || loading()\"\n [ariaLabel]=\"'Menu for ' + name()\"\n (menuOpen)=\"onMenuOpen()\"\n (menuClose)=\"onMenuClose()\"\n>\n <!-- Trigger button -->\n <button\n fkDropdownTrigger\n class=\"fk-user-menu__trigger\"\n type=\"button\"\n [disabled]=\"disabled() || loading()\"\n [attr.aria-label]=\"ariaLabel() ?? 'User menu for ' + name()\"\n >\n <!-- Avatar -->\n <fk-avatar\n [name]=\"name()\"\n [avatarUrl]=\"avatarUrl()\"\n [initials]=\"initials()\"\n [size]=\"size()\"\n [status]=\"status()\"\n [showStatus]=\"showStatus()\"\n />\n\n <!-- Name & email block -->\n @if (showName() || showEmail()) {\n <span class=\"fk-user-menu__info\">\n @if (showName()) {\n <span class=\"fk-user-menu__name\">{{ name() }}</span>\n }\n @if (showEmail() && email()) {\n <span class=\"fk-user-menu__email\">{{ email() }}</span>\n }\n </span>\n }\n\n <!-- Badge -->\n @if (badge()) {\n <span class=\"fk-user-menu__badge\">{{ badge() }}</span>\n }\n\n <!-- Chevron -->\n @if (showChevron()) {\n <span\n class=\"fk-user-menu__chevron\"\n [class.fk-user-menu__chevron--open]=\"isOpen()\"\n aria-hidden=\"true\"\n >\n <svg\n class=\"fk-user-menu__chevron-svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 18 18\"\n >\n <path\n d=\"M4.5 6.75L9 11.25L13.5 6.75\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n fill=\"none\"\n />\n </svg>\n </span>\n }\n </button>\n\n <!-- Panel content -->\n <ng-template fkDropdownPanel>\n <!-- User header inside panel (popover variant) -->\n @if (variant() === 'popover') {\n <div class=\"fk-user-menu__panel-header\">\n <span class=\"fk-user-menu__panel-name\">{{ name() }}</span>\n @if (email()) {\n <span class=\"fk-user-menu__panel-email\">{{ email() }}</span>\n }\n </div>\n }\n\n <!-- Menu items -->\n @for (item of menuItems(); track item.value) {\n @if (item.separator) {\n <fk-menu-separator />\n } @else {\n <fk-menu-item\n [danger]=\"item.danger ?? false\"\n [disabled]=\"item.disabled ?? false\"\n (itemClick)=\"selectItem(item)\"\n >\n @if (item.icon && iconTemplate(); as tpl) {\n <span fkMenuItemIcon>\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n />\n </span>\n }\n {{ item.label }}\n </fk-menu-item>\n }\n }\n </ng-template>\n</fk-dropdown-menu>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _angular_core from '@angular/core';
|
|
2
|
-
import { InjectionToken, Type, OnInit, ElementRef
|
|
2
|
+
import { InjectionToken, TemplateRef, Type, OnInit, ElementRef } from '@angular/core';
|
|
3
3
|
import { NgControl, AsyncValidatorFn, ValidatorFn, AbstractControl, FormArray, FormGroup, FormControl, ControlValueAccessor } from '@angular/forms';
|
|
4
4
|
import { IconSize, IconColor } from '@frame-kit/ui-ng/core/icon';
|
|
5
5
|
|
|
@@ -425,6 +425,10 @@ declare class FieldArrayOutletComponent {
|
|
|
425
425
|
readonly field: _angular_core.InputSignal<FieldSchema>;
|
|
426
426
|
/** The FormArray backing the repeatable rows. */
|
|
427
427
|
readonly formArray: _angular_core.InputSignal<FormArray<any>>;
|
|
428
|
+
/** Prefix-icon template threaded to each child field (the app owns the icon). */
|
|
429
|
+
readonly prefixIconTemplate: _angular_core.InputSignal<TemplateRef<{
|
|
430
|
+
$implicit: FieldSchema;
|
|
431
|
+
}> | undefined>;
|
|
428
432
|
/** Whether the parent form has been submitted; propagated to each fk-field-outlet. */
|
|
429
433
|
readonly submitted: _angular_core.InputSignal<boolean>;
|
|
430
434
|
/** Fires with the index of the newly added row. */
|
|
@@ -445,7 +449,7 @@ declare class FieldArrayOutletComponent {
|
|
|
445
449
|
/** Removes the row at the given index from the FormArray. */
|
|
446
450
|
removeRow(index: number): void;
|
|
447
451
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FieldArrayOutletComponent, never>;
|
|
448
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FieldArrayOutletComponent, "fk-field-array-outlet", never, { "className": { "alias": "className"; "required": false; "isSignal": true; }; "field": { "alias": "field"; "required": true; "isSignal": true; }; "formArray": { "alias": "formArray"; "required": true; "isSignal": true; }; "submitted": { "alias": "submitted"; "required": false; "isSignal": true; }; }, { "rowAdded": "rowAdded"; "rowRemoved": "rowRemoved"; }, never, never, true, never>;
|
|
452
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FieldArrayOutletComponent, "fk-field-array-outlet", never, { "className": { "alias": "className"; "required": false; "isSignal": true; }; "field": { "alias": "field"; "required": true; "isSignal": true; }; "formArray": { "alias": "formArray"; "required": true; "isSignal": true; }; "prefixIconTemplate": { "alias": "prefixIconTemplate"; "required": false; "isSignal": true; }; "submitted": { "alias": "submitted"; "required": false; "isSignal": true; }; }, { "rowAdded": "rowAdded"; "rowRemoved": "rowRemoved"; }, never, never, true, never>;
|
|
449
453
|
}
|
|
450
454
|
|
|
451
455
|
/**
|
|
@@ -472,6 +476,12 @@ declare class FieldOutletComponent {
|
|
|
472
476
|
readonly form: _angular_core.InputSignal<FormGroup<any>>;
|
|
473
477
|
/** Whether the parent form has been submitted; propagated to fk-form-field. */
|
|
474
478
|
readonly submitted: _angular_core.InputSignal<boolean>;
|
|
479
|
+
/** Optional template rendering a field's prefix icon (the app owns the icon
|
|
480
|
+
* system). Receives the field as `$implicit`; render it from
|
|
481
|
+
* `field.ui.prefixIcon`. */
|
|
482
|
+
readonly prefixIconTemplate: _angular_core.InputSignal<TemplateRef<{
|
|
483
|
+
$implicit: FieldSchema;
|
|
484
|
+
}> | undefined>;
|
|
475
485
|
/** Whether this field is visible (for conditional visibility). */
|
|
476
486
|
readonly visible: _angular_core.WritableSignal<boolean>;
|
|
477
487
|
readonly classes: _angular_core.Signal<string>;
|
|
@@ -493,7 +503,7 @@ declare class FieldOutletComponent {
|
|
|
493
503
|
private setupVisibility;
|
|
494
504
|
private evaluateVisibility;
|
|
495
505
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FieldOutletComponent, never>;
|
|
496
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FieldOutletComponent, "fk-field-outlet", never, { "className": { "alias": "className"; "required": false; "isSignal": true; }; "field": { "alias": "field"; "required": true; "isSignal": true; }; "form": { "alias": "form"; "required": true; "isSignal": true; }; "submitted": { "alias": "submitted"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
506
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FieldOutletComponent, "fk-field-outlet", never, { "className": { "alias": "className"; "required": false; "isSignal": true; }; "field": { "alias": "field"; "required": true; "isSignal": true; }; "form": { "alias": "form"; "required": true; "isSignal": true; }; "submitted": { "alias": "submitted"; "required": false; "isSignal": true; }; "prefixIconTemplate": { "alias": "prefixIconTemplate"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
497
507
|
}
|
|
498
508
|
|
|
499
509
|
/**
|
|
@@ -529,6 +539,14 @@ declare class FormRendererComponent implements OnInit {
|
|
|
529
539
|
* If not provided, one is auto-generated from the schema.
|
|
530
540
|
*/
|
|
531
541
|
readonly form: _angular_core.InputSignal<FormGroup<any> | null>;
|
|
542
|
+
/**
|
|
543
|
+
* Optional template rendering a field's prefix icon (the app owns the icon
|
|
544
|
+
* system). Receives the field as `$implicit`; render it from
|
|
545
|
+
* `field.ui.prefixIcon`. Fields without a `prefixIcon` render no icon.
|
|
546
|
+
*/
|
|
547
|
+
readonly prefixIconTemplate: _angular_core.InputSignal<TemplateRef<{
|
|
548
|
+
$implicit: FieldSchema;
|
|
549
|
+
}> | undefined>;
|
|
532
550
|
/** Emits the FormGroup value when the form is submitted. */
|
|
533
551
|
readonly formSubmit: _angular_core.OutputEmitterRef<Record<string, unknown>>;
|
|
534
552
|
/** The resolved FormGroup (either provided or auto-generated). */
|
|
@@ -551,7 +569,7 @@ declare class FormRendererComponent implements OnInit {
|
|
|
551
569
|
*/
|
|
552
570
|
focusFirstInvalidField(): void;
|
|
553
571
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FormRendererComponent, never>;
|
|
554
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FormRendererComponent, "fk-form-renderer", never, { "className": { "alias": "className"; "required": false; "isSignal": true; }; "schema": { "alias": "schema"; "required": true; "isSignal": true; }; "form": { "alias": "form"; "required": false; "isSignal": true; }; }, { "formSubmit": "formSubmit"; }, never, ["*"], true, never>;
|
|
572
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FormRendererComponent, "fk-form-renderer", never, { "className": { "alias": "className"; "required": false; "isSignal": true; }; "schema": { "alias": "schema"; "required": true; "isSignal": true; }; "form": { "alias": "form"; "required": false; "isSignal": true; }; "prefixIconTemplate": { "alias": "prefixIconTemplate"; "required": false; "isSignal": true; }; }, { "formSubmit": "formSubmit"; }, never, ["*"], true, never>;
|
|
555
573
|
}
|
|
556
574
|
|
|
557
575
|
/**
|
|
@@ -593,12 +611,16 @@ declare class SectionOutletComponent {
|
|
|
593
611
|
readonly form: _angular_core.InputSignal<FormGroup<any>>;
|
|
594
612
|
/** Whether the parent form has been submitted; propagated to each fk-field-outlet. */
|
|
595
613
|
readonly submitted: _angular_core.InputSignal<boolean>;
|
|
614
|
+
/** Prefix-icon template threaded to each field (the app owns the icon). */
|
|
615
|
+
readonly prefixIconTemplate: _angular_core.InputSignal<TemplateRef<{
|
|
616
|
+
$implicit: FieldSchema;
|
|
617
|
+
}> | undefined>;
|
|
596
618
|
readonly classes: _angular_core.Signal<string>;
|
|
597
619
|
get hostClass(): string;
|
|
598
620
|
/** Looks up a field definition within this section by its key. */
|
|
599
621
|
getField(key: string): FormSchemaSection['fields'][number] | undefined;
|
|
600
622
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SectionOutletComponent, never>;
|
|
601
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SectionOutletComponent, "fk-section-outlet", never, { "className": { "alias": "className"; "required": false; "isSignal": true; }; "section": { "alias": "section"; "required": true; "isSignal": true; }; "form": { "alias": "form"; "required": true; "isSignal": true; }; "submitted": { "alias": "submitted"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
623
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SectionOutletComponent, "fk-section-outlet", never, { "className": { "alias": "className"; "required": false; "isSignal": true; }; "section": { "alias": "section"; "required": true; "isSignal": true; }; "form": { "alias": "form"; "required": true; "isSignal": true; }; "submitted": { "alias": "submitted"; "required": false; "isSignal": true; }; "prefixIconTemplate": { "alias": "prefixIconTemplate"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
602
624
|
}
|
|
603
625
|
|
|
604
626
|
declare class FormSectionComponent {
|
|
@@ -1128,8 +1150,6 @@ declare class FileDropzoneComponent {
|
|
|
1128
1150
|
readonly multiple: _angular_core.InputSignal<boolean>;
|
|
1129
1151
|
/** When true, prevents drag-and-drop and click-to-browse interaction. */
|
|
1130
1152
|
readonly disabled: _angular_core.InputSignal<boolean>;
|
|
1131
|
-
/** Icon name rendered inside the dropzone surface. */
|
|
1132
|
-
readonly icon: _angular_core.InputSignal<string>;
|
|
1133
1153
|
/** Primary prompt text displayed inside the dropzone. */
|
|
1134
1154
|
readonly prompt: _angular_core.InputSignal<string>;
|
|
1135
1155
|
/** Secondary hint text shown below the prompt. */
|
|
@@ -1148,7 +1168,25 @@ declare class FileDropzoneComponent {
|
|
|
1148
1168
|
onChange(event: Event): void;
|
|
1149
1169
|
private emit;
|
|
1150
1170
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FileDropzoneComponent, never>;
|
|
1151
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FileDropzoneComponent, "fk-file-dropzone", never, { "accept": { "alias": "accept"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "
|
|
1171
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FileDropzoneComponent, "fk-file-dropzone", never, { "accept": { "alias": "accept"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "prompt": { "alias": "prompt"; "required": true; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "filesSelected": "filesSelected"; }, never, ["[fkFileDropzoneIcon]"], true, never>;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
/** Injection token for the icon slot of `fk-file-dropzone`. */
|
|
1175
|
+
declare const FK_FILE_DROPZONE_ICON: InjectionToken<FkFileDropzoneIconDirective>;
|
|
1176
|
+
/**
|
|
1177
|
+
* Marks projected content as the icon of an `fk-file-dropzone`, overriding the
|
|
1178
|
+
* built-in upload glyph. Project any icon element (the app owns the icon
|
|
1179
|
+
* system):
|
|
1180
|
+
*
|
|
1181
|
+
* ```html
|
|
1182
|
+
* <fk-file-dropzone prompt="Drop a file">
|
|
1183
|
+
* <fk-icon fkFileDropzoneIcon name="file-content" size="lg" />
|
|
1184
|
+
* </fk-file-dropzone>
|
|
1185
|
+
* ```
|
|
1186
|
+
*/
|
|
1187
|
+
declare class FkFileDropzoneIconDirective {
|
|
1188
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FkFileDropzoneIconDirective, never>;
|
|
1189
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<FkFileDropzoneIconDirective, "[fkFileDropzoneIcon]", never, {}, {}, never, never, true, never>;
|
|
1152
1190
|
}
|
|
1153
1191
|
|
|
1154
1192
|
declare class FileUploadComponent implements ControlValueAccessor, FieldControl {
|
|
@@ -1670,5 +1708,5 @@ declare class TimeInputComponent implements ControlValueAccessor, FieldControl {
|
|
|
1670
1708
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<TimeInputComponent, "fk-time-input", never, { "className": { "alias": "className"; "required": false; "isSignal": true; }; "isRequired": { "alias": "required"; "required": false; "isSignal": true; }; "isReadonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "step": { "alias": "step"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
1671
1709
|
}
|
|
1672
1710
|
|
|
1673
|
-
export { AutocompleteComponent, CheckboxComponent, DEFAULT_ERROR_MESSAGES, DateInputComponent, DatetimeInputComponent, ERROR_MESSAGES, ErrorComponent, FIELD_CONTROL, FK_AUTOCOMPLETE_OPTION_TPL, FK_PREFIX, FK_SUFFIX, FORM, FieldArrayOutletComponent, FieldGroupComponent, FieldOutletComponent, FieldRegistry, FileDropzoneComponent, FileUploadComponent, FkAutocompleteOptionTplDirective, FkPrefixDirective, FkSuffixDirective, FormComponent, FormFieldComponent, FormRendererComponent, FormSectionComponent, HintComponent, InputComponent, LabelComponent, NumberInputComponent, PasswordInputComponent, RadioComponent, SchemaParser, SectionOutletComponent, SegmentedBarComponent, SelectComponent, SliderComponent, SwitchComponent, TagInputComponent, TextareaComponent, TimeInputComponent, ValidationRegistry, getError, getFieldState, getInvalidFields, hasError, interpolateMessage, isFormValid, markAllTouched, resolveErrorMessage };
|
|
1711
|
+
export { AutocompleteComponent, CheckboxComponent, DEFAULT_ERROR_MESSAGES, DateInputComponent, DatetimeInputComponent, ERROR_MESSAGES, ErrorComponent, FIELD_CONTROL, FK_AUTOCOMPLETE_OPTION_TPL, FK_FILE_DROPZONE_ICON, FK_PREFIX, FK_SUFFIX, FORM, FieldArrayOutletComponent, FieldGroupComponent, FieldOutletComponent, FieldRegistry, FileDropzoneComponent, FileUploadComponent, FkAutocompleteOptionTplDirective, FkFileDropzoneIconDirective, FkPrefixDirective, FkSuffixDirective, FormComponent, FormFieldComponent, FormRendererComponent, FormSectionComponent, HintComponent, InputComponent, LabelComponent, NumberInputComponent, PasswordInputComponent, RadioComponent, SchemaParser, SectionOutletComponent, SegmentedBarComponent, SelectComponent, SliderComponent, SwitchComponent, TagInputComponent, TextareaComponent, TimeInputComponent, ValidationRegistry, getError, getFieldState, getInvalidFields, hasError, interpolateMessage, isFormValid, markAllTouched, resolveErrorMessage };
|
|
1674
1712
|
export type { AsyncValidatorConfig, AsyncValidatorFactory, AutocompleteFilterMode, AutocompleteOption, ErrorMessages, FieldControl, FieldGroupLayout, FieldSchema, FieldState, FieldUiConfig, FkFileDropzoneSelection, FormRendererSubmitValue, FormSchema, FormSchemaSection, FormStatus, InputType, LabelEndLink, LayoutColumn, LayoutRow, Option, PasswordAutoComplete, ProgressSegment, RadioOption, SegmentedBarSize, SelectOption, ShowErrorsOn, ValidatorConfig, ValidatorFactory, VisibilityRule };
|