@frame-kit/ui-ng 0.1.6 → 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
package/DEVELOPMENT_GUIDE.md
CHANGED
|
@@ -36,6 +36,7 @@ FrameKit UI-ng is a style-agnostic, token-driven Angular component library. Comp
|
|
|
36
36
|
2. **Components only consume tokens.** Token definitions belong in theme files, never in component SCSS.
|
|
37
37
|
3. **Components are self-sufficient.** Every component renders correctly with zero external dependencies — no theme file required.
|
|
38
38
|
4. **Stable public API.** Consumers use `<fk-*>` components with stable inputs. Internal implementations can change without breaking consumers.
|
|
39
|
+
5. **Icons are not a dependency.** No component or directive **outside the icon family** (`core/icon`, `ui/icon-badge`, `ui/icon-list`) may import `IconComponent` or render `<fk-icon>`. This keeps ui-ng usable without the icon registry. Take consumer-supplied icons three ways (see [Icons](#icons)); a CI guardrail (`icon-dependency.guardrail.spec.ts`) enforces this.
|
|
39
40
|
|
|
40
41
|
### Library structure
|
|
41
42
|
|
|
@@ -637,6 +638,20 @@ readonly iconStartRef = contentChild(FK_ALERT_ICON_START);
|
|
|
637
638
|
|
|
638
639
|
---
|
|
639
640
|
|
|
641
|
+
## Icons
|
|
642
|
+
|
|
643
|
+
**ui-ng is icon-agnostic.** Only the icon family — `core/icon`, `ui/icon-badge`, `ui/icon-list` — may import `IconComponent` or render `<fk-icon>`. Every other component takes icons from the consumer so the library works without the icon registry and without pinning a specific icon set. A CI guardrail (`packages/ui-ng/icon-dependency.guardrail.spec.ts`) fails the build on any violation.
|
|
644
|
+
|
|
645
|
+
Pick the mechanism by how the icon is supplied:
|
|
646
|
+
|
|
647
|
+
1. **Structural glyph** (an arrow, caret, grip, spinner that is part of the component's own chrome) → **inline SVG** with `currentColor` and tokenized dimensions. No input, no dependency. Example: `fk-pagination` prev/next arrows.
|
|
648
|
+
2. **A single consumer-supplied icon** → a **projection slot** via a marker directive (see [Content-slot directives](#content-slot-directives)). The consumer projects their own `<fk-icon>` (or anything). Provide an inline-SVG default inside the `<ng-content>` when there's a sensible fallback. Examples: `fk-menu-item` (`[fkMenuItemIcon]`), `fk-file-dropzone` (`[fkFileDropzoneIcon]`).
|
|
649
|
+
3. **A data-driven icon** (a list/tree/timeline where each item carries an icon name) → an **icon `TemplateRef` input** rendered per item with the item as `$implicit`. The consumer's template renders the icon; the library renders the template. Keep the data field (e.g. `node.icon`) but don't render it directly. Examples: `fk-node-tree` / `fk-timeline` (`iconTemplate`), `fk-form-renderer` (`prefixIconTemplate`).
|
|
650
|
+
|
|
651
|
+
Never add an `icon` **string input** that the component feeds to `<fk-icon>` — that couples ui-ng to the icon component and a specific icon set. Use mechanism 2 or 3 instead.
|
|
652
|
+
|
|
653
|
+
---
|
|
654
|
+
|
|
640
655
|
## Services
|
|
641
656
|
|
|
642
657
|
Runtime services with no UI that **depend on Angular** (e.g. `OverlayOrchestrator`, `ToastService`, `SpotlightService`). Each lives in its own folder under `packages/ui-ng/services/<name>/` and ships a README alongside the source. Framework-agnostic helpers (color, date math) do **not** belong here — they go in `@frame-kit/utils`.
|
|
@@ -2,11 +2,10 @@ import * as i0 from '@angular/core';
|
|
|
2
2
|
import { input, computed, HostBinding, ChangeDetectionStrategy, Component, InjectionToken, signal, output, Directive, contentChild, inject, ChangeDetectorRef, effect, Injectable, TemplateRef, viewChild, forwardRef, DestroyRef, ViewContainerRef, ElementRef } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/forms';
|
|
4
4
|
import { Validators, FormControl, FormGroup, FormArray, NgControl, ReactiveFormsModule } from '@angular/forms';
|
|
5
|
+
import { NgTemplateOutlet } from '@angular/common';
|
|
5
6
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
6
7
|
import { map, distinctUntilChanged } from 'rxjs';
|
|
7
|
-
import { IconComponent } from '@frame-kit/ui-ng/core/icon';
|
|
8
8
|
import { LinkComponent } from '@frame-kit/ui-ng/core/link';
|
|
9
|
-
import { NgTemplateOutlet } from '@angular/common';
|
|
10
9
|
import { TextComponent } from '@frame-kit/ui-ng/core/text';
|
|
11
10
|
|
|
12
11
|
let nextErrorId = 0;
|
|
@@ -2887,6 +2886,10 @@ class FieldOutletComponent {
|
|
|
2887
2886
|
form = input.required(...(ngDevMode ? [{ debugName: "form" }] : /* istanbul ignore next */ []));
|
|
2888
2887
|
/** Whether the parent form has been submitted; propagated to fk-form-field. */
|
|
2889
2888
|
submitted = input(false, ...(ngDevMode ? [{ debugName: "submitted" }] : /* istanbul ignore next */ []));
|
|
2889
|
+
/** Optional template rendering a field's prefix icon (the app owns the icon
|
|
2890
|
+
* system). Receives the field as `$implicit`; render it from
|
|
2891
|
+
* `field.ui.prefixIcon`. */
|
|
2892
|
+
prefixIconTemplate = input(undefined, ...(ngDevMode ? [{ debugName: "prefixIconTemplate" }] : /* istanbul ignore next */ []));
|
|
2890
2893
|
/** Whether this field is visible (for conditional visibility). */
|
|
2891
2894
|
visible = signal(true, ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
2892
2895
|
classes = computed(() => ['fk-field-outlet', this.className()].filter(Boolean).join(' '), ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
@@ -3022,19 +3025,19 @@ class FieldOutletComponent {
|
|
|
3022
3025
|
}
|
|
3023
3026
|
}
|
|
3024
3027
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FieldOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3025
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: FieldOutletComponent, isStandalone: true, selector: "fk-field-outlet", inputs: { className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, submitted: { classPropertyName: "submitted", publicName: "submitted", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClass", "style.display": "this.hostDisplay" } }, viewQueries: [{ propertyName: "controlHostRef", first: true, predicate: ["controlHost"], descendants: true, read: ViewContainerRef, isSignal: true }], ngImport: i0, template: "@if (field().ui?.labelEndLink) {\n <div class=\"fk-field-outlet__label-row\">\n <span class=\"fk-field-outlet__label-text\">\n {{ field().label }}\n @if (field().required) {\n <span class=\"fk-field-outlet__required\" aria-hidden=\"true\">*</span>\n }\n </span>\n <fk-link\n variant=\"primary\"\n size=\"small\"\n [routerLink]=\"field().ui!.labelEndLink!.route\"\n >\n {{ field().ui!.labelEndLink!.text }}\n </fk-link>\n </div>\n}\n\n<fk-form-field\n [label]=\"\n field().ui?.labelEndLink\n ? null\n : field().type === 'checkbox'\n ? null\n : (field().label ?? null)\n \"\n [showErrorsOn]=\"'touched'\"\n [submitted]=\"submitted()\"\n [errorMessages]=\"field().errorMessages ?? null\"\n [fallbackControl]=\"form().get(field().key)\"\n [style.display]=\"visible() ? '' : 'none'\"\n>\n @if (field().ui?.prefixIcon) {\n <
|
|
3028
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: FieldOutletComponent, isStandalone: true, selector: "fk-field-outlet", inputs: { className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, submitted: { classPropertyName: "submitted", publicName: "submitted", isSignal: true, isRequired: false, transformFunction: null }, prefixIconTemplate: { classPropertyName: "prefixIconTemplate", publicName: "prefixIconTemplate", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClass", "style.display": "this.hostDisplay" } }, viewQueries: [{ propertyName: "controlHostRef", first: true, predicate: ["controlHost"], descendants: true, read: ViewContainerRef, isSignal: true }], ngImport: i0, template: "@if (field().ui?.labelEndLink) {\n <div class=\"fk-field-outlet__label-row\">\n <span class=\"fk-field-outlet__label-text\">\n {{ field().label }}\n @if (field().required) {\n <span class=\"fk-field-outlet__required\" aria-hidden=\"true\">*</span>\n }\n </span>\n <fk-link\n variant=\"primary\"\n size=\"small\"\n [routerLink]=\"field().ui!.labelEndLink!.route\"\n >\n {{ field().ui!.labelEndLink!.text }}\n </fk-link>\n </div>\n}\n\n<fk-form-field\n [label]=\"\n field().ui?.labelEndLink\n ? null\n : field().type === 'checkbox'\n ? null\n : (field().label ?? null)\n \"\n [showErrorsOn]=\"'touched'\"\n [submitted]=\"submitted()\"\n [errorMessages]=\"field().errorMessages ?? null\"\n [fallbackControl]=\"form().get(field().key)\"\n [style.display]=\"visible() ? '' : 'none'\"\n>\n @if (field().ui?.prefixIcon && prefixIconTemplate(); as tpl) {\n <span fkPrefix>\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: field() }\"\n />\n </span>\n }\n <ng-container #controlHost />\n @if (field().ui?.hint) {\n <fk-hint>{{ field().ui?.hint }}</fk-hint>\n }\n</fk-form-field>\n", styles: [".fk-field-outlet__label-row{display:flex;align-items:baseline;justify-content:space-between;font-family:var(--fk-font-family-base);font-size:var(--fk-form-label-font-size);font-weight:var(--fk-form-label-font-weight);line-height:var(--fk-form-label-line-height);color:var(--fk-form-label-color)}.fk-field-outlet__label-text{display:flex;align-items:baseline;gap:.25em}.fk-field-outlet__required{color:var(--fk-form-error-color)}.fk-field-outlet__label-row fk-link{--fk-link-font-size-small: .75rem;--fk-link-font-size-medium: .75rem}.fk-field-outlet__label-row+fk-form-field{margin-top:0}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: FormFieldComponent, selector: "fk-form-field", inputs: ["className", "label", "showErrorsOn", "submitted", "externalDescribedBy", "fallbackControl", "errorMessages"] }, { kind: "directive", type: FkPrefixDirective, selector: "[fkPrefix]" }, { kind: "component", type: HintComponent, selector: "fk-hint", inputs: ["className", "id"] }, { kind: "component", type: LinkComponent, selector: "fk-link", inputs: ["href", "routerLink", "queryParams", "variant", "size", "underline", "target", "rel", "external", "disabled", "loading", "download", "className", "id", "ariaLabel", "ariaDescribedBy", "ariaCurrent", "role", "tabIndex", "trackingId", "trackingCategory", "trackingLabel", "dataAttributes"], outputs: ["clicked"] }, { kind: "ngmodule", type: ReactiveFormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3026
3029
|
}
|
|
3027
3030
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FieldOutletComponent, decorators: [{
|
|
3028
3031
|
type: Component,
|
|
3029
3032
|
args: [{ selector: 'fk-field-outlet', standalone: true, imports: [
|
|
3033
|
+
NgTemplateOutlet,
|
|
3030
3034
|
FormFieldComponent,
|
|
3031
3035
|
FkPrefixDirective,
|
|
3032
3036
|
HintComponent,
|
|
3033
|
-
IconComponent,
|
|
3034
3037
|
LinkComponent,
|
|
3035
3038
|
ReactiveFormsModule,
|
|
3036
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (field().ui?.labelEndLink) {\n <div class=\"fk-field-outlet__label-row\">\n <span class=\"fk-field-outlet__label-text\">\n {{ field().label }}\n @if (field().required) {\n <span class=\"fk-field-outlet__required\" aria-hidden=\"true\">*</span>\n }\n </span>\n <fk-link\n variant=\"primary\"\n size=\"small\"\n [routerLink]=\"field().ui!.labelEndLink!.route\"\n >\n {{ field().ui!.labelEndLink!.text }}\n </fk-link>\n </div>\n}\n\n<fk-form-field\n [label]=\"\n field().ui?.labelEndLink\n ? null\n : field().type === 'checkbox'\n ? null\n : (field().label ?? null)\n \"\n [showErrorsOn]=\"'touched'\"\n [submitted]=\"submitted()\"\n [errorMessages]=\"field().errorMessages ?? null\"\n [fallbackControl]=\"form().get(field().key)\"\n [style.display]=\"visible() ? '' : 'none'\"\n>\n @if (field().ui?.prefixIcon) {\n <
|
|
3037
|
-
}], ctorParameters: () => [], propDecorators: { className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], submitted: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitted", required: false }] }], hostClass: [{
|
|
3039
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (field().ui?.labelEndLink) {\n <div class=\"fk-field-outlet__label-row\">\n <span class=\"fk-field-outlet__label-text\">\n {{ field().label }}\n @if (field().required) {\n <span class=\"fk-field-outlet__required\" aria-hidden=\"true\">*</span>\n }\n </span>\n <fk-link\n variant=\"primary\"\n size=\"small\"\n [routerLink]=\"field().ui!.labelEndLink!.route\"\n >\n {{ field().ui!.labelEndLink!.text }}\n </fk-link>\n </div>\n}\n\n<fk-form-field\n [label]=\"\n field().ui?.labelEndLink\n ? null\n : field().type === 'checkbox'\n ? null\n : (field().label ?? null)\n \"\n [showErrorsOn]=\"'touched'\"\n [submitted]=\"submitted()\"\n [errorMessages]=\"field().errorMessages ?? null\"\n [fallbackControl]=\"form().get(field().key)\"\n [style.display]=\"visible() ? '' : 'none'\"\n>\n @if (field().ui?.prefixIcon && prefixIconTemplate(); as tpl) {\n <span fkPrefix>\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: field() }\"\n />\n </span>\n }\n <ng-container #controlHost />\n @if (field().ui?.hint) {\n <fk-hint>{{ field().ui?.hint }}</fk-hint>\n }\n</fk-form-field>\n", styles: [".fk-field-outlet__label-row{display:flex;align-items:baseline;justify-content:space-between;font-family:var(--fk-font-family-base);font-size:var(--fk-form-label-font-size);font-weight:var(--fk-form-label-font-weight);line-height:var(--fk-form-label-line-height);color:var(--fk-form-label-color)}.fk-field-outlet__label-text{display:flex;align-items:baseline;gap:.25em}.fk-field-outlet__required{color:var(--fk-form-error-color)}.fk-field-outlet__label-row fk-link{--fk-link-font-size-small: .75rem;--fk-link-font-size-medium: .75rem}.fk-field-outlet__label-row+fk-form-field{margin-top:0}\n"] }]
|
|
3040
|
+
}], ctorParameters: () => [], propDecorators: { className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], submitted: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitted", required: false }] }], prefixIconTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefixIconTemplate", required: false }] }], hostClass: [{
|
|
3038
3041
|
type: HostBinding,
|
|
3039
3042
|
args: ['class']
|
|
3040
3043
|
}], hostDisplay: [{
|
|
@@ -3065,6 +3068,8 @@ class FieldArrayOutletComponent {
|
|
|
3065
3068
|
field = input.required(...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
|
|
3066
3069
|
/** The FormArray backing the repeatable rows. */
|
|
3067
3070
|
formArray = input.required(...(ngDevMode ? [{ debugName: "formArray" }] : /* istanbul ignore next */ []));
|
|
3071
|
+
/** Prefix-icon template threaded to each child field (the app owns the icon). */
|
|
3072
|
+
prefixIconTemplate = input(undefined, ...(ngDevMode ? [{ debugName: "prefixIconTemplate" }] : /* istanbul ignore next */ []));
|
|
3068
3073
|
/** Whether the parent form has been submitted; propagated to each fk-field-outlet. */
|
|
3069
3074
|
submitted = input(false, ...(ngDevMode ? [{ debugName: "submitted" }] : /* istanbul ignore next */ []));
|
|
3070
3075
|
/** Fires with the index of the newly added row. */
|
|
@@ -3112,12 +3117,12 @@ class FieldArrayOutletComponent {
|
|
|
3112
3117
|
this.rowRemoved.emit(index);
|
|
3113
3118
|
}
|
|
3114
3119
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FieldArrayOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3115
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: FieldArrayOutletComponent, isStandalone: true, selector: "fk-field-array-outlet", inputs: { className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, formArray: { classPropertyName: "formArray", publicName: "formArray", isSignal: true, isRequired: true, transformFunction: null }, submitted: { classPropertyName: "submitted", publicName: "submitted", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rowAdded: "rowAdded", rowRemoved: "rowRemoved" }, host: { properties: { "class": "this.hostClass" } }, ngImport: i0, template: "@if (field().label) {\n <legend class=\"fk-field-array__legend\">{{ field().label }}</legend>\n}\n@for (row of rows(); track $index) {\n <div class=\"fk-field-array__row\" [formGroup]=\"row\">\n @for (childField of field().arrayFields ?? []; track childField.key) {\n <fk-field-outlet\n [field]=\"childField\"\n [form]=\"row\"\n [submitted]=\"submitted()\"\n />\n }\n @if (canRemove()) {\n <button\n type=\"button\"\n class=\"fk-field-array__remove\"\n aria-label=\"Remove row\"\n (click)=\"removeRow($index)\"\n >\n ×\n </button>\n }\n </div>\n}\n@if (canAdd()) {\n <button type=\"button\" class=\"fk-field-array__add\" (click)=\"addRow()\">\n + Add\n </button>\n}\n", styles: [":host{display:block}.fk-field-array__legend{font-size:var( --fk-field-array-label-font-size, var(--fk-form-label-font-size, .875rem) );font-weight:var( --fk-field-array-label-font-weight, var(--fk-form-label-font-weight, 500) );color:var( --fk-field-array-label-color, var(--fk-form-label-color, #1f2d3d) )}.fk-field-array__row{display:flex;column-gap:var(--fk-field-array-row-gap, var(--fk-rhythm-3, .75rem));align-items:flex-start;margin-top:var(--fk-field-array-row-gap, var(--fk-rhythm-3, .75rem))}.fk-field-array__legend+.fk-field-array__row{margin-top:var( --fk-field-array-label-gap, var(--fk-form-label-gap, .375rem) )}.fk-field-array__row>fk-field-outlet{flex:1;--fk-form-label-gap: 0}.fk-field-array__remove{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:var(--fk-field-array-remove-size, var(--fk-rhythm-8, 2rem));height:var(--fk-field-array-remove-size, var(--fk-rhythm-8, 2rem));margin-top:var(--fk-field-array-remove-offset, .25rem);padding:0;font-size:1.125rem;line-height:1;color:var(--fk-field-array-remove-color, var(--fk-color-muted, #8a98a8));background:transparent;border:1px solid var( --fk-field-array-remove-border-color, var(--fk-color-border, #d9e2ee) );border-radius:var( --fk-field-array-remove-radius, var(--fk-radius-md, .5rem) );cursor:pointer;transition:color .15s,border-color .15s}.fk-field-array__remove:hover{color:var( --fk-field-array-remove-hover-color, var(--fk-form-error-color, #dc2626) );border-color:var( --fk-field-array-remove-hover-color, var(--fk-form-error-color, #dc2626) )}.fk-field-array__remove:focus-visible{outline:none;box-shadow:var( --fk-field-array-remove-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)) )}.fk-field-array__add{margin-top:var(--fk-field-array-add-gap, var(--fk-rhythm-3, .75rem));padding:var(--fk-field-array-add-padding-y, var(--fk-rhythm-2, .5rem)) var(--fk-field-array-add-padding-x, var(--fk-rhythm-4, 1rem));font-size:var( --fk-field-array-add-font-size, var(--fk-typography-small-font-size, .8125rem) );color:var(--fk-field-array-add-color, var(--fk-color-primary, #0a84ff));background:transparent;border:1px dashed var(--fk-field-array-add-border-color, var(--fk-color-border, #d9e2ee));border-radius:var( --fk-field-array-add-radius, var(--fk-radius-md, .5rem) );cursor:pointer;transition:color .15s,border-color .15s}.fk-field-array__add:hover{border-color:var( --fk-field-array-add-hover-border-color, var(--fk-color-primary, #0a84ff) )}.fk-field-array__add:focus-visible{outline:none;box-shadow:var( --fk-field-array-add-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)) )}\n"], dependencies: [{ kind: "component", type: FieldOutletComponent, selector: "fk-field-outlet", inputs: ["className", "field", "form", "submitted"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3120
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: FieldArrayOutletComponent, isStandalone: true, selector: "fk-field-array-outlet", inputs: { className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, formArray: { classPropertyName: "formArray", publicName: "formArray", isSignal: true, isRequired: true, transformFunction: null }, prefixIconTemplate: { classPropertyName: "prefixIconTemplate", publicName: "prefixIconTemplate", isSignal: true, isRequired: false, transformFunction: null }, submitted: { classPropertyName: "submitted", publicName: "submitted", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rowAdded: "rowAdded", rowRemoved: "rowRemoved" }, host: { properties: { "class": "this.hostClass" } }, ngImport: i0, template: "@if (field().label) {\n <legend class=\"fk-field-array__legend\">{{ field().label }}</legend>\n}\n@for (row of rows(); track $index) {\n <div class=\"fk-field-array__row\" [formGroup]=\"row\">\n @for (childField of field().arrayFields ?? []; track childField.key) {\n <fk-field-outlet\n [field]=\"childField\"\n [form]=\"row\"\n [submitted]=\"submitted()\"\n [prefixIconTemplate]=\"prefixIconTemplate()\"\n />\n }\n @if (canRemove()) {\n <button\n type=\"button\"\n class=\"fk-field-array__remove\"\n aria-label=\"Remove row\"\n (click)=\"removeRow($index)\"\n >\n ×\n </button>\n }\n </div>\n}\n@if (canAdd()) {\n <button type=\"button\" class=\"fk-field-array__add\" (click)=\"addRow()\">\n + Add\n </button>\n}\n", styles: [":host{display:block}.fk-field-array__legend{font-size:var( --fk-field-array-label-font-size, var(--fk-form-label-font-size, .875rem) );font-weight:var( --fk-field-array-label-font-weight, var(--fk-form-label-font-weight, 500) );color:var( --fk-field-array-label-color, var(--fk-form-label-color, #1f2d3d) )}.fk-field-array__row{display:flex;column-gap:var(--fk-field-array-row-gap, var(--fk-rhythm-3, .75rem));align-items:flex-start;margin-top:var(--fk-field-array-row-gap, var(--fk-rhythm-3, .75rem))}.fk-field-array__legend+.fk-field-array__row{margin-top:var( --fk-field-array-label-gap, var(--fk-form-label-gap, .375rem) )}.fk-field-array__row>fk-field-outlet{flex:1;--fk-form-label-gap: 0}.fk-field-array__remove{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:var(--fk-field-array-remove-size, var(--fk-rhythm-8, 2rem));height:var(--fk-field-array-remove-size, var(--fk-rhythm-8, 2rem));margin-top:var(--fk-field-array-remove-offset, .25rem);padding:0;font-size:1.125rem;line-height:1;color:var(--fk-field-array-remove-color, var(--fk-color-muted, #8a98a8));background:transparent;border:1px solid var( --fk-field-array-remove-border-color, var(--fk-color-border, #d9e2ee) );border-radius:var( --fk-field-array-remove-radius, var(--fk-radius-md, .5rem) );cursor:pointer;transition:color .15s,border-color .15s}.fk-field-array__remove:hover{color:var( --fk-field-array-remove-hover-color, var(--fk-form-error-color, #dc2626) );border-color:var( --fk-field-array-remove-hover-color, var(--fk-form-error-color, #dc2626) )}.fk-field-array__remove:focus-visible{outline:none;box-shadow:var( --fk-field-array-remove-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)) )}.fk-field-array__add{margin-top:var(--fk-field-array-add-gap, var(--fk-rhythm-3, .75rem));padding:var(--fk-field-array-add-padding-y, var(--fk-rhythm-2, .5rem)) var(--fk-field-array-add-padding-x, var(--fk-rhythm-4, 1rem));font-size:var( --fk-field-array-add-font-size, var(--fk-typography-small-font-size, .8125rem) );color:var(--fk-field-array-add-color, var(--fk-color-primary, #0a84ff));background:transparent;border:1px dashed var(--fk-field-array-add-border-color, var(--fk-color-border, #d9e2ee));border-radius:var( --fk-field-array-add-radius, var(--fk-radius-md, .5rem) );cursor:pointer;transition:color .15s,border-color .15s}.fk-field-array__add:hover{border-color:var( --fk-field-array-add-hover-border-color, var(--fk-color-primary, #0a84ff) )}.fk-field-array__add:focus-visible{outline:none;box-shadow:var( --fk-field-array-add-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)) )}\n"], dependencies: [{ kind: "component", type: FieldOutletComponent, selector: "fk-field-outlet", inputs: ["className", "field", "form", "submitted", "prefixIconTemplate"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3116
3121
|
}
|
|
3117
3122
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FieldArrayOutletComponent, decorators: [{
|
|
3118
3123
|
type: Component,
|
|
3119
|
-
args: [{ selector: 'fk-field-array-outlet', standalone: true, imports: [FieldOutletComponent, ReactiveFormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (field().label) {\n <legend class=\"fk-field-array__legend\">{{ field().label }}</legend>\n}\n@for (row of rows(); track $index) {\n <div class=\"fk-field-array__row\" [formGroup]=\"row\">\n @for (childField of field().arrayFields ?? []; track childField.key) {\n <fk-field-outlet\n [field]=\"childField\"\n [form]=\"row\"\n [submitted]=\"submitted()\"\n />\n }\n @if (canRemove()) {\n <button\n type=\"button\"\n class=\"fk-field-array__remove\"\n aria-label=\"Remove row\"\n (click)=\"removeRow($index)\"\n >\n ×\n </button>\n }\n </div>\n}\n@if (canAdd()) {\n <button type=\"button\" class=\"fk-field-array__add\" (click)=\"addRow()\">\n + Add\n </button>\n}\n", styles: [":host{display:block}.fk-field-array__legend{font-size:var( --fk-field-array-label-font-size, var(--fk-form-label-font-size, .875rem) );font-weight:var( --fk-field-array-label-font-weight, var(--fk-form-label-font-weight, 500) );color:var( --fk-field-array-label-color, var(--fk-form-label-color, #1f2d3d) )}.fk-field-array__row{display:flex;column-gap:var(--fk-field-array-row-gap, var(--fk-rhythm-3, .75rem));align-items:flex-start;margin-top:var(--fk-field-array-row-gap, var(--fk-rhythm-3, .75rem))}.fk-field-array__legend+.fk-field-array__row{margin-top:var( --fk-field-array-label-gap, var(--fk-form-label-gap, .375rem) )}.fk-field-array__row>fk-field-outlet{flex:1;--fk-form-label-gap: 0}.fk-field-array__remove{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:var(--fk-field-array-remove-size, var(--fk-rhythm-8, 2rem));height:var(--fk-field-array-remove-size, var(--fk-rhythm-8, 2rem));margin-top:var(--fk-field-array-remove-offset, .25rem);padding:0;font-size:1.125rem;line-height:1;color:var(--fk-field-array-remove-color, var(--fk-color-muted, #8a98a8));background:transparent;border:1px solid var( --fk-field-array-remove-border-color, var(--fk-color-border, #d9e2ee) );border-radius:var( --fk-field-array-remove-radius, var(--fk-radius-md, .5rem) );cursor:pointer;transition:color .15s,border-color .15s}.fk-field-array__remove:hover{color:var( --fk-field-array-remove-hover-color, var(--fk-form-error-color, #dc2626) );border-color:var( --fk-field-array-remove-hover-color, var(--fk-form-error-color, #dc2626) )}.fk-field-array__remove:focus-visible{outline:none;box-shadow:var( --fk-field-array-remove-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)) )}.fk-field-array__add{margin-top:var(--fk-field-array-add-gap, var(--fk-rhythm-3, .75rem));padding:var(--fk-field-array-add-padding-y, var(--fk-rhythm-2, .5rem)) var(--fk-field-array-add-padding-x, var(--fk-rhythm-4, 1rem));font-size:var( --fk-field-array-add-font-size, var(--fk-typography-small-font-size, .8125rem) );color:var(--fk-field-array-add-color, var(--fk-color-primary, #0a84ff));background:transparent;border:1px dashed var(--fk-field-array-add-border-color, var(--fk-color-border, #d9e2ee));border-radius:var( --fk-field-array-add-radius, var(--fk-radius-md, .5rem) );cursor:pointer;transition:color .15s,border-color .15s}.fk-field-array__add:hover{border-color:var( --fk-field-array-add-hover-border-color, var(--fk-color-primary, #0a84ff) )}.fk-field-array__add:focus-visible{outline:none;box-shadow:var( --fk-field-array-add-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)) )}\n"] }]
|
|
3120
|
-
}], propDecorators: { className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], formArray: [{ type: i0.Input, args: [{ isSignal: true, alias: "formArray", required: true }] }], submitted: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitted", required: false }] }], rowAdded: [{ type: i0.Output, args: ["rowAdded"] }], rowRemoved: [{ type: i0.Output, args: ["rowRemoved"] }], hostClass: [{
|
|
3124
|
+
args: [{ selector: 'fk-field-array-outlet', standalone: true, imports: [FieldOutletComponent, ReactiveFormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (field().label) {\n <legend class=\"fk-field-array__legend\">{{ field().label }}</legend>\n}\n@for (row of rows(); track $index) {\n <div class=\"fk-field-array__row\" [formGroup]=\"row\">\n @for (childField of field().arrayFields ?? []; track childField.key) {\n <fk-field-outlet\n [field]=\"childField\"\n [form]=\"row\"\n [submitted]=\"submitted()\"\n [prefixIconTemplate]=\"prefixIconTemplate()\"\n />\n }\n @if (canRemove()) {\n <button\n type=\"button\"\n class=\"fk-field-array__remove\"\n aria-label=\"Remove row\"\n (click)=\"removeRow($index)\"\n >\n ×\n </button>\n }\n </div>\n}\n@if (canAdd()) {\n <button type=\"button\" class=\"fk-field-array__add\" (click)=\"addRow()\">\n + Add\n </button>\n}\n", styles: [":host{display:block}.fk-field-array__legend{font-size:var( --fk-field-array-label-font-size, var(--fk-form-label-font-size, .875rem) );font-weight:var( --fk-field-array-label-font-weight, var(--fk-form-label-font-weight, 500) );color:var( --fk-field-array-label-color, var(--fk-form-label-color, #1f2d3d) )}.fk-field-array__row{display:flex;column-gap:var(--fk-field-array-row-gap, var(--fk-rhythm-3, .75rem));align-items:flex-start;margin-top:var(--fk-field-array-row-gap, var(--fk-rhythm-3, .75rem))}.fk-field-array__legend+.fk-field-array__row{margin-top:var( --fk-field-array-label-gap, var(--fk-form-label-gap, .375rem) )}.fk-field-array__row>fk-field-outlet{flex:1;--fk-form-label-gap: 0}.fk-field-array__remove{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:var(--fk-field-array-remove-size, var(--fk-rhythm-8, 2rem));height:var(--fk-field-array-remove-size, var(--fk-rhythm-8, 2rem));margin-top:var(--fk-field-array-remove-offset, .25rem);padding:0;font-size:1.125rem;line-height:1;color:var(--fk-field-array-remove-color, var(--fk-color-muted, #8a98a8));background:transparent;border:1px solid var( --fk-field-array-remove-border-color, var(--fk-color-border, #d9e2ee) );border-radius:var( --fk-field-array-remove-radius, var(--fk-radius-md, .5rem) );cursor:pointer;transition:color .15s,border-color .15s}.fk-field-array__remove:hover{color:var( --fk-field-array-remove-hover-color, var(--fk-form-error-color, #dc2626) );border-color:var( --fk-field-array-remove-hover-color, var(--fk-form-error-color, #dc2626) )}.fk-field-array__remove:focus-visible{outline:none;box-shadow:var( --fk-field-array-remove-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)) )}.fk-field-array__add{margin-top:var(--fk-field-array-add-gap, var(--fk-rhythm-3, .75rem));padding:var(--fk-field-array-add-padding-y, var(--fk-rhythm-2, .5rem)) var(--fk-field-array-add-padding-x, var(--fk-rhythm-4, 1rem));font-size:var( --fk-field-array-add-font-size, var(--fk-typography-small-font-size, .8125rem) );color:var(--fk-field-array-add-color, var(--fk-color-primary, #0a84ff));background:transparent;border:1px dashed var(--fk-field-array-add-border-color, var(--fk-color-border, #d9e2ee));border-radius:var( --fk-field-array-add-radius, var(--fk-radius-md, .5rem) );cursor:pointer;transition:color .15s,border-color .15s}.fk-field-array__add:hover{border-color:var( --fk-field-array-add-hover-border-color, var(--fk-color-primary, #0a84ff) )}.fk-field-array__add:focus-visible{outline:none;box-shadow:var( --fk-field-array-add-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)) )}\n"] }]
|
|
3125
|
+
}], propDecorators: { className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], formArray: [{ type: i0.Input, args: [{ isSignal: true, alias: "formArray", required: true }] }], prefixIconTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefixIconTemplate", required: false }] }], submitted: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitted", required: false }] }], rowAdded: [{ type: i0.Output, args: ["rowAdded"] }], rowRemoved: [{ type: i0.Output, args: ["rowRemoved"] }], hostClass: [{
|
|
3121
3126
|
type: HostBinding,
|
|
3122
3127
|
args: ['class']
|
|
3123
3128
|
}] } });
|
|
@@ -3143,6 +3148,8 @@ class SectionOutletComponent {
|
|
|
3143
3148
|
form = input.required(...(ngDevMode ? [{ debugName: "form" }] : /* istanbul ignore next */ []));
|
|
3144
3149
|
/** Whether the parent form has been submitted; propagated to each fk-field-outlet. */
|
|
3145
3150
|
submitted = input(false, ...(ngDevMode ? [{ debugName: "submitted" }] : /* istanbul ignore next */ []));
|
|
3151
|
+
/** Prefix-icon template threaded to each field (the app owns the icon). */
|
|
3152
|
+
prefixIconTemplate = input(undefined, ...(ngDevMode ? [{ debugName: "prefixIconTemplate" }] : /* istanbul ignore next */ []));
|
|
3146
3153
|
classes = computed(() => ['fk-section-outlet', this.className()].filter(Boolean).join(' '), ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
3147
3154
|
get hostClass() {
|
|
3148
3155
|
return this.classes();
|
|
@@ -3152,12 +3159,12 @@ class SectionOutletComponent {
|
|
|
3152
3159
|
return this.section().fields.find((f) => f.key === key);
|
|
3153
3160
|
}
|
|
3154
3161
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SectionOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3155
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: SectionOutletComponent, isStandalone: true, selector: "fk-section-outlet", inputs: { className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, section: { classPropertyName: "section", publicName: "section", isSignal: true, isRequired: true, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, submitted: { classPropertyName: "submitted", publicName: "submitted", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClass" } }, ngImport: i0, template: "@if (section().title) {\n <h3 class=\"fk-section__title\">{{ section().title }}</h3>\n}\n@if (section().description) {\n <p class=\"fk-section__description\">{{ section().description }}</p>\n}\n<div class=\"fk-section__fields\">\n @if (section().layout?.length) {\n @for (row of section().layout!; track $index) {\n <div class=\"fk-section__row\">\n @for (col of row.columns; track col.fieldKey) {\n <div class=\"fk-section__col\" [style.--fk-col-span]=\"col.span ?? 12\">\n @if (getField(col.fieldKey); as field) {\n <fk-field-outlet\n [field]=\"field\"\n [form]=\"form()\"\n [submitted]=\"submitted()\"\n />\n }\n </div>\n }\n </div>\n }\n } @else {\n @for (field of section().fields; track field.key) {\n <fk-field-outlet\n [field]=\"field\"\n [form]=\"form()\"\n [submitted]=\"submitted()\"\n />\n }\n }\n</div>\n", styles: [":host{display:block;margin-bottom:var(--fk-rhythm-6, 1.5rem)}.fk-section__title{font-size:1.125rem;font-weight:600;color:var(--fk-form-label-color);margin:0 0 var(--fk-rhythm-2, .5rem)}.fk-section__description{font-size:var(--fk-form-hint-font-size);color:var(--fk-form-hint-color);margin:0 0 var(--fk-rhythm-4, 1rem)}.fk-section__fields{display:flex;flex-direction:column}.fk-section__row{display:grid;grid-template-columns:repeat(12,1fr);column-gap:var(--fk-form-field-gap)}.fk-section__col{grid-column:span var(--fk-col-span, 12)}\n"], dependencies: [{ kind: "component", type: FieldOutletComponent, selector: "fk-field-outlet", inputs: ["className", "field", "form", "submitted"] }, { kind: "ngmodule", type: ReactiveFormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3162
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: SectionOutletComponent, isStandalone: true, selector: "fk-section-outlet", inputs: { className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, section: { classPropertyName: "section", publicName: "section", isSignal: true, isRequired: true, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, submitted: { classPropertyName: "submitted", publicName: "submitted", isSignal: true, isRequired: false, transformFunction: null }, prefixIconTemplate: { classPropertyName: "prefixIconTemplate", publicName: "prefixIconTemplate", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClass" } }, ngImport: i0, template: "@if (section().title) {\n <h3 class=\"fk-section__title\">{{ section().title }}</h3>\n}\n@if (section().description) {\n <p class=\"fk-section__description\">{{ section().description }}</p>\n}\n<div class=\"fk-section__fields\">\n @if (section().layout?.length) {\n @for (row of section().layout!; track $index) {\n <div class=\"fk-section__row\">\n @for (col of row.columns; track col.fieldKey) {\n <div class=\"fk-section__col\" [style.--fk-col-span]=\"col.span ?? 12\">\n @if (getField(col.fieldKey); as field) {\n <fk-field-outlet\n [field]=\"field\"\n [form]=\"form()\"\n [submitted]=\"submitted()\"\n [prefixIconTemplate]=\"prefixIconTemplate()\"\n />\n }\n </div>\n }\n </div>\n }\n } @else {\n @for (field of section().fields; track field.key) {\n <fk-field-outlet\n [field]=\"field\"\n [form]=\"form()\"\n [submitted]=\"submitted()\"\n [prefixIconTemplate]=\"prefixIconTemplate()\"\n />\n }\n }\n</div>\n", styles: [":host{display:block;margin-bottom:var(--fk-rhythm-6, 1.5rem)}.fk-section__title{font-size:1.125rem;font-weight:600;color:var(--fk-form-label-color);margin:0 0 var(--fk-rhythm-2, .5rem)}.fk-section__description{font-size:var(--fk-form-hint-font-size);color:var(--fk-form-hint-color);margin:0 0 var(--fk-rhythm-4, 1rem)}.fk-section__fields{display:flex;flex-direction:column}.fk-section__row{display:grid;grid-template-columns:repeat(12,1fr);column-gap:var(--fk-form-field-gap)}.fk-section__col{grid-column:span var(--fk-col-span, 12)}\n"], dependencies: [{ kind: "component", type: FieldOutletComponent, selector: "fk-field-outlet", inputs: ["className", "field", "form", "submitted", "prefixIconTemplate"] }, { kind: "ngmodule", type: ReactiveFormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3156
3163
|
}
|
|
3157
3164
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SectionOutletComponent, decorators: [{
|
|
3158
3165
|
type: Component,
|
|
3159
|
-
args: [{ selector: 'fk-section-outlet', standalone: true, imports: [FieldOutletComponent, ReactiveFormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (section().title) {\n <h3 class=\"fk-section__title\">{{ section().title }}</h3>\n}\n@if (section().description) {\n <p class=\"fk-section__description\">{{ section().description }}</p>\n}\n<div class=\"fk-section__fields\">\n @if (section().layout?.length) {\n @for (row of section().layout!; track $index) {\n <div class=\"fk-section__row\">\n @for (col of row.columns; track col.fieldKey) {\n <div class=\"fk-section__col\" [style.--fk-col-span]=\"col.span ?? 12\">\n @if (getField(col.fieldKey); as field) {\n <fk-field-outlet\n [field]=\"field\"\n [form]=\"form()\"\n [submitted]=\"submitted()\"\n />\n }\n </div>\n }\n </div>\n }\n } @else {\n @for (field of section().fields; track field.key) {\n <fk-field-outlet\n [field]=\"field\"\n [form]=\"form()\"\n [submitted]=\"submitted()\"\n />\n }\n }\n</div>\n", styles: [":host{display:block;margin-bottom:var(--fk-rhythm-6, 1.5rem)}.fk-section__title{font-size:1.125rem;font-weight:600;color:var(--fk-form-label-color);margin:0 0 var(--fk-rhythm-2, .5rem)}.fk-section__description{font-size:var(--fk-form-hint-font-size);color:var(--fk-form-hint-color);margin:0 0 var(--fk-rhythm-4, 1rem)}.fk-section__fields{display:flex;flex-direction:column}.fk-section__row{display:grid;grid-template-columns:repeat(12,1fr);column-gap:var(--fk-form-field-gap)}.fk-section__col{grid-column:span var(--fk-col-span, 12)}\n"] }]
|
|
3160
|
-
}], propDecorators: { className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], section: [{ type: i0.Input, args: [{ isSignal: true, alias: "section", required: true }] }], form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], submitted: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitted", required: false }] }], hostClass: [{
|
|
3166
|
+
args: [{ selector: 'fk-section-outlet', standalone: true, imports: [FieldOutletComponent, ReactiveFormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (section().title) {\n <h3 class=\"fk-section__title\">{{ section().title }}</h3>\n}\n@if (section().description) {\n <p class=\"fk-section__description\">{{ section().description }}</p>\n}\n<div class=\"fk-section__fields\">\n @if (section().layout?.length) {\n @for (row of section().layout!; track $index) {\n <div class=\"fk-section__row\">\n @for (col of row.columns; track col.fieldKey) {\n <div class=\"fk-section__col\" [style.--fk-col-span]=\"col.span ?? 12\">\n @if (getField(col.fieldKey); as field) {\n <fk-field-outlet\n [field]=\"field\"\n [form]=\"form()\"\n [submitted]=\"submitted()\"\n [prefixIconTemplate]=\"prefixIconTemplate()\"\n />\n }\n </div>\n }\n </div>\n }\n } @else {\n @for (field of section().fields; track field.key) {\n <fk-field-outlet\n [field]=\"field\"\n [form]=\"form()\"\n [submitted]=\"submitted()\"\n [prefixIconTemplate]=\"prefixIconTemplate()\"\n />\n }\n }\n</div>\n", styles: [":host{display:block;margin-bottom:var(--fk-rhythm-6, 1.5rem)}.fk-section__title{font-size:1.125rem;font-weight:600;color:var(--fk-form-label-color);margin:0 0 var(--fk-rhythm-2, .5rem)}.fk-section__description{font-size:var(--fk-form-hint-font-size);color:var(--fk-form-hint-color);margin:0 0 var(--fk-rhythm-4, 1rem)}.fk-section__fields{display:flex;flex-direction:column}.fk-section__row{display:grid;grid-template-columns:repeat(12,1fr);column-gap:var(--fk-form-field-gap)}.fk-section__col{grid-column:span var(--fk-col-span, 12)}\n"] }]
|
|
3167
|
+
}], propDecorators: { className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], section: [{ type: i0.Input, args: [{ isSignal: true, alias: "section", required: true }] }], form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], submitted: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitted", required: false }] }], prefixIconTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefixIconTemplate", required: false }] }], hostClass: [{
|
|
3161
3168
|
type: HostBinding,
|
|
3162
3169
|
args: ['class']
|
|
3163
3170
|
}] } });
|
|
@@ -3195,6 +3202,12 @@ class FormRendererComponent {
|
|
|
3195
3202
|
* If not provided, one is auto-generated from the schema.
|
|
3196
3203
|
*/
|
|
3197
3204
|
form = input(null, ...(ngDevMode ? [{ debugName: "form" }] : /* istanbul ignore next */ []));
|
|
3205
|
+
/**
|
|
3206
|
+
* Optional template rendering a field's prefix icon (the app owns the icon
|
|
3207
|
+
* system). Receives the field as `$implicit`; render it from
|
|
3208
|
+
* `field.ui.prefixIcon`. Fields without a `prefixIcon` render no icon.
|
|
3209
|
+
*/
|
|
3210
|
+
prefixIconTemplate = input(undefined, ...(ngDevMode ? [{ debugName: "prefixIconTemplate" }] : /* istanbul ignore next */ []));
|
|
3198
3211
|
/** Emits the FormGroup value when the form is submitted. */
|
|
3199
3212
|
formSubmit = output();
|
|
3200
3213
|
/** The resolved FormGroup (either provided or auto-generated). */
|
|
@@ -3260,7 +3273,7 @@ class FormRendererComponent {
|
|
|
3260
3273
|
});
|
|
3261
3274
|
}
|
|
3262
3275
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FormRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3263
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: FormRendererComponent, isStandalone: true, selector: "fk-form-renderer", inputs: { className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, schema: { classPropertyName: "schema", publicName: "schema", isSignal: true, isRequired: true, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { formSubmit: "formSubmit" }, host: { properties: { "class": "this.hostClass" } }, ngImport: i0, template: "@if (resolvedForm()) {\n <fk-form (formSubmit)=\"onFormSubmit()\">\n <div class=\"fk-form-renderer__fields\" [formGroup]=\"resolvedForm()!\">\n @if (schema().sections?.length) {\n @for (section of schema().sections!; track $index) {\n <fk-section-outlet\n [section]=\"section\"\n [form]=\"resolvedForm()!\"\n [submitted]=\"formRef()?.submitted() ?? false\"\n />\n }\n }\n @if (schema().layout?.length) {\n @for (row of schema().layout!; track $index) {\n <div class=\"fk-form-renderer__row\">\n @for (col of row.columns; track col.fieldKey) {\n <div\n class=\"fk-form-renderer__col\"\n [style.--fk-col-span]=\"col.span ?? 12\"\n >\n @if (getField(col.fieldKey); as field) {\n <fk-field-outlet\n [field]=\"field\"\n [form]=\"resolvedForm()!\"\n [submitted]=\"formRef()?.submitted() ?? false\"\n />\n }\n </div>\n }\n </div>\n }\n } @else {\n @for (field of schema().fields; track field.key) {\n @if (field.arrayFields?.length) {\n <fk-field-array-outlet\n [field]=\"field\"\n [formArray]=\"getFormArray(field.key)\"\n [submitted]=\"formRef()?.submitted() ?? false\"\n />\n } @else {\n <fk-field-outlet\n [field]=\"field\"\n [form]=\"resolvedForm()!\"\n [submitted]=\"formRef()?.submitted() ?? false\"\n />\n }\n }\n }\n </div>\n <ng-content />\n </fk-form>\n}\n", styles: [":host{display:block}.fk-form-renderer__fields{display:flex;flex-direction:column;row-gap:var(--fk-form-field-gap, var(--fk-rhythm-4, 1rem))}.fk-form-renderer__row{display:grid;grid-template-columns:repeat(12,1fr);column-gap:var(--fk-form-field-gap, var(--fk-rhythm-4, 1rem))}.fk-form-renderer__col{grid-column:span var(--fk-col-span, 12)}\n"], dependencies: [{ kind: "component", type: FieldArrayOutletComponent, selector: "fk-field-array-outlet", inputs: ["className", "field", "formArray", "submitted"], outputs: ["rowAdded", "rowRemoved"] }, { kind: "component", type: FieldOutletComponent, selector: "fk-field-outlet", inputs: ["className", "field", "form", "submitted"] }, { kind: "component", type: FormComponent, selector: "fk-form", inputs: ["className"], outputs: ["formSubmit"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormArrayDirective, selector: "[formArray]", inputs: ["formArray"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: SectionOutletComponent, selector: "fk-section-outlet", inputs: ["className", "section", "form", "submitted"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3276
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: FormRendererComponent, isStandalone: true, selector: "fk-form-renderer", inputs: { className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, schema: { classPropertyName: "schema", publicName: "schema", isSignal: true, isRequired: true, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, prefixIconTemplate: { classPropertyName: "prefixIconTemplate", publicName: "prefixIconTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { formSubmit: "formSubmit" }, host: { properties: { "class": "this.hostClass" } }, ngImport: i0, template: "@if (resolvedForm()) {\n <fk-form (formSubmit)=\"onFormSubmit()\">\n <div class=\"fk-form-renderer__fields\" [formGroup]=\"resolvedForm()!\">\n @if (schema().sections?.length) {\n @for (section of schema().sections!; track $index) {\n <fk-section-outlet\n [section]=\"section\"\n [form]=\"resolvedForm()!\"\n [submitted]=\"formRef()?.submitted() ?? false\"\n [prefixIconTemplate]=\"prefixIconTemplate()\"\n />\n }\n }\n @if (schema().layout?.length) {\n @for (row of schema().layout!; track $index) {\n <div class=\"fk-form-renderer__row\">\n @for (col of row.columns; track col.fieldKey) {\n <div\n class=\"fk-form-renderer__col\"\n [style.--fk-col-span]=\"col.span ?? 12\"\n >\n @if (getField(col.fieldKey); as field) {\n <fk-field-outlet\n [field]=\"field\"\n [form]=\"resolvedForm()!\"\n [submitted]=\"formRef()?.submitted() ?? false\"\n [prefixIconTemplate]=\"prefixIconTemplate()\"\n />\n }\n </div>\n }\n </div>\n }\n } @else {\n @for (field of schema().fields; track field.key) {\n @if (field.arrayFields?.length) {\n <fk-field-array-outlet\n [field]=\"field\"\n [formArray]=\"getFormArray(field.key)\"\n [submitted]=\"formRef()?.submitted() ?? false\"\n [prefixIconTemplate]=\"prefixIconTemplate()\"\n />\n } @else {\n <fk-field-outlet\n [field]=\"field\"\n [form]=\"resolvedForm()!\"\n [submitted]=\"formRef()?.submitted() ?? false\"\n [prefixIconTemplate]=\"prefixIconTemplate()\"\n />\n }\n }\n }\n </div>\n <ng-content />\n </fk-form>\n}\n", styles: [":host{display:block}.fk-form-renderer__fields{display:flex;flex-direction:column;row-gap:var(--fk-form-field-gap, var(--fk-rhythm-4, 1rem))}.fk-form-renderer__row{display:grid;grid-template-columns:repeat(12,1fr);column-gap:var(--fk-form-field-gap, var(--fk-rhythm-4, 1rem))}.fk-form-renderer__col{grid-column:span var(--fk-col-span, 12)}\n"], dependencies: [{ kind: "component", type: FieldArrayOutletComponent, selector: "fk-field-array-outlet", inputs: ["className", "field", "formArray", "prefixIconTemplate", "submitted"], outputs: ["rowAdded", "rowRemoved"] }, { kind: "component", type: FieldOutletComponent, selector: "fk-field-outlet", inputs: ["className", "field", "form", "submitted", "prefixIconTemplate"] }, { kind: "component", type: FormComponent, selector: "fk-form", inputs: ["className"], outputs: ["formSubmit"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormArrayDirective, selector: "[formArray]", inputs: ["formArray"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: SectionOutletComponent, selector: "fk-section-outlet", inputs: ["className", "section", "form", "submitted", "prefixIconTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3264
3277
|
}
|
|
3265
3278
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FormRendererComponent, decorators: [{
|
|
3266
3279
|
type: Component,
|
|
@@ -3270,8 +3283,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
3270
3283
|
FormComponent,
|
|
3271
3284
|
ReactiveFormsModule,
|
|
3272
3285
|
SectionOutletComponent,
|
|
3273
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (resolvedForm()) {\n <fk-form (formSubmit)=\"onFormSubmit()\">\n <div class=\"fk-form-renderer__fields\" [formGroup]=\"resolvedForm()!\">\n @if (schema().sections?.length) {\n @for (section of schema().sections!; track $index) {\n <fk-section-outlet\n [section]=\"section\"\n [form]=\"resolvedForm()!\"\n [submitted]=\"formRef()?.submitted() ?? false\"\n />\n }\n }\n @if (schema().layout?.length) {\n @for (row of schema().layout!; track $index) {\n <div class=\"fk-form-renderer__row\">\n @for (col of row.columns; track col.fieldKey) {\n <div\n class=\"fk-form-renderer__col\"\n [style.--fk-col-span]=\"col.span ?? 12\"\n >\n @if (getField(col.fieldKey); as field) {\n <fk-field-outlet\n [field]=\"field\"\n [form]=\"resolvedForm()!\"\n [submitted]=\"formRef()?.submitted() ?? false\"\n />\n }\n </div>\n }\n </div>\n }\n } @else {\n @for (field of schema().fields; track field.key) {\n @if (field.arrayFields?.length) {\n <fk-field-array-outlet\n [field]=\"field\"\n [formArray]=\"getFormArray(field.key)\"\n [submitted]=\"formRef()?.submitted() ?? false\"\n />\n } @else {\n <fk-field-outlet\n [field]=\"field\"\n [form]=\"resolvedForm()!\"\n [submitted]=\"formRef()?.submitted() ?? false\"\n />\n }\n }\n }\n </div>\n <ng-content />\n </fk-form>\n}\n", styles: [":host{display:block}.fk-form-renderer__fields{display:flex;flex-direction:column;row-gap:var(--fk-form-field-gap, var(--fk-rhythm-4, 1rem))}.fk-form-renderer__row{display:grid;grid-template-columns:repeat(12,1fr);column-gap:var(--fk-form-field-gap, var(--fk-rhythm-4, 1rem))}.fk-form-renderer__col{grid-column:span var(--fk-col-span, 12)}\n"] }]
|
|
3274
|
-
}], propDecorators: { className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], schema: [{ type: i0.Input, args: [{ isSignal: true, alias: "schema", required: true }] }], form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: false }] }], formSubmit: [{ type: i0.Output, args: ["formSubmit"] }], hostClass: [{
|
|
3286
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (resolvedForm()) {\n <fk-form (formSubmit)=\"onFormSubmit()\">\n <div class=\"fk-form-renderer__fields\" [formGroup]=\"resolvedForm()!\">\n @if (schema().sections?.length) {\n @for (section of schema().sections!; track $index) {\n <fk-section-outlet\n [section]=\"section\"\n [form]=\"resolvedForm()!\"\n [submitted]=\"formRef()?.submitted() ?? false\"\n [prefixIconTemplate]=\"prefixIconTemplate()\"\n />\n }\n }\n @if (schema().layout?.length) {\n @for (row of schema().layout!; track $index) {\n <div class=\"fk-form-renderer__row\">\n @for (col of row.columns; track col.fieldKey) {\n <div\n class=\"fk-form-renderer__col\"\n [style.--fk-col-span]=\"col.span ?? 12\"\n >\n @if (getField(col.fieldKey); as field) {\n <fk-field-outlet\n [field]=\"field\"\n [form]=\"resolvedForm()!\"\n [submitted]=\"formRef()?.submitted() ?? false\"\n [prefixIconTemplate]=\"prefixIconTemplate()\"\n />\n }\n </div>\n }\n </div>\n }\n } @else {\n @for (field of schema().fields; track field.key) {\n @if (field.arrayFields?.length) {\n <fk-field-array-outlet\n [field]=\"field\"\n [formArray]=\"getFormArray(field.key)\"\n [submitted]=\"formRef()?.submitted() ?? false\"\n [prefixIconTemplate]=\"prefixIconTemplate()\"\n />\n } @else {\n <fk-field-outlet\n [field]=\"field\"\n [form]=\"resolvedForm()!\"\n [submitted]=\"formRef()?.submitted() ?? false\"\n [prefixIconTemplate]=\"prefixIconTemplate()\"\n />\n }\n }\n }\n </div>\n <ng-content />\n </fk-form>\n}\n", styles: [":host{display:block}.fk-form-renderer__fields{display:flex;flex-direction:column;row-gap:var(--fk-form-field-gap, var(--fk-rhythm-4, 1rem))}.fk-form-renderer__row{display:grid;grid-template-columns:repeat(12,1fr);column-gap:var(--fk-form-field-gap, var(--fk-rhythm-4, 1rem))}.fk-form-renderer__col{grid-column:span var(--fk-col-span, 12)}\n"] }]
|
|
3287
|
+
}], propDecorators: { className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], schema: [{ type: i0.Input, args: [{ isSignal: true, alias: "schema", required: true }] }], form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: false }] }], prefixIconTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefixIconTemplate", required: false }] }], formSubmit: [{ type: i0.Output, args: ["formSubmit"] }], hostClass: [{
|
|
3275
3288
|
type: HostBinding,
|
|
3276
3289
|
args: ['class']
|
|
3277
3290
|
}] } });
|
|
@@ -3422,8 +3435,6 @@ class FileDropzoneComponent {
|
|
|
3422
3435
|
multiple = input(false, ...(ngDevMode ? [{ debugName: "multiple" }] : /* istanbul ignore next */ []));
|
|
3423
3436
|
/** When true, prevents drag-and-drop and click-to-browse interaction. */
|
|
3424
3437
|
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
3425
|
-
/** Icon name rendered inside the dropzone surface. */
|
|
3426
|
-
icon = input('upload', ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
3427
3438
|
/** Primary prompt text displayed inside the dropzone. */
|
|
3428
3439
|
prompt = input.required(...(ngDevMode ? [{ debugName: "prompt" }] : /* istanbul ignore next */ []));
|
|
3429
3440
|
/** Secondary hint text shown below the prompt. */
|
|
@@ -3493,16 +3504,55 @@ class FileDropzoneComponent {
|
|
|
3493
3504
|
this.filesSelected.emit(this.multiple() ? files : [files[0]]);
|
|
3494
3505
|
}
|
|
3495
3506
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FileDropzoneComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3496
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: FileDropzoneComponent, isStandalone: true, selector: "fk-file-dropzone", inputs: { accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null },
|
|
3507
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: FileDropzoneComponent, isStandalone: true, selector: "fk-file-dropzone", inputs: { accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, prompt: { classPropertyName: "prompt", publicName: "prompt", isSignal: true, isRequired: true, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", 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: { filesSelected: "filesSelected" }, host: { properties: { "class": "this.hostClass" } }, ngImport: i0, template: "<label\n class=\"fk-file-dropzone__container\"\n [attr.id]=\"id() ?? undefined\"\n [attr.aria-label]=\"ariaLabel()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n>\n <ng-content select=\"[fkFileDropzoneIcon]\">\n <svg\n class=\"fk-file-dropzone__icon\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M12 3v12M7 8l5-5 5 5M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2\"\n stroke=\"currentColor\"\n stroke-width=\"1.6\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </ng-content>\n\n <fk-text tone=\"muted\" class=\"fk-file-dropzone__prompt\">\n {{ prompt() }}\n </fk-text>\n\n @if (hint(); as h) {\n <fk-text tone=\"muted\" class=\"fk-file-dropzone__hint\">\n {{ h }}\n </fk-text>\n }\n\n <input\n #nativeInput\n type=\"file\"\n class=\"fk-file-dropzone__native\"\n [attr.accept]=\"accept()\"\n [multiple]=\"multiple()\"\n [disabled]=\"disabled()\"\n (change)=\"onChange($event)\"\n />\n</label>\n", styles: [":host{display:block}.fk-file-dropzone__container{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--fk-file-dropzone-gap, var(--fk-rhythm-2, .5rem));min-height:var(--fk-file-dropzone-min-height, 10rem);padding:var(--fk-file-dropzone-padding, var(--fk-rhythm-10, 2.5rem));background:var(--fk-file-dropzone-bg, var(--fk-color-surface-raised, #f8fafc));border:var(--fk-file-dropzone-border-width, 2px) var(--fk-file-dropzone-border-style, dashed) var(--fk-file-dropzone-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-file-dropzone-border-radius, var(--fk-radius-lg, .75rem));cursor:pointer;transition:border-color .15s ease,background-color .15s ease}.fk-file-dropzone__container:hover{border-color:var(--fk-file-dropzone-border-color-hover, var(--fk-color-primary, #0a84ff))}.fk-file-dropzone__container:focus-within{outline:none;box-shadow:var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18))}.fk-file-dropzone__icon{width:var(--fk-file-dropzone-icon-size, 2rem);height:var(--fk-file-dropzone-icon-size, 2rem);color:var(--fk-file-dropzone-icon-color, var(--fk-color-muted, #8a98a8))}.fk-file-dropzone__prompt{font-weight:var(--fk-font-weight-semibold, 600);color:var(--fk-file-dropzone-prompt-color, var(--fk-color-text, #1f2d3d))}.fk-file-dropzone__hint{font-size:var(--fk-file-dropzone-hint-font-size, .8125rem)}.fk-file-dropzone__native{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}:host.fk-file-dropzone--dragging .fk-file-dropzone__container{border-color:var(--fk-file-dropzone-border-color-dragging, var(--fk-color-primary, #0a84ff));background:var(--fk-file-dropzone-bg-dragging, rgba(10, 132, 255, .04))}:host.fk-file-dropzone--disabled .fk-file-dropzone__container{cursor:not-allowed;opacity:var(--fk-file-dropzone-opacity-disabled, .6)}:host.fk-file-dropzone--disabled .fk-file-dropzone__container:hover{border-color:var(--fk-file-dropzone-border-color, var(--fk-color-border, #d9e2ee))}:host.fk-file-dropzone--disabled .fk-file-dropzone__icon{color:var(--fk-file-dropzone-icon-color-disabled, var(--fk-color-muted, #8a98a8))}\n"], dependencies: [{ kind: "component", type: TextComponent, selector: "fk-text", inputs: ["as", "variant", "tone", "align", "weight", "truncate", "maxLines", "gutterBottom", "italic", "visuallyHidden", "className", "id", "ariaLabel", "ariaDescribedBy", "role", "htmlFor"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3497
3508
|
}
|
|
3498
3509
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FileDropzoneComponent, decorators: [{
|
|
3499
3510
|
type: Component,
|
|
3500
|
-
args: [{ selector: 'fk-file-dropzone', standalone: true, imports: [
|
|
3501
|
-
}], propDecorators: { accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }],
|
|
3511
|
+
args: [{ selector: 'fk-file-dropzone', standalone: true, imports: [TextComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<label\n class=\"fk-file-dropzone__container\"\n [attr.id]=\"id() ?? undefined\"\n [attr.aria-label]=\"ariaLabel()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n>\n <ng-content select=\"[fkFileDropzoneIcon]\">\n <svg\n class=\"fk-file-dropzone__icon\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M12 3v12M7 8l5-5 5 5M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2\"\n stroke=\"currentColor\"\n stroke-width=\"1.6\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </ng-content>\n\n <fk-text tone=\"muted\" class=\"fk-file-dropzone__prompt\">\n {{ prompt() }}\n </fk-text>\n\n @if (hint(); as h) {\n <fk-text tone=\"muted\" class=\"fk-file-dropzone__hint\">\n {{ h }}\n </fk-text>\n }\n\n <input\n #nativeInput\n type=\"file\"\n class=\"fk-file-dropzone__native\"\n [attr.accept]=\"accept()\"\n [multiple]=\"multiple()\"\n [disabled]=\"disabled()\"\n (change)=\"onChange($event)\"\n />\n</label>\n", styles: [":host{display:block}.fk-file-dropzone__container{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--fk-file-dropzone-gap, var(--fk-rhythm-2, .5rem));min-height:var(--fk-file-dropzone-min-height, 10rem);padding:var(--fk-file-dropzone-padding, var(--fk-rhythm-10, 2.5rem));background:var(--fk-file-dropzone-bg, var(--fk-color-surface-raised, #f8fafc));border:var(--fk-file-dropzone-border-width, 2px) var(--fk-file-dropzone-border-style, dashed) var(--fk-file-dropzone-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-file-dropzone-border-radius, var(--fk-radius-lg, .75rem));cursor:pointer;transition:border-color .15s ease,background-color .15s ease}.fk-file-dropzone__container:hover{border-color:var(--fk-file-dropzone-border-color-hover, var(--fk-color-primary, #0a84ff))}.fk-file-dropzone__container:focus-within{outline:none;box-shadow:var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18))}.fk-file-dropzone__icon{width:var(--fk-file-dropzone-icon-size, 2rem);height:var(--fk-file-dropzone-icon-size, 2rem);color:var(--fk-file-dropzone-icon-color, var(--fk-color-muted, #8a98a8))}.fk-file-dropzone__prompt{font-weight:var(--fk-font-weight-semibold, 600);color:var(--fk-file-dropzone-prompt-color, var(--fk-color-text, #1f2d3d))}.fk-file-dropzone__hint{font-size:var(--fk-file-dropzone-hint-font-size, .8125rem)}.fk-file-dropzone__native{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}:host.fk-file-dropzone--dragging .fk-file-dropzone__container{border-color:var(--fk-file-dropzone-border-color-dragging, var(--fk-color-primary, #0a84ff));background:var(--fk-file-dropzone-bg-dragging, rgba(10, 132, 255, .04))}:host.fk-file-dropzone--disabled .fk-file-dropzone__container{cursor:not-allowed;opacity:var(--fk-file-dropzone-opacity-disabled, .6)}:host.fk-file-dropzone--disabled .fk-file-dropzone__container:hover{border-color:var(--fk-file-dropzone-border-color, var(--fk-color-border, #d9e2ee))}:host.fk-file-dropzone--disabled .fk-file-dropzone__icon{color:var(--fk-file-dropzone-icon-color-disabled, var(--fk-color-muted, #8a98a8))}\n"] }]
|
|
3512
|
+
}], propDecorators: { accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], prompt: [{ type: i0.Input, args: [{ isSignal: true, alias: "prompt", required: true }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", 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 }] }], filesSelected: [{ type: i0.Output, args: ["filesSelected"] }], hostClass: [{
|
|
3502
3513
|
type: HostBinding,
|
|
3503
3514
|
args: ['class']
|
|
3504
3515
|
}] } });
|
|
3505
3516
|
|
|
3517
|
+
/** Injection token for the icon slot of `fk-file-dropzone`. */
|
|
3518
|
+
const FK_FILE_DROPZONE_ICON = new InjectionToken('FK_FILE_DROPZONE_ICON');
|
|
3519
|
+
/**
|
|
3520
|
+
* Marks projected content as the icon of an `fk-file-dropzone`, overriding the
|
|
3521
|
+
* built-in upload glyph. Project any icon element (the app owns the icon
|
|
3522
|
+
* system):
|
|
3523
|
+
*
|
|
3524
|
+
* ```html
|
|
3525
|
+
* <fk-file-dropzone prompt="Drop a file">
|
|
3526
|
+
* <fk-icon fkFileDropzoneIcon name="file-content" size="lg" />
|
|
3527
|
+
* </fk-file-dropzone>
|
|
3528
|
+
* ```
|
|
3529
|
+
*/
|
|
3530
|
+
class FkFileDropzoneIconDirective {
|
|
3531
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FkFileDropzoneIconDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
3532
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: FkFileDropzoneIconDirective, isStandalone: true, selector: "[fkFileDropzoneIcon]", host: { attributes: { "aria-hidden": "true" } }, providers: [
|
|
3533
|
+
{
|
|
3534
|
+
provide: FK_FILE_DROPZONE_ICON,
|
|
3535
|
+
useExisting: FkFileDropzoneIconDirective,
|
|
3536
|
+
},
|
|
3537
|
+
], ngImport: i0 });
|
|
3538
|
+
}
|
|
3539
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FkFileDropzoneIconDirective, decorators: [{
|
|
3540
|
+
type: Directive,
|
|
3541
|
+
args: [{
|
|
3542
|
+
selector: '[fkFileDropzoneIcon]',
|
|
3543
|
+
standalone: true,
|
|
3544
|
+
providers: [
|
|
3545
|
+
{
|
|
3546
|
+
provide: FK_FILE_DROPZONE_ICON,
|
|
3547
|
+
useExisting: FkFileDropzoneIconDirective,
|
|
3548
|
+
},
|
|
3549
|
+
],
|
|
3550
|
+
host: {
|
|
3551
|
+
'aria-hidden': 'true',
|
|
3552
|
+
},
|
|
3553
|
+
}]
|
|
3554
|
+
}] });
|
|
3555
|
+
|
|
3506
3556
|
class SegmentedBarComponent {
|
|
3507
3557
|
// ===== INPUTS =====
|
|
3508
3558
|
/** Segments to render, each with a value, optional label, and color. */
|
|
@@ -3628,5 +3678,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
3628
3678
|
* Generated bundle index. Do not edit.
|
|
3629
3679
|
*/
|
|
3630
3680
|
|
|
3631
|
-
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 };
|
|
3681
|
+
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 };
|
|
3632
3682
|
//# sourceMappingURL=frame-kit-ui-ng-forms.mjs.map
|