@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,6 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { input, output, signal, viewChild, computed, HostBinding, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
-
import { IconComponent } from '@frame-kit/ui-ng/core/icon';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* A single-line text field that lives in two states:
|
|
@@ -104,11 +103,11 @@ class EditableFieldComponent {
|
|
|
104
103
|
this.editValue.set(target.value);
|
|
105
104
|
}
|
|
106
105
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EditableFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
107
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: EditableFieldComponent, isStandalone: true, selector: "fk-editable-field", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", 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 }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", editStart: "editStart", editCancel: "editCancel" }, host: { properties: { "class": "this.hostClass", "attr.id": "this.hostId" } }, viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (editing()) {\n <div class=\"fk-editable-field__container\">\n <div class=\"fk-editable-field__field fk-editable-field__field--editing\">\n <input\n #inputEl\n class=\"fk-editable-field__input\"\n type=\"text\"\n [value]=\"editValue()\"\n [placeholder]=\"placeholder()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n (input)=\"onInput($event)\"\n (keydown)=\"onKeydown($event)\"\n />\n\n <button\n class=\"fk-editable-field__inline-btn\"\n type=\"button\"\n aria-label=\"Cancel\"\n (click)=\"cancel()\"\n >\n <ng-content select=\"[cancelIcon]\">\n <fk-
|
|
106
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: EditableFieldComponent, isStandalone: true, selector: "fk-editable-field", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", 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 }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", editStart: "editStart", editCancel: "editCancel" }, host: { properties: { "class": "this.hostClass", "attr.id": "this.hostId" } }, viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (editing()) {\n <div class=\"fk-editable-field__container\">\n <div class=\"fk-editable-field__field fk-editable-field__field--editing\">\n <input\n #inputEl\n class=\"fk-editable-field__input\"\n type=\"text\"\n [value]=\"editValue()\"\n [placeholder]=\"placeholder()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n (input)=\"onInput($event)\"\n (keydown)=\"onKeydown($event)\"\n />\n\n <button\n class=\"fk-editable-field__inline-btn\"\n type=\"button\"\n aria-label=\"Cancel\"\n (click)=\"cancel()\"\n >\n <ng-content select=\"[cancelIcon]\">\n <svg\n class=\"fk-editable-field__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=\"M6 6l12 12M18 6L6 18\"\n stroke=\"currentColor\"\n stroke-width=\"1.9\"\n stroke-linecap=\"round\"\n />\n </svg>\n </ng-content>\n </button>\n </div>\n\n <button\n class=\"fk-editable-field__save\"\n type=\"button\"\n aria-label=\"Save\"\n (click)=\"save()\"\n >\n <ng-content select=\"[saveIcon]\">\n <span class=\"fk-editable-field__save-text\">Save</span>\n </ng-content>\n </button>\n </div>\n} @else {\n <button\n class=\"fk-editable-field__field fk-editable-field__field--display\"\n type=\"button\"\n [disabled]=\"disabled()\"\n [attr.aria-label]=\"ariaLabel() ? 'Edit ' + ariaLabel() : 'Edit'\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n (click)=\"startEdit()\"\n >\n <span class=\"fk-editable-field__value\">\n @if (value()) {\n {{ value() }}\n } @else {\n <span class=\"fk-editable-field__empty\">{{ emptyText() }}</span>\n }\n </span>\n\n @if (!disabled()) {\n <span\n class=\"fk-editable-field__inline-btn fk-editable-field__inline-btn--decoration\"\n >\n <ng-content select=\"[editIcon]\">\n <svg\n class=\"fk-editable-field__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=\"M4 20h4L18.5 9.5a2.1 2.1 0 0 0-3-3L5 17v3Z\"\n stroke=\"currentColor\"\n stroke-width=\"1.7\"\n stroke-linejoin=\"round\"\n />\n <path d=\"M13.5 6.5l3 3\" stroke=\"currentColor\" stroke-width=\"1.7\" />\n </svg>\n </ng-content>\n </span>\n }\n </button>\n}\n", styles: [":host{display:block}.fk-editable-field__container{display:flex;align-items:center;gap:var(--fk-editable-field-gap, var(--fk-rhythm-2, .5rem))}.fk-editable-field__field{flex:1;min-width:0;display:flex;align-items:center;width:100%;padding-right:var(--fk-editable-field-trailing-padding, var(--fk-rhythm-1, .25rem));font-family:inherit;text-align:start;background:var(--fk-editable-field-bg, var(--fk-color-surface, #ffffff));border:1px solid var(--fk-editable-field-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-editable-field-border-radius, var(--fk-radius-md, .375rem));transition:border-color .12s ease,box-shadow .12s ease}.fk-editable-field__field--display{cursor:pointer}.fk-editable-field__field--display:hover:not(:disabled){border-color:var(--fk-editable-field-hover-border, var(--fk-color-primary, #3b82f6))}.fk-editable-field__field--display:focus-visible{outline:none;border-color:var(--fk-editable-field-focus-border, var(--fk-color-primary, #3b82f6));box-shadow:var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18))}.fk-editable-field__field--display:disabled{cursor:default;opacity:var(--fk-editable-field-disabled-opacity, .6)}.fk-editable-field__field--editing:focus-within{border-color:var(--fk-editable-field-focus-border, var(--fk-color-primary, #3b82f6));box-shadow:var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18))}.fk-editable-field__input{flex:1;min-width:0;padding:var(--fk-editable-field-input-padding, var(--fk-rhythm-1, .25rem) var(--fk-rhythm-2, .5rem));font-family:inherit;font-size:var(--fk-editable-field-font-size, var(--fk-typography-body-font-size, .875rem));color:var(--fk-editable-field-color, var(--fk-color-text, #1f2d3d));background:transparent;border:none;outline:none}.fk-editable-field__value{flex:1;min-width:0;padding:var(--fk-editable-field-input-padding, var(--fk-rhythm-1, .25rem) var(--fk-rhythm-2, .5rem));font-size:var(--fk-editable-field-font-size, var(--fk-typography-body-font-size, .875rem));color:var(--fk-editable-field-color, var(--fk-color-text, #1f2d3d));overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fk-editable-field__empty{color:var(--fk-editable-field-empty-color, var(--fk-color-muted, #8a98a8))}.fk-editable-field__icon{width:var(--fk-editable-field-icon-size, 1rem);height:var(--fk-editable-field-icon-size, 1rem)}.fk-editable-field__inline-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--fk-editable-field-inline-btn-size, 1.5rem);height:var(--fk-editable-field-inline-btn-size, 1.5rem);padding:0;background:none;border:none;color:var(--fk-editable-field-trigger-color, var(--fk-color-muted, #8a98a8));cursor:pointer}.fk-editable-field__inline-btn:hover{color:var(--fk-editable-field-trigger-hover-color, var(--fk-color-primary, #3b82f6))}.fk-editable-field__inline-btn:focus-visible{outline:none;box-shadow:var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18));border-radius:var(--fk-radius-sm, .25rem)}.fk-editable-field__inline-btn--decoration{pointer-events:none;cursor:inherit}.fk-editable-field__save{display:inline-flex;align-items:center;flex-shrink:0;padding:var(--fk-rhythm-1, .25rem) var(--fk-rhythm-3, .75rem);font-family:inherit;font-size:var(--fk-editable-field-action-font-size, var(--fk-typography-small-font-size, .8125rem));font-weight:var(--fk-font-weight-medium, 500);color:var(--fk-editable-field-save-color, #ffffff);background:var(--fk-editable-field-save-bg, var(--fk-color-primary, #3b82f6));border:1px solid var(--fk-editable-field-save-bg, var(--fk-color-primary, #3b82f6));border-radius:var(--fk-editable-field-border-radius, var(--fk-radius-md, .375rem));cursor:pointer}.fk-editable-field__save:hover{opacity:.9}.fk-editable-field__save:focus-visible{outline:none;box-shadow:var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18))}.fk-editable-field__save-text{font:inherit}:host-context(.fk-editable-field--sm) .fk-editable-field__input,:host-context(.fk-editable-field--sm) .fk-editable-field__value{font-size:var(--fk-editable-field-sm-font-size, var(--fk-typography-small-font-size, .8125rem))}:host-context(.fk-editable-field--lg) .fk-editable-field__input,:host-context(.fk-editable-field--lg) .fk-editable-field__value{font-size:var(--fk-editable-field-lg-font-size, var(--fk-typography-heading-font-size, 1.25rem));font-weight:var(--fk-editable-field-lg-font-weight, var(--fk-font-weight-semibold, 600))}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
108
107
|
}
|
|
109
108
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EditableFieldComponent, decorators: [{
|
|
110
109
|
type: Component,
|
|
111
|
-
args: [{ selector: 'fk-editable-field', standalone: true, imports: [
|
|
110
|
+
args: [{ selector: 'fk-editable-field', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (editing()) {\n <div class=\"fk-editable-field__container\">\n <div class=\"fk-editable-field__field fk-editable-field__field--editing\">\n <input\n #inputEl\n class=\"fk-editable-field__input\"\n type=\"text\"\n [value]=\"editValue()\"\n [placeholder]=\"placeholder()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n (input)=\"onInput($event)\"\n (keydown)=\"onKeydown($event)\"\n />\n\n <button\n class=\"fk-editable-field__inline-btn\"\n type=\"button\"\n aria-label=\"Cancel\"\n (click)=\"cancel()\"\n >\n <ng-content select=\"[cancelIcon]\">\n <svg\n class=\"fk-editable-field__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=\"M6 6l12 12M18 6L6 18\"\n stroke=\"currentColor\"\n stroke-width=\"1.9\"\n stroke-linecap=\"round\"\n />\n </svg>\n </ng-content>\n </button>\n </div>\n\n <button\n class=\"fk-editable-field__save\"\n type=\"button\"\n aria-label=\"Save\"\n (click)=\"save()\"\n >\n <ng-content select=\"[saveIcon]\">\n <span class=\"fk-editable-field__save-text\">Save</span>\n </ng-content>\n </button>\n </div>\n} @else {\n <button\n class=\"fk-editable-field__field fk-editable-field__field--display\"\n type=\"button\"\n [disabled]=\"disabled()\"\n [attr.aria-label]=\"ariaLabel() ? 'Edit ' + ariaLabel() : 'Edit'\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n (click)=\"startEdit()\"\n >\n <span class=\"fk-editable-field__value\">\n @if (value()) {\n {{ value() }}\n } @else {\n <span class=\"fk-editable-field__empty\">{{ emptyText() }}</span>\n }\n </span>\n\n @if (!disabled()) {\n <span\n class=\"fk-editable-field__inline-btn fk-editable-field__inline-btn--decoration\"\n >\n <ng-content select=\"[editIcon]\">\n <svg\n class=\"fk-editable-field__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=\"M4 20h4L18.5 9.5a2.1 2.1 0 0 0-3-3L5 17v3Z\"\n stroke=\"currentColor\"\n stroke-width=\"1.7\"\n stroke-linejoin=\"round\"\n />\n <path d=\"M13.5 6.5l3 3\" stroke=\"currentColor\" stroke-width=\"1.7\" />\n </svg>\n </ng-content>\n </span>\n }\n </button>\n}\n", styles: [":host{display:block}.fk-editable-field__container{display:flex;align-items:center;gap:var(--fk-editable-field-gap, var(--fk-rhythm-2, .5rem))}.fk-editable-field__field{flex:1;min-width:0;display:flex;align-items:center;width:100%;padding-right:var(--fk-editable-field-trailing-padding, var(--fk-rhythm-1, .25rem));font-family:inherit;text-align:start;background:var(--fk-editable-field-bg, var(--fk-color-surface, #ffffff));border:1px solid var(--fk-editable-field-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-editable-field-border-radius, var(--fk-radius-md, .375rem));transition:border-color .12s ease,box-shadow .12s ease}.fk-editable-field__field--display{cursor:pointer}.fk-editable-field__field--display:hover:not(:disabled){border-color:var(--fk-editable-field-hover-border, var(--fk-color-primary, #3b82f6))}.fk-editable-field__field--display:focus-visible{outline:none;border-color:var(--fk-editable-field-focus-border, var(--fk-color-primary, #3b82f6));box-shadow:var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18))}.fk-editable-field__field--display:disabled{cursor:default;opacity:var(--fk-editable-field-disabled-opacity, .6)}.fk-editable-field__field--editing:focus-within{border-color:var(--fk-editable-field-focus-border, var(--fk-color-primary, #3b82f6));box-shadow:var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18))}.fk-editable-field__input{flex:1;min-width:0;padding:var(--fk-editable-field-input-padding, var(--fk-rhythm-1, .25rem) var(--fk-rhythm-2, .5rem));font-family:inherit;font-size:var(--fk-editable-field-font-size, var(--fk-typography-body-font-size, .875rem));color:var(--fk-editable-field-color, var(--fk-color-text, #1f2d3d));background:transparent;border:none;outline:none}.fk-editable-field__value{flex:1;min-width:0;padding:var(--fk-editable-field-input-padding, var(--fk-rhythm-1, .25rem) var(--fk-rhythm-2, .5rem));font-size:var(--fk-editable-field-font-size, var(--fk-typography-body-font-size, .875rem));color:var(--fk-editable-field-color, var(--fk-color-text, #1f2d3d));overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fk-editable-field__empty{color:var(--fk-editable-field-empty-color, var(--fk-color-muted, #8a98a8))}.fk-editable-field__icon{width:var(--fk-editable-field-icon-size, 1rem);height:var(--fk-editable-field-icon-size, 1rem)}.fk-editable-field__inline-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--fk-editable-field-inline-btn-size, 1.5rem);height:var(--fk-editable-field-inline-btn-size, 1.5rem);padding:0;background:none;border:none;color:var(--fk-editable-field-trigger-color, var(--fk-color-muted, #8a98a8));cursor:pointer}.fk-editable-field__inline-btn:hover{color:var(--fk-editable-field-trigger-hover-color, var(--fk-color-primary, #3b82f6))}.fk-editable-field__inline-btn:focus-visible{outline:none;box-shadow:var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18));border-radius:var(--fk-radius-sm, .25rem)}.fk-editable-field__inline-btn--decoration{pointer-events:none;cursor:inherit}.fk-editable-field__save{display:inline-flex;align-items:center;flex-shrink:0;padding:var(--fk-rhythm-1, .25rem) var(--fk-rhythm-3, .75rem);font-family:inherit;font-size:var(--fk-editable-field-action-font-size, var(--fk-typography-small-font-size, .8125rem));font-weight:var(--fk-font-weight-medium, 500);color:var(--fk-editable-field-save-color, #ffffff);background:var(--fk-editable-field-save-bg, var(--fk-color-primary, #3b82f6));border:1px solid var(--fk-editable-field-save-bg, var(--fk-color-primary, #3b82f6));border-radius:var(--fk-editable-field-border-radius, var(--fk-radius-md, .375rem));cursor:pointer}.fk-editable-field__save:hover{opacity:.9}.fk-editable-field__save:focus-visible{outline:none;box-shadow:var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18))}.fk-editable-field__save-text{font:inherit}:host-context(.fk-editable-field--sm) .fk-editable-field__input,:host-context(.fk-editable-field--sm) .fk-editable-field__value{font-size:var(--fk-editable-field-sm-font-size, var(--fk-typography-small-font-size, .8125rem))}:host-context(.fk-editable-field--lg) .fk-editable-field__input,:host-context(.fk-editable-field--lg) .fk-editable-field__value{font-size:var(--fk-editable-field-lg-font-size, var(--fk-typography-heading-font-size, 1.25rem));font-weight:var(--fk-editable-field-lg-font-weight, var(--fk-font-weight-semibold, 600))}\n"] }]
|
|
112
111
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", 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 }] }], ariaDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedBy", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], editStart: [{ type: i0.Output, args: ["editStart"] }], editCancel: [{ type: i0.Output, args: ["editCancel"] }], inputRef: [{ type: i0.ViewChild, args: ['inputEl', { isSignal: true }] }], hostClass: [{
|
|
113
112
|
type: HostBinding,
|
|
114
113
|
args: ['class']
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frame-kit-ui-ng-ui-editable-field.mjs","sources":["../../../../packages/ui-ng/ui/editable-field/editable-field.component.ts","../../../../packages/ui-ng/ui/editable-field/editable-field.component.html","../../../../packages/ui-ng/ui/editable-field/frame-kit-ui-ng-ui-editable-field.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n ElementRef,\n HostBinding,\n input,\n output,\n signal,\n viewChild,\n} from '@angular/core';\n\nimport { IconComponent } from '@frame-kit/ui-ng/core/icon';\nimport type { EditableFieldSize } from './editable-field.types';\n\n/**\n * A single-line text field that lives in two states:\n *\n * - **Display** — the field reads as a regular bordered input\n * showing the current value. A pencil icon sits inside the\n * trailing edge. Clicking anywhere on the field surface enters\n * edit mode.\n * - **Edit** — the field becomes a live `<input>`. The pencil slot\n * swaps to a cancel (✗) icon inside the trailing edge. A\n * separate Save button slides in as a sibling to the field's\n * right.\n *\n * Distinct from `fk-inline-edit`, which renders the value as a span +\n * an Edit button as siblings. `fk-editable-field` is meant for form-\n * shaped surfaces (billing details, profile pages) where every row\n * should *look* like a regular input even in display mode.\n *\n * The save / cancel / pencil icons can be overridden via the named\n * content slots `[editIcon]`, `[cancelIcon]`, and `[saveIcon]`.\n */\n@Component({\n selector: 'fk-editable-field',\n standalone: true,\n imports: [IconComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './editable-field.component.html',\n styleUrl: './editable-field.component.scss',\n})\nexport class EditableFieldComponent {\n // ===== INPUTS =====\n\n /** Current committed value displayed in read mode. */\n readonly value = input<string>('');\n /** Placeholder text shown in the input when the edit buffer is empty. */\n readonly placeholder = input<string>('Enter a value…');\n /** Size variant controlling the font and spacing of the component. */\n readonly size = input<EditableFieldSize>('md');\n /** Text displayed in read mode when the committed value is empty. */\n readonly emptyText = input<string>('None');\n\n // ===== BASE PROPS =====\n\n readonly className = input<string>('');\n readonly id = input<string | null>(null);\n readonly ariaLabel = input<string | null>(null);\n readonly ariaDescribedBy = input<string | null>(null);\n readonly disabled = input(false);\n\n // ===== OUTPUTS =====\n\n /** Fires when the user saves an edit, emitting the trimmed new value. */\n readonly valueChange = output<string>();\n /** Fires when the component enters edit mode. */\n readonly editStart = output<void>();\n /** Fires when the user cancels an in-progress edit without saving. */\n readonly editCancel = output<void>();\n\n // ===== STATE =====\n\n readonly editing = signal(false);\n readonly editValue = signal('');\n\n readonly inputRef = viewChild<ElementRef<HTMLInputElement>>('inputEl');\n\n // ===== COMPUTED =====\n\n readonly classes = computed(() =>\n [\n 'fk-editable-field',\n `fk-editable-field--${this.size()}`,\n this.editing() ? 'fk-editable-field--editing' : '',\n this.disabled() ? 'fk-editable-field--disabled' : '',\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() {\n return this.id();\n }\n\n // ===== METHODS =====\n\n /** Enters edit mode and focuses the input, copying the current value into the edit buffer. */\n startEdit(): void {\n if (this.disabled()) {\n return;\n }\n\n this.editValue.set(this.value());\n this.editing.set(true);\n this.editStart.emit();\n\n setTimeout(() => {\n this.inputRef()?.nativeElement.focus();\n });\n }\n\n /** Commits the current edit buffer, exits edit mode, and emits the trimmed value. */\n save(): void {\n const trimmed = this.editValue().trim();\n\n this.editing.set(false);\n this.valueChange.emit(trimmed);\n }\n\n /** Discards the current edit buffer and exits edit mode. */\n cancel(): void {\n this.editing.set(false);\n this.editCancel.emit();\n }\n\n onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Enter') {\n event.preventDefault();\n this.save();\n }\n\n if (event.key === 'Escape') {\n event.preventDefault();\n this.cancel();\n }\n }\n\n onInput(event: Event): void {\n const target = event.target as HTMLInputElement;\n\n this.editValue.set(target.value);\n }\n}\n","@if (editing()) {\n <div class=\"fk-editable-field__container\">\n <div class=\"fk-editable-field__field fk-editable-field__field--editing\">\n <input\n #inputEl\n class=\"fk-editable-field__input\"\n type=\"text\"\n [value]=\"editValue()\"\n [placeholder]=\"placeholder()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n (input)=\"onInput($event)\"\n (keydown)=\"onKeydown($event)\"\n />\n\n <button\n class=\"fk-editable-field__inline-btn\"\n type=\"button\"\n aria-label=\"Cancel\"\n (click)=\"cancel()\"\n >\n <ng-content select=\"[cancelIcon]\">\n <fk-icon name=\"circle-xmark-outline\" size=\"sm\" />\n </ng-content>\n </button>\n </div>\n\n <button\n class=\"fk-editable-field__save\"\n type=\"button\"\n aria-label=\"Save\"\n (click)=\"save()\"\n >\n <ng-content select=\"[saveIcon]\">\n <span class=\"fk-editable-field__save-text\">Save</span>\n </ng-content>\n </button>\n </div>\n} @else {\n <button\n class=\"fk-editable-field__field fk-editable-field__field--display\"\n type=\"button\"\n [disabled]=\"disabled()\"\n [attr.aria-label]=\"ariaLabel() ? 'Edit ' + ariaLabel() : 'Edit'\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n (click)=\"startEdit()\"\n >\n <span class=\"fk-editable-field__value\">\n @if (value()) {\n {{ value() }}\n } @else {\n <span class=\"fk-editable-field__empty\">{{ emptyText() }}</span>\n }\n </span>\n\n @if (!disabled()) {\n <span\n class=\"fk-editable-field__inline-btn fk-editable-field__inline-btn--decoration\"\n >\n <ng-content select=\"[editIcon]\">\n <fk-icon name=\"pen-outline\" size=\"sm\" />\n </ng-content>\n </span>\n }\n </button>\n}\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-editable-field.mjs","sources":["../../../../packages/ui-ng/ui/editable-field/editable-field.component.ts","../../../../packages/ui-ng/ui/editable-field/editable-field.component.html","../../../../packages/ui-ng/ui/editable-field/frame-kit-ui-ng-ui-editable-field.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n ElementRef,\n HostBinding,\n input,\n output,\n signal,\n viewChild,\n} from '@angular/core';\n\nimport type { EditableFieldSize } from './editable-field.types';\n\n/**\n * A single-line text field that lives in two states:\n *\n * - **Display** — the field reads as a regular bordered input\n * showing the current value. A pencil icon sits inside the\n * trailing edge. Clicking anywhere on the field surface enters\n * edit mode.\n * - **Edit** — the field becomes a live `<input>`. The pencil slot\n * swaps to a cancel (✗) icon inside the trailing edge. A\n * separate Save button slides in as a sibling to the field's\n * right.\n *\n * Distinct from `fk-inline-edit`, which renders the value as a span +\n * an Edit button as siblings. `fk-editable-field` is meant for form-\n * shaped surfaces (billing details, profile pages) where every row\n * should *look* like a regular input even in display mode.\n *\n * The save / cancel / pencil icons can be overridden via the named\n * content slots `[editIcon]`, `[cancelIcon]`, and `[saveIcon]`.\n */\n@Component({\n selector: 'fk-editable-field',\n standalone: true,\n imports: [],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './editable-field.component.html',\n styleUrl: './editable-field.component.scss',\n})\nexport class EditableFieldComponent {\n // ===== INPUTS =====\n\n /** Current committed value displayed in read mode. */\n readonly value = input<string>('');\n /** Placeholder text shown in the input when the edit buffer is empty. */\n readonly placeholder = input<string>('Enter a value…');\n /** Size variant controlling the font and spacing of the component. */\n readonly size = input<EditableFieldSize>('md');\n /** Text displayed in read mode when the committed value is empty. */\n readonly emptyText = input<string>('None');\n\n // ===== BASE PROPS =====\n\n readonly className = input<string>('');\n readonly id = input<string | null>(null);\n readonly ariaLabel = input<string | null>(null);\n readonly ariaDescribedBy = input<string | null>(null);\n readonly disabled = input(false);\n\n // ===== OUTPUTS =====\n\n /** Fires when the user saves an edit, emitting the trimmed new value. */\n readonly valueChange = output<string>();\n /** Fires when the component enters edit mode. */\n readonly editStart = output<void>();\n /** Fires when the user cancels an in-progress edit without saving. */\n readonly editCancel = output<void>();\n\n // ===== STATE =====\n\n readonly editing = signal(false);\n readonly editValue = signal('');\n\n readonly inputRef = viewChild<ElementRef<HTMLInputElement>>('inputEl');\n\n // ===== COMPUTED =====\n\n readonly classes = computed(() =>\n [\n 'fk-editable-field',\n `fk-editable-field--${this.size()}`,\n this.editing() ? 'fk-editable-field--editing' : '',\n this.disabled() ? 'fk-editable-field--disabled' : '',\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() {\n return this.id();\n }\n\n // ===== METHODS =====\n\n /** Enters edit mode and focuses the input, copying the current value into the edit buffer. */\n startEdit(): void {\n if (this.disabled()) {\n return;\n }\n\n this.editValue.set(this.value());\n this.editing.set(true);\n this.editStart.emit();\n\n setTimeout(() => {\n this.inputRef()?.nativeElement.focus();\n });\n }\n\n /** Commits the current edit buffer, exits edit mode, and emits the trimmed value. */\n save(): void {\n const trimmed = this.editValue().trim();\n\n this.editing.set(false);\n this.valueChange.emit(trimmed);\n }\n\n /** Discards the current edit buffer and exits edit mode. */\n cancel(): void {\n this.editing.set(false);\n this.editCancel.emit();\n }\n\n onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Enter') {\n event.preventDefault();\n this.save();\n }\n\n if (event.key === 'Escape') {\n event.preventDefault();\n this.cancel();\n }\n }\n\n onInput(event: Event): void {\n const target = event.target as HTMLInputElement;\n\n this.editValue.set(target.value);\n }\n}\n","@if (editing()) {\n <div class=\"fk-editable-field__container\">\n <div class=\"fk-editable-field__field fk-editable-field__field--editing\">\n <input\n #inputEl\n class=\"fk-editable-field__input\"\n type=\"text\"\n [value]=\"editValue()\"\n [placeholder]=\"placeholder()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n (input)=\"onInput($event)\"\n (keydown)=\"onKeydown($event)\"\n />\n\n <button\n class=\"fk-editable-field__inline-btn\"\n type=\"button\"\n aria-label=\"Cancel\"\n (click)=\"cancel()\"\n >\n <ng-content select=\"[cancelIcon]\">\n <svg\n class=\"fk-editable-field__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=\"M6 6l12 12M18 6L6 18\"\n stroke=\"currentColor\"\n stroke-width=\"1.9\"\n stroke-linecap=\"round\"\n />\n </svg>\n </ng-content>\n </button>\n </div>\n\n <button\n class=\"fk-editable-field__save\"\n type=\"button\"\n aria-label=\"Save\"\n (click)=\"save()\"\n >\n <ng-content select=\"[saveIcon]\">\n <span class=\"fk-editable-field__save-text\">Save</span>\n </ng-content>\n </button>\n </div>\n} @else {\n <button\n class=\"fk-editable-field__field fk-editable-field__field--display\"\n type=\"button\"\n [disabled]=\"disabled()\"\n [attr.aria-label]=\"ariaLabel() ? 'Edit ' + ariaLabel() : 'Edit'\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n (click)=\"startEdit()\"\n >\n <span class=\"fk-editable-field__value\">\n @if (value()) {\n {{ value() }}\n } @else {\n <span class=\"fk-editable-field__empty\">{{ emptyText() }}</span>\n }\n </span>\n\n @if (!disabled()) {\n <span\n class=\"fk-editable-field__inline-btn fk-editable-field__inline-btn--decoration\"\n >\n <ng-content select=\"[editIcon]\">\n <svg\n class=\"fk-editable-field__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=\"M4 20h4L18.5 9.5a2.1 2.1 0 0 0-3-3L5 17v3Z\"\n stroke=\"currentColor\"\n stroke-width=\"1.7\"\n stroke-linejoin=\"round\"\n />\n <path d=\"M13.5 6.5l3 3\" stroke=\"currentColor\" stroke-width=\"1.7\" />\n </svg>\n </ng-content>\n </span>\n }\n </button>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,6 @@ import * as i0 from '@angular/core';
|
|
|
3
3
|
import { model, input, output, signal, computed, HostBinding, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
4
4
|
import * as i1 from '@angular/forms';
|
|
5
5
|
import { FormsModule } from '@angular/forms';
|
|
6
|
-
import { IconComponent } from '@frame-kit/ui-ng/core/icon';
|
|
7
6
|
import { ButtonComponent, FkButtonIconStartDirective } from '@frame-kit/ui-ng/ui/button';
|
|
8
7
|
|
|
9
8
|
class ListEditorComponent {
|
|
@@ -108,7 +107,7 @@ class ListEditorComponent {
|
|
|
108
107
|
}
|
|
109
108
|
}
|
|
110
109
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ListEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
111
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: ListEditorComponent, isStandalone: true, selector: "fk-list-editor", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, addLabel: { classPropertyName: "addLabel", publicName: "addLabel", isSignal: true, isRequired: false, transformFunction: null }, orderable: { classPropertyName: "orderable", publicName: "orderable", isSignal: true, isRequired: false, transformFunction: null }, showOrder: { classPropertyName: "showOrder", publicName: "showOrder", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, lockedItems: { classPropertyName: "lockedItems", publicName: "lockedItems", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { items: "itemsChange", itemsChange: "itemsChange", itemAdded: "itemAdded", itemRemoved: "itemRemoved" }, host: { properties: { "class": "this.hostClass" } }, ngImport: i0, template: "<div\n cdkDropList\n [cdkDropListDisabled]=\"disabled() || !orderable()\"\n (cdkDropListDropped)=\"onDrop($event)\"\n class=\"fk-list-editor__list\"\n [attr.aria-label]=\"ariaLabel()\"\n>\n @for (item of items(); track $index) {\n <div\n cdkDrag\n [cdkDragDisabled]=\"disabled() || !orderable()\"\n class=\"fk-list-editor__item\"\n >\n @if (orderable()) {\n <span class=\"fk-list-editor__handle\" cdkDragHandle>\n <fk-icon name=\"dots-outline\" size=\"sm\" color=\"muted\" />\n </span>\n }\n\n @if (showOrder()) {\n <span class=\"fk-list-editor__order\">{{ $index + 1 }}</span>\n }\n\n <input\n class=\"fk-list-editor__input\"\n type=\"text\"\n [value]=\"item\"\n [disabled]=\"disabled() || isLocked(item)\"\n (input)=\"updateItem($index, $any($event.target).value)\"\n />\n\n <button\n class=\"fk-list-editor__remove\"\n type=\"button\"\n [disabled]=\"disabled() || isLocked(item)\"\n [title]=\"isLocked(item) ? 'This item cannot be removed' : 'Remove item'\"\n (click)=\"removeItem($index)\"\n >\n <fk-icon name=\"circle-xmark-outline\" size=\"sm\" />\n </button>\n\n <div *cdkDragPlaceholder class=\"fk-list-editor__placeholder\"></div>\n </div>\n }\n</div>\n\n@if (items().length === 0 && emptyMessage()) {\n <p class=\"fk-list-editor__empty\">{{ emptyMessage() }}</p>\n}\n\n<div class=\"fk-list-editor__add\">\n <div class=\"fk-list-editor__add-input\">\n <input\n class=\"fk-list-editor__input\"\n type=\"text\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [ngModel]=\"newItemValue()\"\n (ngModelChange)=\"newItemValue.set($event)\"\n (keydown)=\"onKeydown($event)\"\n />\n\n @if (newItemValue() && !disabled()) {\n <button\n class=\"fk-list-editor__add-clear\"\n type=\"button\"\n aria-label=\"Clear input\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"newItemValue.set('')\"\n >\n <fk-icon name=\"circle-xmark-outline\" size=\"sm\" />\n </button>\n }\n </div>\n\n <fk-button\n variant=\"outline\"\n size=\"sm\"\n [disabled]=\"!canAdd() || disabled()\"\n (click)=\"addItem()\"\n >\n <fk-icon name=\"add\" fkButtonIconStart />\n {{ addLabel() }}\n </fk-button>\n</div>\n\n@if (hasDuplicates()) {\n <p class=\"fk-list-editor__error\">Item names must be unique.</p>\n}\n", styles: [":host{display:block}.fk-list-editor__list{display:flex;flex-direction:column;gap:var(--fk-list-editor-row-gap, var(--fk-rhythm-2, .5rem))}.fk-list-editor__item{display:flex;align-items:center;gap:var(--fk-list-editor-row-gap, var(--fk-rhythm-2, .5rem));padding:var(--fk-list-editor-item-padding, var(--fk-rhythm-2, .5rem) var(--fk-rhythm-3, .75rem));background:var(--fk-list-editor-item-bg, var(--fk-color-surface, #ffffff));border:1px solid var(--fk-list-editor-item-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-list-editor-item-radius, var(--fk-radius-md, .5rem));transition:box-shadow .15s ease}.fk-list-editor__item:hover{box-shadow:var(--fk-list-editor-item-hover-shadow, 0 1px 3px rgba(0, 0, 0, .06))}.fk-list-editor__handle{display:flex;cursor:grab;padding:var(--fk-list-editor-handle-padding, var(--fk-rhythm-1, .25rem))}.fk-list-editor__handle:active{cursor:grabbing}.fk-list-editor__order{display:flex;align-items:center;justify-content:center;width:var(--fk-list-editor-order-size, 1.5rem);height:var(--fk-list-editor-order-size, 1.5rem);border-radius:var(--fk-list-editor-order-radius, 50%);background:var(--fk-list-editor-order-bg, var(--fk-color-primary-light, #e0f2fe));color:var(--fk-list-editor-order-color, var(--fk-color-primary, #0a84ff));font-size:var(--fk-list-editor-order-font-size, .75rem);font-weight:var(--fk-list-editor-order-font-weight, var(--fk-font-weight-semibold, 600));flex-shrink:0}.fk-list-editor__input{flex:1;min-width:0;padding:var(--fk-list-editor-input-padding, var(--fk-rhythm-2, .5rem) var(--fk-rhythm-3, .75rem));border:1px solid var(--fk-list-editor-input-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-list-editor-input-radius, var(--fk-radius-md, .5rem));font-size:var(--fk-list-editor-input-font-size, .875rem);color:var(--fk-list-editor-input-color, var(--fk-color-text, #1f2d3d));background:var(--fk-list-editor-input-bg, var(--fk-color-surface, #ffffff));outline:none;transition:border-color .15s ease}.fk-list-editor__input:focus{border-color:var(--fk-list-editor-input-focus-border-color, var(--fk-color-primary, #0a84ff))}.fk-list-editor__input:disabled{opacity:var(--fk-list-editor-disabled-opacity, var(--fk-input-disabled-opacity, .5));cursor:not-allowed}.fk-list-editor__remove{display:flex;align-items:center;padding:var(--fk-list-editor-remove-padding, var(--fk-rhythm-1, .25rem));border:none;background:transparent;cursor:pointer;color:var(--fk-list-editor-remove-color, var(--fk-color-muted, #8a98a8));transition:color .15s ease}.fk-list-editor__remove:hover:not(:disabled){color:var(--fk-list-editor-remove-hover-color, var(--fk-color-danger, #e02424))}.fk-list-editor__remove:focus-visible{outline:none;box-shadow:var(--fk-list-editor-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)))}.fk-list-editor__remove:disabled{opacity:.35;cursor:not-allowed}.fk-list-editor__placeholder{height:var(--fk-list-editor-placeholder-height, 3rem);border:2px dashed var(--fk-list-editor-placeholder-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-list-editor-item-radius, var(--fk-radius-md, .5rem));background:var(--fk-list-editor-placeholder-bg, var(--fk-color-surface-muted, #f7f9fb))}.fk-list-editor__empty{padding:var(--fk-list-editor-empty-padding, var(--fk-rhythm-4, 1rem));text-align:var(--fk-list-editor-empty-text-align, left);color:var(--fk-list-editor-empty-color, var(--fk-color-muted, #8a98a8));font-size:var(--fk-list-editor-empty-font-size, var(--fk-typography-small-font-size, .875rem))}.fk-list-editor__add{display:flex;align-items:center;gap:var(--fk-list-editor-row-gap, var(--fk-rhythm-2, .5rem));margin-top:var(--fk-list-editor-add-gap, var(--fk-rhythm-3, .75rem))}.fk-list-editor__add-input{position:relative;display:flex;flex:1;min-width:0}.fk-list-editor__add-input .fk-list-editor__input{padding-right:var(--fk-list-editor-add-clear-reserve, var(--fk-rhythm-7, 1.75rem))}.fk-list-editor__add-clear{position:absolute;top:50%;right:var(--fk-list-editor-add-clear-offset, var(--fk-rhythm-2, .5rem));transform:translateY(-50%);display:flex;align-items:center;justify-content:center;padding:var(--fk-list-editor-add-clear-padding, .125rem);border:0;background:transparent;border-radius:var(--fk-list-editor-add-clear-radius, var(--fk-radius-sm, .25rem));color:var(--fk-list-editor-remove-color, var(--fk-color-muted, #8a98a8));cursor:pointer;transition:color .15s ease}.fk-list-editor__add-clear:hover{color:var(--fk-list-editor-remove-hover-color, var(--fk-color-danger, #e02424))}.fk-list-editor__add-clear:focus-visible{outline:none;box-shadow:var(--fk-list-editor-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)))}.fk-list-editor__error{margin-top:var(--fk-list-editor-error-gap, var(--fk-rhythm-2, .5rem));color:var(--fk-list-editor-error-color, var(--fk-color-danger, #e02424));font-size:var(--fk-list-editor-error-font-size, var(--fk-typography-small-font-size, .875rem))}:host.fk-list-editor--sm .fk-list-editor__input{font-size:var(--fk-list-editor-input-font-size-sm, .8125rem);padding:var(--fk-list-editor-input-padding-sm, var(--fk-rhythm-1, .25rem) var(--fk-rhythm-2, .5rem))}:host.fk-list-editor--sm .fk-list-editor__item{padding:var(--fk-list-editor-item-padding-sm, var(--fk-rhythm-1, .25rem) var(--fk-rhythm-2, .5rem))}:host.fk-list-editor--disabled{opacity:var(--fk-list-editor-disabled-opacity, var(--fk-input-disabled-opacity, .5));pointer-events:none}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.fk-list-editor__list.cdk-drop-list-dragging .fk-list-editor__item:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drag-preview.fk-list-editor__item{box-shadow:var(--fk-list-editor-drag-shadow, 0 4px 12px rgba(0, 0, 0, .12));border-color:var(--fk-list-editor-drag-border-color, var(--fk-color-primary, #0a84ff))}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: CdkDragPlaceholder, selector: "ng-template[cdkDragPlaceholder]", inputs: ["data"] }, { kind: "component", type: ButtonComponent, selector: "fk-button", inputs: ["variant", "size", "loading", "disabled", "type", "fullWidth", "id", "className", "ariaLabel", "ariaDescribedBy"] }, { kind: "component", type: IconComponent, selector: "fk-icon", inputs: ["name", "size", "color", "className", "id", "ariaLabel", "ariaHidden"] }, { kind: "directive", type: FkButtonIconStartDirective, selector: "[fkButtonIconStart]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
110
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: ListEditorComponent, isStandalone: true, selector: "fk-list-editor", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, addLabel: { classPropertyName: "addLabel", publicName: "addLabel", isSignal: true, isRequired: false, transformFunction: null }, orderable: { classPropertyName: "orderable", publicName: "orderable", isSignal: true, isRequired: false, transformFunction: null }, showOrder: { classPropertyName: "showOrder", publicName: "showOrder", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, lockedItems: { classPropertyName: "lockedItems", publicName: "lockedItems", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { items: "itemsChange", itemsChange: "itemsChange", itemAdded: "itemAdded", itemRemoved: "itemRemoved" }, host: { properties: { "class": "this.hostClass" } }, ngImport: i0, template: "<div\n cdkDropList\n [cdkDropListDisabled]=\"disabled() || !orderable()\"\n (cdkDropListDropped)=\"onDrop($event)\"\n class=\"fk-list-editor__list\"\n [attr.aria-label]=\"ariaLabel()\"\n>\n @for (item of items(); track $index) {\n <div\n cdkDrag\n [cdkDragDisabled]=\"disabled() || !orderable()\"\n class=\"fk-list-editor__item\"\n >\n @if (orderable()) {\n <span class=\"fk-list-editor__handle\" cdkDragHandle>\n <svg\n class=\"fk-list-editor__icon\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <circle cx=\"9\" cy=\"6\" r=\"1.5\" fill=\"currentColor\" />\n <circle cx=\"15\" cy=\"6\" r=\"1.5\" fill=\"currentColor\" />\n <circle cx=\"9\" cy=\"12\" r=\"1.5\" fill=\"currentColor\" />\n <circle cx=\"15\" cy=\"12\" r=\"1.5\" fill=\"currentColor\" />\n <circle cx=\"9\" cy=\"18\" r=\"1.5\" fill=\"currentColor\" />\n <circle cx=\"15\" cy=\"18\" r=\"1.5\" fill=\"currentColor\" />\n </svg>\n </span>\n }\n\n @if (showOrder()) {\n <span class=\"fk-list-editor__order\">{{ $index + 1 }}</span>\n }\n\n <input\n class=\"fk-list-editor__input\"\n type=\"text\"\n [value]=\"item\"\n [disabled]=\"disabled() || isLocked(item)\"\n (input)=\"updateItem($index, $any($event.target).value)\"\n />\n\n <button\n class=\"fk-list-editor__remove\"\n type=\"button\"\n [disabled]=\"disabled() || isLocked(item)\"\n [title]=\"isLocked(item) ? 'This item cannot be removed' : 'Remove item'\"\n (click)=\"removeItem($index)\"\n >\n <svg\n class=\"fk-list-editor__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=\"M6 6l12 12M18 6L6 18\"\n stroke=\"currentColor\"\n stroke-width=\"1.9\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n\n <div *cdkDragPlaceholder class=\"fk-list-editor__placeholder\"></div>\n </div>\n }\n</div>\n\n@if (items().length === 0 && emptyMessage()) {\n <p class=\"fk-list-editor__empty\">{{ emptyMessage() }}</p>\n}\n\n<div class=\"fk-list-editor__add\">\n <div class=\"fk-list-editor__add-input\">\n <input\n class=\"fk-list-editor__input\"\n type=\"text\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [ngModel]=\"newItemValue()\"\n (ngModelChange)=\"newItemValue.set($event)\"\n (keydown)=\"onKeydown($event)\"\n />\n\n @if (newItemValue() && !disabled()) {\n <button\n class=\"fk-list-editor__add-clear\"\n type=\"button\"\n aria-label=\"Clear input\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"newItemValue.set('')\"\n >\n <svg\n class=\"fk-list-editor__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=\"M6 6l12 12M18 6L6 18\"\n stroke=\"currentColor\"\n stroke-width=\"1.9\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n }\n </div>\n\n <fk-button\n variant=\"outline\"\n size=\"sm\"\n [disabled]=\"!canAdd() || disabled()\"\n (click)=\"addItem()\"\n >\n <svg\n fkButtonIconStart\n class=\"fk-list-editor__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 5v14M5 12h14\"\n stroke=\"currentColor\"\n stroke-width=\"1.9\"\n stroke-linecap=\"round\"\n />\n </svg>\n {{ addLabel() }}\n </fk-button>\n</div>\n\n@if (hasDuplicates()) {\n <p class=\"fk-list-editor__error\">Item names must be unique.</p>\n}\n", styles: [":host{display:block}.fk-list-editor__list{display:flex;flex-direction:column;gap:var(--fk-list-editor-row-gap, var(--fk-rhythm-2, .5rem))}.fk-list-editor__item{display:flex;align-items:center;gap:var(--fk-list-editor-row-gap, var(--fk-rhythm-2, .5rem));padding:var(--fk-list-editor-item-padding, var(--fk-rhythm-2, .5rem) var(--fk-rhythm-3, .75rem));background:var(--fk-list-editor-item-bg, var(--fk-color-surface, #ffffff));border:1px solid var(--fk-list-editor-item-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-list-editor-item-radius, var(--fk-radius-md, .5rem));transition:box-shadow .15s ease}.fk-list-editor__item:hover{box-shadow:var(--fk-list-editor-item-hover-shadow, 0 1px 3px rgba(0, 0, 0, .06))}.fk-list-editor__icon{width:var(--fk-list-editor-icon-size, 1rem);height:var(--fk-list-editor-icon-size, 1rem)}.fk-list-editor__handle{display:flex;cursor:grab;color:var(--fk-list-editor-handle-color, var(--fk-color-muted, #8a98a8));padding:var(--fk-list-editor-handle-padding, var(--fk-rhythm-1, .25rem))}.fk-list-editor__handle:active{cursor:grabbing}.fk-list-editor__order{display:flex;align-items:center;justify-content:center;width:var(--fk-list-editor-order-size, 1.5rem);height:var(--fk-list-editor-order-size, 1.5rem);border-radius:var(--fk-list-editor-order-radius, 50%);background:var(--fk-list-editor-order-bg, var(--fk-color-primary-light, #e0f2fe));color:var(--fk-list-editor-order-color, var(--fk-color-primary, #0a84ff));font-size:var(--fk-list-editor-order-font-size, .75rem);font-weight:var(--fk-list-editor-order-font-weight, var(--fk-font-weight-semibold, 600));flex-shrink:0}.fk-list-editor__input{flex:1;min-width:0;padding:var(--fk-list-editor-input-padding, var(--fk-rhythm-2, .5rem) var(--fk-rhythm-3, .75rem));border:1px solid var(--fk-list-editor-input-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-list-editor-input-radius, var(--fk-radius-md, .5rem));font-size:var(--fk-list-editor-input-font-size, .875rem);color:var(--fk-list-editor-input-color, var(--fk-color-text, #1f2d3d));background:var(--fk-list-editor-input-bg, var(--fk-color-surface, #ffffff));outline:none;transition:border-color .15s ease}.fk-list-editor__input:focus{border-color:var(--fk-list-editor-input-focus-border-color, var(--fk-color-primary, #0a84ff))}.fk-list-editor__input:disabled{opacity:var(--fk-list-editor-disabled-opacity, var(--fk-input-disabled-opacity, .5));cursor:not-allowed}.fk-list-editor__remove{display:flex;align-items:center;padding:var(--fk-list-editor-remove-padding, var(--fk-rhythm-1, .25rem));border:none;background:transparent;cursor:pointer;color:var(--fk-list-editor-remove-color, var(--fk-color-muted, #8a98a8));transition:color .15s ease}.fk-list-editor__remove:hover:not(:disabled){color:var(--fk-list-editor-remove-hover-color, var(--fk-color-danger, #e02424))}.fk-list-editor__remove:focus-visible{outline:none;box-shadow:var(--fk-list-editor-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)))}.fk-list-editor__remove:disabled{opacity:.35;cursor:not-allowed}.fk-list-editor__placeholder{height:var(--fk-list-editor-placeholder-height, 3rem);border:2px dashed var(--fk-list-editor-placeholder-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-list-editor-item-radius, var(--fk-radius-md, .5rem));background:var(--fk-list-editor-placeholder-bg, var(--fk-color-surface-muted, #f7f9fb))}.fk-list-editor__empty{padding:var(--fk-list-editor-empty-padding, var(--fk-rhythm-4, 1rem));text-align:var(--fk-list-editor-empty-text-align, left);color:var(--fk-list-editor-empty-color, var(--fk-color-muted, #8a98a8));font-size:var(--fk-list-editor-empty-font-size, var(--fk-typography-small-font-size, .875rem))}.fk-list-editor__add{display:flex;align-items:center;gap:var(--fk-list-editor-row-gap, var(--fk-rhythm-2, .5rem));margin-top:var(--fk-list-editor-add-gap, var(--fk-rhythm-3, .75rem))}.fk-list-editor__add-input{position:relative;display:flex;flex:1;min-width:0}.fk-list-editor__add-input .fk-list-editor__input{padding-right:var(--fk-list-editor-add-clear-reserve, var(--fk-rhythm-7, 1.75rem))}.fk-list-editor__add-clear{position:absolute;top:50%;right:var(--fk-list-editor-add-clear-offset, var(--fk-rhythm-2, .5rem));transform:translateY(-50%);display:flex;align-items:center;justify-content:center;padding:var(--fk-list-editor-add-clear-padding, .125rem);border:0;background:transparent;border-radius:var(--fk-list-editor-add-clear-radius, var(--fk-radius-sm, .25rem));color:var(--fk-list-editor-remove-color, var(--fk-color-muted, #8a98a8));cursor:pointer;transition:color .15s ease}.fk-list-editor__add-clear:hover{color:var(--fk-list-editor-remove-hover-color, var(--fk-color-danger, #e02424))}.fk-list-editor__add-clear:focus-visible{outline:none;box-shadow:var(--fk-list-editor-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)))}.fk-list-editor__error{margin-top:var(--fk-list-editor-error-gap, var(--fk-rhythm-2, .5rem));color:var(--fk-list-editor-error-color, var(--fk-color-danger, #e02424));font-size:var(--fk-list-editor-error-font-size, var(--fk-typography-small-font-size, .875rem))}:host.fk-list-editor--sm .fk-list-editor__input{font-size:var(--fk-list-editor-input-font-size-sm, .8125rem);padding:var(--fk-list-editor-input-padding-sm, var(--fk-rhythm-1, .25rem) var(--fk-rhythm-2, .5rem))}:host.fk-list-editor--sm .fk-list-editor__item{padding:var(--fk-list-editor-item-padding-sm, var(--fk-rhythm-1, .25rem) var(--fk-rhythm-2, .5rem))}:host.fk-list-editor--disabled{opacity:var(--fk-list-editor-disabled-opacity, var(--fk-input-disabled-opacity, .5));pointer-events:none}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.fk-list-editor__list.cdk-drop-list-dragging .fk-list-editor__item:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drag-preview.fk-list-editor__item{box-shadow:var(--fk-list-editor-drag-shadow, 0 4px 12px rgba(0, 0, 0, .12));border-color:var(--fk-list-editor-drag-border-color, var(--fk-color-primary, #0a84ff))}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: CdkDragPlaceholder, selector: "ng-template[cdkDragPlaceholder]", inputs: ["data"] }, { kind: "component", type: ButtonComponent, selector: "fk-button", inputs: ["variant", "size", "loading", "disabled", "type", "fullWidth", "id", "className", "ariaLabel", "ariaDescribedBy"] }, { kind: "directive", type: FkButtonIconStartDirective, selector: "[fkButtonIconStart]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
112
111
|
}
|
|
113
112
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ListEditorComponent, decorators: [{
|
|
114
113
|
type: Component,
|
|
@@ -119,9 +118,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
119
118
|
CdkDragHandle,
|
|
120
119
|
CdkDragPlaceholder,
|
|
121
120
|
ButtonComponent,
|
|
122
|
-
IconComponent,
|
|
123
121
|
FkButtonIconStartDirective,
|
|
124
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n cdkDropList\n [cdkDropListDisabled]=\"disabled() || !orderable()\"\n (cdkDropListDropped)=\"onDrop($event)\"\n class=\"fk-list-editor__list\"\n [attr.aria-label]=\"ariaLabel()\"\n>\n @for (item of items(); track $index) {\n <div\n cdkDrag\n [cdkDragDisabled]=\"disabled() || !orderable()\"\n class=\"fk-list-editor__item\"\n >\n @if (orderable()) {\n <span class=\"fk-list-editor__handle\" cdkDragHandle>\n <fk-icon name=\"dots-outline\" size=\"sm\" color=\"muted\" />\n </span>\n }\n\n @if (showOrder()) {\n <span class=\"fk-list-editor__order\">{{ $index + 1 }}</span>\n }\n\n <input\n class=\"fk-list-editor__input\"\n type=\"text\"\n [value]=\"item\"\n [disabled]=\"disabled() || isLocked(item)\"\n (input)=\"updateItem($index, $any($event.target).value)\"\n />\n\n <button\n class=\"fk-list-editor__remove\"\n type=\"button\"\n [disabled]=\"disabled() || isLocked(item)\"\n [title]=\"isLocked(item) ? 'This item cannot be removed' : 'Remove item'\"\n (click)=\"removeItem($index)\"\n >\n <fk-icon name=\"circle-xmark-outline\" size=\"sm\" />\n </button>\n\n <div *cdkDragPlaceholder class=\"fk-list-editor__placeholder\"></div>\n </div>\n }\n</div>\n\n@if (items().length === 0 && emptyMessage()) {\n <p class=\"fk-list-editor__empty\">{{ emptyMessage() }}</p>\n}\n\n<div class=\"fk-list-editor__add\">\n <div class=\"fk-list-editor__add-input\">\n <input\n class=\"fk-list-editor__input\"\n type=\"text\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [ngModel]=\"newItemValue()\"\n (ngModelChange)=\"newItemValue.set($event)\"\n (keydown)=\"onKeydown($event)\"\n />\n\n @if (newItemValue() && !disabled()) {\n <button\n class=\"fk-list-editor__add-clear\"\n type=\"button\"\n aria-label=\"Clear input\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"newItemValue.set('')\"\n >\n <fk-icon name=\"circle-xmark-outline\" size=\"sm\" />\n </button>\n }\n </div>\n\n <fk-button\n variant=\"outline\"\n size=\"sm\"\n [disabled]=\"!canAdd() || disabled()\"\n (click)=\"addItem()\"\n >\n <fk-icon name=\"add\" fkButtonIconStart />\n {{ addLabel() }}\n </fk-button>\n</div>\n\n@if (hasDuplicates()) {\n <p class=\"fk-list-editor__error\">Item names must be unique.</p>\n}\n", styles: [":host{display:block}.fk-list-editor__list{display:flex;flex-direction:column;gap:var(--fk-list-editor-row-gap, var(--fk-rhythm-2, .5rem))}.fk-list-editor__item{display:flex;align-items:center;gap:var(--fk-list-editor-row-gap, var(--fk-rhythm-2, .5rem));padding:var(--fk-list-editor-item-padding, var(--fk-rhythm-2, .5rem) var(--fk-rhythm-3, .75rem));background:var(--fk-list-editor-item-bg, var(--fk-color-surface, #ffffff));border:1px solid var(--fk-list-editor-item-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-list-editor-item-radius, var(--fk-radius-md, .5rem));transition:box-shadow .15s ease}.fk-list-editor__item:hover{box-shadow:var(--fk-list-editor-item-hover-shadow, 0 1px 3px rgba(0, 0, 0, .06))}.fk-list-editor__handle{display:flex;cursor:grab;padding:var(--fk-list-editor-handle-padding, var(--fk-rhythm-1, .25rem))}.fk-list-editor__handle:active{cursor:grabbing}.fk-list-editor__order{display:flex;align-items:center;justify-content:center;width:var(--fk-list-editor-order-size, 1.5rem);height:var(--fk-list-editor-order-size, 1.5rem);border-radius:var(--fk-list-editor-order-radius, 50%);background:var(--fk-list-editor-order-bg, var(--fk-color-primary-light, #e0f2fe));color:var(--fk-list-editor-order-color, var(--fk-color-primary, #0a84ff));font-size:var(--fk-list-editor-order-font-size, .75rem);font-weight:var(--fk-list-editor-order-font-weight, var(--fk-font-weight-semibold, 600));flex-shrink:0}.fk-list-editor__input{flex:1;min-width:0;padding:var(--fk-list-editor-input-padding, var(--fk-rhythm-2, .5rem) var(--fk-rhythm-3, .75rem));border:1px solid var(--fk-list-editor-input-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-list-editor-input-radius, var(--fk-radius-md, .5rem));font-size:var(--fk-list-editor-input-font-size, .875rem);color:var(--fk-list-editor-input-color, var(--fk-color-text, #1f2d3d));background:var(--fk-list-editor-input-bg, var(--fk-color-surface, #ffffff));outline:none;transition:border-color .15s ease}.fk-list-editor__input:focus{border-color:var(--fk-list-editor-input-focus-border-color, var(--fk-color-primary, #0a84ff))}.fk-list-editor__input:disabled{opacity:var(--fk-list-editor-disabled-opacity, var(--fk-input-disabled-opacity, .5));cursor:not-allowed}.fk-list-editor__remove{display:flex;align-items:center;padding:var(--fk-list-editor-remove-padding, var(--fk-rhythm-1, .25rem));border:none;background:transparent;cursor:pointer;color:var(--fk-list-editor-remove-color, var(--fk-color-muted, #8a98a8));transition:color .15s ease}.fk-list-editor__remove:hover:not(:disabled){color:var(--fk-list-editor-remove-hover-color, var(--fk-color-danger, #e02424))}.fk-list-editor__remove:focus-visible{outline:none;box-shadow:var(--fk-list-editor-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)))}.fk-list-editor__remove:disabled{opacity:.35;cursor:not-allowed}.fk-list-editor__placeholder{height:var(--fk-list-editor-placeholder-height, 3rem);border:2px dashed var(--fk-list-editor-placeholder-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-list-editor-item-radius, var(--fk-radius-md, .5rem));background:var(--fk-list-editor-placeholder-bg, var(--fk-color-surface-muted, #f7f9fb))}.fk-list-editor__empty{padding:var(--fk-list-editor-empty-padding, var(--fk-rhythm-4, 1rem));text-align:var(--fk-list-editor-empty-text-align, left);color:var(--fk-list-editor-empty-color, var(--fk-color-muted, #8a98a8));font-size:var(--fk-list-editor-empty-font-size, var(--fk-typography-small-font-size, .875rem))}.fk-list-editor__add{display:flex;align-items:center;gap:var(--fk-list-editor-row-gap, var(--fk-rhythm-2, .5rem));margin-top:var(--fk-list-editor-add-gap, var(--fk-rhythm-3, .75rem))}.fk-list-editor__add-input{position:relative;display:flex;flex:1;min-width:0}.fk-list-editor__add-input .fk-list-editor__input{padding-right:var(--fk-list-editor-add-clear-reserve, var(--fk-rhythm-7, 1.75rem))}.fk-list-editor__add-clear{position:absolute;top:50%;right:var(--fk-list-editor-add-clear-offset, var(--fk-rhythm-2, .5rem));transform:translateY(-50%);display:flex;align-items:center;justify-content:center;padding:var(--fk-list-editor-add-clear-padding, .125rem);border:0;background:transparent;border-radius:var(--fk-list-editor-add-clear-radius, var(--fk-radius-sm, .25rem));color:var(--fk-list-editor-remove-color, var(--fk-color-muted, #8a98a8));cursor:pointer;transition:color .15s ease}.fk-list-editor__add-clear:hover{color:var(--fk-list-editor-remove-hover-color, var(--fk-color-danger, #e02424))}.fk-list-editor__add-clear:focus-visible{outline:none;box-shadow:var(--fk-list-editor-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)))}.fk-list-editor__error{margin-top:var(--fk-list-editor-error-gap, var(--fk-rhythm-2, .5rem));color:var(--fk-list-editor-error-color, var(--fk-color-danger, #e02424));font-size:var(--fk-list-editor-error-font-size, var(--fk-typography-small-font-size, .875rem))}:host.fk-list-editor--sm .fk-list-editor__input{font-size:var(--fk-list-editor-input-font-size-sm, .8125rem);padding:var(--fk-list-editor-input-padding-sm, var(--fk-rhythm-1, .25rem) var(--fk-rhythm-2, .5rem))}:host.fk-list-editor--sm .fk-list-editor__item{padding:var(--fk-list-editor-item-padding-sm, var(--fk-rhythm-1, .25rem) var(--fk-rhythm-2, .5rem))}:host.fk-list-editor--disabled{opacity:var(--fk-list-editor-disabled-opacity, var(--fk-input-disabled-opacity, .5));pointer-events:none}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.fk-list-editor__list.cdk-drop-list-dragging .fk-list-editor__item:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drag-preview.fk-list-editor__item{box-shadow:var(--fk-list-editor-drag-shadow, 0 4px 12px rgba(0, 0, 0, .12));border-color:var(--fk-list-editor-drag-border-color, var(--fk-color-primary, #0a84ff))}\n"] }]
|
|
122
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n cdkDropList\n [cdkDropListDisabled]=\"disabled() || !orderable()\"\n (cdkDropListDropped)=\"onDrop($event)\"\n class=\"fk-list-editor__list\"\n [attr.aria-label]=\"ariaLabel()\"\n>\n @for (item of items(); track $index) {\n <div\n cdkDrag\n [cdkDragDisabled]=\"disabled() || !orderable()\"\n class=\"fk-list-editor__item\"\n >\n @if (orderable()) {\n <span class=\"fk-list-editor__handle\" cdkDragHandle>\n <svg\n class=\"fk-list-editor__icon\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <circle cx=\"9\" cy=\"6\" r=\"1.5\" fill=\"currentColor\" />\n <circle cx=\"15\" cy=\"6\" r=\"1.5\" fill=\"currentColor\" />\n <circle cx=\"9\" cy=\"12\" r=\"1.5\" fill=\"currentColor\" />\n <circle cx=\"15\" cy=\"12\" r=\"1.5\" fill=\"currentColor\" />\n <circle cx=\"9\" cy=\"18\" r=\"1.5\" fill=\"currentColor\" />\n <circle cx=\"15\" cy=\"18\" r=\"1.5\" fill=\"currentColor\" />\n </svg>\n </span>\n }\n\n @if (showOrder()) {\n <span class=\"fk-list-editor__order\">{{ $index + 1 }}</span>\n }\n\n <input\n class=\"fk-list-editor__input\"\n type=\"text\"\n [value]=\"item\"\n [disabled]=\"disabled() || isLocked(item)\"\n (input)=\"updateItem($index, $any($event.target).value)\"\n />\n\n <button\n class=\"fk-list-editor__remove\"\n type=\"button\"\n [disabled]=\"disabled() || isLocked(item)\"\n [title]=\"isLocked(item) ? 'This item cannot be removed' : 'Remove item'\"\n (click)=\"removeItem($index)\"\n >\n <svg\n class=\"fk-list-editor__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=\"M6 6l12 12M18 6L6 18\"\n stroke=\"currentColor\"\n stroke-width=\"1.9\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n\n <div *cdkDragPlaceholder class=\"fk-list-editor__placeholder\"></div>\n </div>\n }\n</div>\n\n@if (items().length === 0 && emptyMessage()) {\n <p class=\"fk-list-editor__empty\">{{ emptyMessage() }}</p>\n}\n\n<div class=\"fk-list-editor__add\">\n <div class=\"fk-list-editor__add-input\">\n <input\n class=\"fk-list-editor__input\"\n type=\"text\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [ngModel]=\"newItemValue()\"\n (ngModelChange)=\"newItemValue.set($event)\"\n (keydown)=\"onKeydown($event)\"\n />\n\n @if (newItemValue() && !disabled()) {\n <button\n class=\"fk-list-editor__add-clear\"\n type=\"button\"\n aria-label=\"Clear input\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"newItemValue.set('')\"\n >\n <svg\n class=\"fk-list-editor__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=\"M6 6l12 12M18 6L6 18\"\n stroke=\"currentColor\"\n stroke-width=\"1.9\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n }\n </div>\n\n <fk-button\n variant=\"outline\"\n size=\"sm\"\n [disabled]=\"!canAdd() || disabled()\"\n (click)=\"addItem()\"\n >\n <svg\n fkButtonIconStart\n class=\"fk-list-editor__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 5v14M5 12h14\"\n stroke=\"currentColor\"\n stroke-width=\"1.9\"\n stroke-linecap=\"round\"\n />\n </svg>\n {{ addLabel() }}\n </fk-button>\n</div>\n\n@if (hasDuplicates()) {\n <p class=\"fk-list-editor__error\">Item names must be unique.</p>\n}\n", styles: [":host{display:block}.fk-list-editor__list{display:flex;flex-direction:column;gap:var(--fk-list-editor-row-gap, var(--fk-rhythm-2, .5rem))}.fk-list-editor__item{display:flex;align-items:center;gap:var(--fk-list-editor-row-gap, var(--fk-rhythm-2, .5rem));padding:var(--fk-list-editor-item-padding, var(--fk-rhythm-2, .5rem) var(--fk-rhythm-3, .75rem));background:var(--fk-list-editor-item-bg, var(--fk-color-surface, #ffffff));border:1px solid var(--fk-list-editor-item-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-list-editor-item-radius, var(--fk-radius-md, .5rem));transition:box-shadow .15s ease}.fk-list-editor__item:hover{box-shadow:var(--fk-list-editor-item-hover-shadow, 0 1px 3px rgba(0, 0, 0, .06))}.fk-list-editor__icon{width:var(--fk-list-editor-icon-size, 1rem);height:var(--fk-list-editor-icon-size, 1rem)}.fk-list-editor__handle{display:flex;cursor:grab;color:var(--fk-list-editor-handle-color, var(--fk-color-muted, #8a98a8));padding:var(--fk-list-editor-handle-padding, var(--fk-rhythm-1, .25rem))}.fk-list-editor__handle:active{cursor:grabbing}.fk-list-editor__order{display:flex;align-items:center;justify-content:center;width:var(--fk-list-editor-order-size, 1.5rem);height:var(--fk-list-editor-order-size, 1.5rem);border-radius:var(--fk-list-editor-order-radius, 50%);background:var(--fk-list-editor-order-bg, var(--fk-color-primary-light, #e0f2fe));color:var(--fk-list-editor-order-color, var(--fk-color-primary, #0a84ff));font-size:var(--fk-list-editor-order-font-size, .75rem);font-weight:var(--fk-list-editor-order-font-weight, var(--fk-font-weight-semibold, 600));flex-shrink:0}.fk-list-editor__input{flex:1;min-width:0;padding:var(--fk-list-editor-input-padding, var(--fk-rhythm-2, .5rem) var(--fk-rhythm-3, .75rem));border:1px solid var(--fk-list-editor-input-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-list-editor-input-radius, var(--fk-radius-md, .5rem));font-size:var(--fk-list-editor-input-font-size, .875rem);color:var(--fk-list-editor-input-color, var(--fk-color-text, #1f2d3d));background:var(--fk-list-editor-input-bg, var(--fk-color-surface, #ffffff));outline:none;transition:border-color .15s ease}.fk-list-editor__input:focus{border-color:var(--fk-list-editor-input-focus-border-color, var(--fk-color-primary, #0a84ff))}.fk-list-editor__input:disabled{opacity:var(--fk-list-editor-disabled-opacity, var(--fk-input-disabled-opacity, .5));cursor:not-allowed}.fk-list-editor__remove{display:flex;align-items:center;padding:var(--fk-list-editor-remove-padding, var(--fk-rhythm-1, .25rem));border:none;background:transparent;cursor:pointer;color:var(--fk-list-editor-remove-color, var(--fk-color-muted, #8a98a8));transition:color .15s ease}.fk-list-editor__remove:hover:not(:disabled){color:var(--fk-list-editor-remove-hover-color, var(--fk-color-danger, #e02424))}.fk-list-editor__remove:focus-visible{outline:none;box-shadow:var(--fk-list-editor-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)))}.fk-list-editor__remove:disabled{opacity:.35;cursor:not-allowed}.fk-list-editor__placeholder{height:var(--fk-list-editor-placeholder-height, 3rem);border:2px dashed var(--fk-list-editor-placeholder-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-list-editor-item-radius, var(--fk-radius-md, .5rem));background:var(--fk-list-editor-placeholder-bg, var(--fk-color-surface-muted, #f7f9fb))}.fk-list-editor__empty{padding:var(--fk-list-editor-empty-padding, var(--fk-rhythm-4, 1rem));text-align:var(--fk-list-editor-empty-text-align, left);color:var(--fk-list-editor-empty-color, var(--fk-color-muted, #8a98a8));font-size:var(--fk-list-editor-empty-font-size, var(--fk-typography-small-font-size, .875rem))}.fk-list-editor__add{display:flex;align-items:center;gap:var(--fk-list-editor-row-gap, var(--fk-rhythm-2, .5rem));margin-top:var(--fk-list-editor-add-gap, var(--fk-rhythm-3, .75rem))}.fk-list-editor__add-input{position:relative;display:flex;flex:1;min-width:0}.fk-list-editor__add-input .fk-list-editor__input{padding-right:var(--fk-list-editor-add-clear-reserve, var(--fk-rhythm-7, 1.75rem))}.fk-list-editor__add-clear{position:absolute;top:50%;right:var(--fk-list-editor-add-clear-offset, var(--fk-rhythm-2, .5rem));transform:translateY(-50%);display:flex;align-items:center;justify-content:center;padding:var(--fk-list-editor-add-clear-padding, .125rem);border:0;background:transparent;border-radius:var(--fk-list-editor-add-clear-radius, var(--fk-radius-sm, .25rem));color:var(--fk-list-editor-remove-color, var(--fk-color-muted, #8a98a8));cursor:pointer;transition:color .15s ease}.fk-list-editor__add-clear:hover{color:var(--fk-list-editor-remove-hover-color, var(--fk-color-danger, #e02424))}.fk-list-editor__add-clear:focus-visible{outline:none;box-shadow:var(--fk-list-editor-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)))}.fk-list-editor__error{margin-top:var(--fk-list-editor-error-gap, var(--fk-rhythm-2, .5rem));color:var(--fk-list-editor-error-color, var(--fk-color-danger, #e02424));font-size:var(--fk-list-editor-error-font-size, var(--fk-typography-small-font-size, .875rem))}:host.fk-list-editor--sm .fk-list-editor__input{font-size:var(--fk-list-editor-input-font-size-sm, .8125rem);padding:var(--fk-list-editor-input-padding-sm, var(--fk-rhythm-1, .25rem) var(--fk-rhythm-2, .5rem))}:host.fk-list-editor--sm .fk-list-editor__item{padding:var(--fk-list-editor-item-padding-sm, var(--fk-rhythm-1, .25rem) var(--fk-rhythm-2, .5rem))}:host.fk-list-editor--disabled{opacity:var(--fk-list-editor-disabled-opacity, var(--fk-input-disabled-opacity, .5));pointer-events:none}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.fk-list-editor__list.cdk-drop-list-dragging .fk-list-editor__item:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drag-preview.fk-list-editor__item{box-shadow:var(--fk-list-editor-drag-shadow, 0 4px 12px rgba(0, 0, 0, .12));border-color:var(--fk-list-editor-drag-border-color, var(--fk-color-primary, #0a84ff))}\n"] }]
|
|
125
123
|
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }, { type: i0.Output, args: ["itemsChange"] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], addLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "addLabel", required: false }] }], orderable: [{ type: i0.Input, args: [{ isSignal: true, alias: "orderable", required: false }] }], showOrder: [{ type: i0.Input, args: [{ isSignal: true, alias: "showOrder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], lockedItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "lockedItems", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], itemsChange: [{ type: i0.Output, args: ["itemsChange"] }], itemAdded: [{ type: i0.Output, args: ["itemAdded"] }], itemRemoved: [{ type: i0.Output, args: ["itemRemoved"] }], hostClass: [{
|
|
126
124
|
type: HostBinding,
|
|
127
125
|
args: ['class']
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frame-kit-ui-ng-ui-list-editor.mjs","sources":["../../../../packages/ui-ng/ui/list-editor/list-editor.component.ts","../../../../packages/ui-ng/ui/list-editor/list-editor.component.html","../../../../packages/ui-ng/ui/list-editor/frame-kit-ui-ng-ui-list-editor.ts"],"sourcesContent":["import {\n CdkDrag,\n CdkDragDrop,\n CdkDragHandle,\n CdkDragPlaceholder,\n CdkDropList,\n moveItemInArray,\n} from '@angular/cdk/drag-drop';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n model,\n output,\n signal,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\n\nimport { IconComponent } from '@frame-kit/ui-ng/core/icon';\nimport { ButtonComponent } from '@frame-kit/ui-ng/ui/button';\nimport { FkButtonIconStartDirective } from '@frame-kit/ui-ng/ui/button';\nimport type { ListEditorSize } from './list-editor.types';\n\n@Component({\n selector: 'fk-list-editor',\n standalone: true,\n imports: [\n FormsModule,\n CdkDropList,\n CdkDrag,\n CdkDragHandle,\n CdkDragPlaceholder,\n ButtonComponent,\n IconComponent,\n FkButtonIconStartDirective,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './list-editor.component.html',\n styleUrl: './list-editor.component.scss',\n})\nexport class ListEditorComponent {\n // ===== INPUTS =====\n /** The current list of string items; two-way bindable via `[(items)]`. */\n readonly items = model<string[]>([]);\n /** Placeholder text for the new-item input field. */\n readonly placeholder = input('Add an item...');\n /** Message displayed when the list is empty. */\n readonly emptyMessage = input('No items added yet.');\n /** Label for the add button. */\n readonly addLabel = input('Add');\n /** When true, items can be reordered via drag-and-drop. */\n readonly orderable = input(true);\n /** When true, shows a numeric position indicator next to each item. */\n readonly showOrder = input(true);\n /** Size variant controlling the spacing and font of the component. */\n readonly size = input<ListEditorSize>('md');\n /** Items that cannot be removed by the user (matched case-insensitively). */\n readonly lockedItems = input<string[]>([]);\n\n // ===== BASE PROPS =====\n readonly className = input<string>('');\n readonly disabled = input(false);\n readonly ariaLabel = input<string | null>(null);\n\n // ===== OUTPUTS =====\n /** Fires whenever the items array changes, emitting the full updated array. */\n readonly itemsChange = output<string[]>();\n /** Fires when a new item is successfully added, emitting the added value. */\n readonly itemAdded = output<string>();\n /** Fires when an item is removed, emitting the removed value and its former index. */\n readonly itemRemoved = output<{ item: string; index: number }>();\n\n // ===== LOCAL STATE =====\n readonly newItemValue = signal('');\n\n // ===== COMPUTED =====\n readonly canAdd = computed(() => {\n const value = this.newItemValue().trim();\n\n if (!value) {\n return false;\n }\n\n const existing = this.items().map((n) => n.trim().toLowerCase());\n\n return !existing.includes(value.toLowerCase());\n });\n\n readonly hasDuplicates = computed(() => {\n const names = this.items().map((n) => n.trim().toLowerCase());\n\n return new Set(names).size !== names.length;\n });\n\n readonly hasEmptyItems = computed(() => {\n return this.items().some((n) => n.trim() === '');\n });\n\n readonly classes = computed(() =>\n [\n 'fk-list-editor',\n `fk-list-editor--${this.size()}`,\n this.disabled() ? 'fk-list-editor--disabled' : '',\n this.className(),\n ]\n .filter(Boolean)\n .join(' '),\n );\n\n @HostBinding('class')\n get hostClass() {\n return this.classes();\n }\n\n // ===== ACTIONS =====\n\n /** Adds the current input value as a new item if it is non-empty and not a duplicate. */\n addItem(): void {\n const value = this.newItemValue().trim();\n\n if (!value || !this.canAdd() || this.disabled()) {\n return;\n }\n\n this.items.update((prev) => [...prev, value]);\n this.newItemValue.set('');\n this.itemsChange.emit(this.items());\n this.itemAdded.emit(value);\n }\n\n /** Removes the item at the given index unless it is locked or the component is disabled. */\n removeItem(index: number): void {\n const item = this.items()[index];\n\n if (this.disabled() || this.isLocked(item)) {\n return;\n }\n\n this.items.update((prev) => prev.filter((_, i) => i !== index));\n this.itemsChange.emit(this.items());\n this.itemRemoved.emit({ item, index });\n }\n\n /** Updates the item at the given index with a new value and emits the changed array. */\n updateItem(index: number, value: string): void {\n this.items.update((prev) =>\n prev.map((item, i) => (i === index ? value : item)),\n );\n this.itemsChange.emit(this.items());\n }\n\n onDrop(event: CdkDragDrop<string[]>): void {\n const updated = [...this.items()];\n\n moveItemInArray(updated, event.previousIndex, event.currentIndex);\n this.items.set(updated);\n this.itemsChange.emit(this.items());\n }\n\n /** Returns true if the given item matches any entry in `lockedItems`. */\n isLocked(item: string): boolean {\n return this.lockedItems().includes(item.trim().toLowerCase());\n }\n\n onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Enter') {\n event.preventDefault();\n this.addItem();\n }\n }\n}\n","<div\n cdkDropList\n [cdkDropListDisabled]=\"disabled() || !orderable()\"\n (cdkDropListDropped)=\"onDrop($event)\"\n class=\"fk-list-editor__list\"\n [attr.aria-label]=\"ariaLabel()\"\n>\n @for (item of items(); track $index) {\n <div\n cdkDrag\n [cdkDragDisabled]=\"disabled() || !orderable()\"\n class=\"fk-list-editor__item\"\n >\n @if (orderable()) {\n <span class=\"fk-list-editor__handle\" cdkDragHandle>\n <fk-icon name=\"dots-outline\" size=\"sm\" color=\"muted\" />\n </span>\n }\n\n @if (showOrder()) {\n <span class=\"fk-list-editor__order\">{{ $index + 1 }}</span>\n }\n\n <input\n class=\"fk-list-editor__input\"\n type=\"text\"\n [value]=\"item\"\n [disabled]=\"disabled() || isLocked(item)\"\n (input)=\"updateItem($index, $any($event.target).value)\"\n />\n\n <button\n class=\"fk-list-editor__remove\"\n type=\"button\"\n [disabled]=\"disabled() || isLocked(item)\"\n [title]=\"isLocked(item) ? 'This item cannot be removed' : 'Remove item'\"\n (click)=\"removeItem($index)\"\n >\n <fk-icon name=\"circle-xmark-outline\" size=\"sm\" />\n </button>\n\n <div *cdkDragPlaceholder class=\"fk-list-editor__placeholder\"></div>\n </div>\n }\n</div>\n\n@if (items().length === 0 && emptyMessage()) {\n <p class=\"fk-list-editor__empty\">{{ emptyMessage() }}</p>\n}\n\n<div class=\"fk-list-editor__add\">\n <div class=\"fk-list-editor__add-input\">\n <input\n class=\"fk-list-editor__input\"\n type=\"text\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [ngModel]=\"newItemValue()\"\n (ngModelChange)=\"newItemValue.set($event)\"\n (keydown)=\"onKeydown($event)\"\n />\n\n @if (newItemValue() && !disabled()) {\n <button\n class=\"fk-list-editor__add-clear\"\n type=\"button\"\n aria-label=\"Clear input\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"newItemValue.set('')\"\n >\n <fk-icon name=\"circle-xmark-outline\" size=\"sm\" />\n </button>\n }\n </div>\n\n <fk-button\n variant=\"outline\"\n size=\"sm\"\n [disabled]=\"!canAdd() || disabled()\"\n (click)=\"addItem()\"\n >\n <fk-icon name=\"add\" fkButtonIconStart />\n {{ addLabel() }}\n </fk-button>\n</div>\n\n@if (hasDuplicates()) {\n <p class=\"fk-list-editor__error\">Item names must be unique.</p>\n}\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-list-editor.mjs","sources":["../../../../packages/ui-ng/ui/list-editor/list-editor.component.ts","../../../../packages/ui-ng/ui/list-editor/list-editor.component.html","../../../../packages/ui-ng/ui/list-editor/frame-kit-ui-ng-ui-list-editor.ts"],"sourcesContent":["import {\n CdkDrag,\n CdkDragDrop,\n CdkDragHandle,\n CdkDragPlaceholder,\n CdkDropList,\n moveItemInArray,\n} from '@angular/cdk/drag-drop';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n model,\n output,\n signal,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\n\nimport { ButtonComponent } from '@frame-kit/ui-ng/ui/button';\nimport { FkButtonIconStartDirective } from '@frame-kit/ui-ng/ui/button';\nimport type { ListEditorSize } from './list-editor.types';\n\n@Component({\n selector: 'fk-list-editor',\n standalone: true,\n imports: [\n FormsModule,\n CdkDropList,\n CdkDrag,\n CdkDragHandle,\n CdkDragPlaceholder,\n ButtonComponent,\n FkButtonIconStartDirective,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './list-editor.component.html',\n styleUrl: './list-editor.component.scss',\n})\nexport class ListEditorComponent {\n // ===== INPUTS =====\n /** The current list of string items; two-way bindable via `[(items)]`. */\n readonly items = model<string[]>([]);\n /** Placeholder text for the new-item input field. */\n readonly placeholder = input('Add an item...');\n /** Message displayed when the list is empty. */\n readonly emptyMessage = input('No items added yet.');\n /** Label for the add button. */\n readonly addLabel = input('Add');\n /** When true, items can be reordered via drag-and-drop. */\n readonly orderable = input(true);\n /** When true, shows a numeric position indicator next to each item. */\n readonly showOrder = input(true);\n /** Size variant controlling the spacing and font of the component. */\n readonly size = input<ListEditorSize>('md');\n /** Items that cannot be removed by the user (matched case-insensitively). */\n readonly lockedItems = input<string[]>([]);\n\n // ===== BASE PROPS =====\n readonly className = input<string>('');\n readonly disabled = input(false);\n readonly ariaLabel = input<string | null>(null);\n\n // ===== OUTPUTS =====\n /** Fires whenever the items array changes, emitting the full updated array. */\n readonly itemsChange = output<string[]>();\n /** Fires when a new item is successfully added, emitting the added value. */\n readonly itemAdded = output<string>();\n /** Fires when an item is removed, emitting the removed value and its former index. */\n readonly itemRemoved = output<{ item: string; index: number }>();\n\n // ===== LOCAL STATE =====\n readonly newItemValue = signal('');\n\n // ===== COMPUTED =====\n readonly canAdd = computed(() => {\n const value = this.newItemValue().trim();\n\n if (!value) {\n return false;\n }\n\n const existing = this.items().map((n) => n.trim().toLowerCase());\n\n return !existing.includes(value.toLowerCase());\n });\n\n readonly hasDuplicates = computed(() => {\n const names = this.items().map((n) => n.trim().toLowerCase());\n\n return new Set(names).size !== names.length;\n });\n\n readonly hasEmptyItems = computed(() => {\n return this.items().some((n) => n.trim() === '');\n });\n\n readonly classes = computed(() =>\n [\n 'fk-list-editor',\n `fk-list-editor--${this.size()}`,\n this.disabled() ? 'fk-list-editor--disabled' : '',\n this.className(),\n ]\n .filter(Boolean)\n .join(' '),\n );\n\n @HostBinding('class')\n get hostClass() {\n return this.classes();\n }\n\n // ===== ACTIONS =====\n\n /** Adds the current input value as a new item if it is non-empty and not a duplicate. */\n addItem(): void {\n const value = this.newItemValue().trim();\n\n if (!value || !this.canAdd() || this.disabled()) {\n return;\n }\n\n this.items.update((prev) => [...prev, value]);\n this.newItemValue.set('');\n this.itemsChange.emit(this.items());\n this.itemAdded.emit(value);\n }\n\n /** Removes the item at the given index unless it is locked or the component is disabled. */\n removeItem(index: number): void {\n const item = this.items()[index];\n\n if (this.disabled() || this.isLocked(item)) {\n return;\n }\n\n this.items.update((prev) => prev.filter((_, i) => i !== index));\n this.itemsChange.emit(this.items());\n this.itemRemoved.emit({ item, index });\n }\n\n /** Updates the item at the given index with a new value and emits the changed array. */\n updateItem(index: number, value: string): void {\n this.items.update((prev) =>\n prev.map((item, i) => (i === index ? value : item)),\n );\n this.itemsChange.emit(this.items());\n }\n\n onDrop(event: CdkDragDrop<string[]>): void {\n const updated = [...this.items()];\n\n moveItemInArray(updated, event.previousIndex, event.currentIndex);\n this.items.set(updated);\n this.itemsChange.emit(this.items());\n }\n\n /** Returns true if the given item matches any entry in `lockedItems`. */\n isLocked(item: string): boolean {\n return this.lockedItems().includes(item.trim().toLowerCase());\n }\n\n onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Enter') {\n event.preventDefault();\n this.addItem();\n }\n }\n}\n","<div\n cdkDropList\n [cdkDropListDisabled]=\"disabled() || !orderable()\"\n (cdkDropListDropped)=\"onDrop($event)\"\n class=\"fk-list-editor__list\"\n [attr.aria-label]=\"ariaLabel()\"\n>\n @for (item of items(); track $index) {\n <div\n cdkDrag\n [cdkDragDisabled]=\"disabled() || !orderable()\"\n class=\"fk-list-editor__item\"\n >\n @if (orderable()) {\n <span class=\"fk-list-editor__handle\" cdkDragHandle>\n <svg\n class=\"fk-list-editor__icon\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <circle cx=\"9\" cy=\"6\" r=\"1.5\" fill=\"currentColor\" />\n <circle cx=\"15\" cy=\"6\" r=\"1.5\" fill=\"currentColor\" />\n <circle cx=\"9\" cy=\"12\" r=\"1.5\" fill=\"currentColor\" />\n <circle cx=\"15\" cy=\"12\" r=\"1.5\" fill=\"currentColor\" />\n <circle cx=\"9\" cy=\"18\" r=\"1.5\" fill=\"currentColor\" />\n <circle cx=\"15\" cy=\"18\" r=\"1.5\" fill=\"currentColor\" />\n </svg>\n </span>\n }\n\n @if (showOrder()) {\n <span class=\"fk-list-editor__order\">{{ $index + 1 }}</span>\n }\n\n <input\n class=\"fk-list-editor__input\"\n type=\"text\"\n [value]=\"item\"\n [disabled]=\"disabled() || isLocked(item)\"\n (input)=\"updateItem($index, $any($event.target).value)\"\n />\n\n <button\n class=\"fk-list-editor__remove\"\n type=\"button\"\n [disabled]=\"disabled() || isLocked(item)\"\n [title]=\"isLocked(item) ? 'This item cannot be removed' : 'Remove item'\"\n (click)=\"removeItem($index)\"\n >\n <svg\n class=\"fk-list-editor__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=\"M6 6l12 12M18 6L6 18\"\n stroke=\"currentColor\"\n stroke-width=\"1.9\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n\n <div *cdkDragPlaceholder class=\"fk-list-editor__placeholder\"></div>\n </div>\n }\n</div>\n\n@if (items().length === 0 && emptyMessage()) {\n <p class=\"fk-list-editor__empty\">{{ emptyMessage() }}</p>\n}\n\n<div class=\"fk-list-editor__add\">\n <div class=\"fk-list-editor__add-input\">\n <input\n class=\"fk-list-editor__input\"\n type=\"text\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [ngModel]=\"newItemValue()\"\n (ngModelChange)=\"newItemValue.set($event)\"\n (keydown)=\"onKeydown($event)\"\n />\n\n @if (newItemValue() && !disabled()) {\n <button\n class=\"fk-list-editor__add-clear\"\n type=\"button\"\n aria-label=\"Clear input\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"newItemValue.set('')\"\n >\n <svg\n class=\"fk-list-editor__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=\"M6 6l12 12M18 6L6 18\"\n stroke=\"currentColor\"\n stroke-width=\"1.9\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n }\n </div>\n\n <fk-button\n variant=\"outline\"\n size=\"sm\"\n [disabled]=\"!canAdd() || disabled()\"\n (click)=\"addItem()\"\n >\n <svg\n fkButtonIconStart\n class=\"fk-list-editor__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 5v14M5 12h14\"\n stroke=\"currentColor\"\n stroke-width=\"1.9\"\n stroke-linecap=\"round\"\n />\n </svg>\n {{ addLabel() }}\n </fk-button>\n</div>\n\n@if (hasDuplicates()) {\n <p class=\"fk-list-editor__error\">Item names must be unique.</p>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;MAwCa,mBAAmB,CAAA;;;AAGrB,IAAA,KAAK,GAAG,KAAK,CAAW,EAAE,4EAAC;;AAE3B,IAAA,WAAW,GAAG,KAAK,CAAC,gBAAgB,kFAAC;;AAErC,IAAA,YAAY,GAAG,KAAK,CAAC,qBAAqB,mFAAC;;AAE3C,IAAA,QAAQ,GAAG,KAAK,CAAC,KAAK,+EAAC;;AAEvB,IAAA,SAAS,GAAG,KAAK,CAAC,IAAI,gFAAC;;AAEvB,IAAA,SAAS,GAAG,KAAK,CAAC,IAAI,gFAAC;;AAEvB,IAAA,IAAI,GAAG,KAAK,CAAiB,IAAI,2EAAC;;AAElC,IAAA,WAAW,GAAG,KAAK,CAAW,EAAE,kFAAC;;AAGjC,IAAA,SAAS,GAAG,KAAK,CAAS,EAAE,gFAAC;AAC7B,IAAA,QAAQ,GAAG,KAAK,CAAC,KAAK,+EAAC;AACvB,IAAA,SAAS,GAAG,KAAK,CAAgB,IAAI,gFAAC;;;IAItC,WAAW,GAAG,MAAM,EAAY;;IAEhC,SAAS,GAAG,MAAM,EAAU;;IAE5B,WAAW,GAAG,MAAM,EAAmC;;AAGvD,IAAA,YAAY,GAAG,MAAM,CAAC,EAAE,mFAAC;;AAGzB,IAAA,MAAM,GAAG,QAAQ,CAAC,MAAK;QAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE;QAExC,IAAI,CAAC,KAAK,EAAE;AACV,YAAA,OAAO,KAAK;QACd;QAEA,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAEhE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;AAChD,IAAA,CAAC,6EAAC;AAEO,IAAA,aAAa,GAAG,QAAQ,CAAC,MAAK;QACrC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAE7D,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM;AAC7C,IAAA,CAAC,oFAAC;AAEO,IAAA,aAAa,GAAG,QAAQ,CAAC,MAAK;AACrC,QAAA,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;AAClD,IAAA,CAAC,oFAAC;AAEO,IAAA,OAAO,GAAG,QAAQ,CAAC,MAC1B;QACE,gBAAgB;AAChB,QAAA,CAAA,gBAAA,EAAmB,IAAI,CAAC,IAAI,EAAE,CAAA,CAAE;QAChC,IAAI,CAAC,QAAQ,EAAE,GAAG,0BAA0B,GAAG,EAAE;QACjD,IAAI,CAAC,SAAS,EAAE;AACjB;SACE,MAAM,CAAC,OAAO;AACd,SAAA,IAAI,CAAC,GAAG,CAAC,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,SAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CACb;AAED,IAAA,IACI,SAAS,GAAA;AACX,QAAA,OAAO,IAAI,CAAC,OAAO,EAAE;IACvB;;;IAKA,OAAO,GAAA;QACL,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE;AAExC,QAAA,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE;YAC/C;QACF;AAEA,QAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC;AAC7C,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;AACnC,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;IAC5B;;AAGA,IAAA,UAAU,CAAC,KAAa,EAAA;QACtB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC;AAEhC,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;YAC1C;QACF;QAEA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,CAAC;QAC/D,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QACnC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACxC;;IAGA,UAAU,CAAC,KAAa,EAAE,KAAa,EAAA;AACrC,QAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,KACrB,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,KAAK,KAAK,GAAG,KAAK,GAAG,IAAI,CAAC,CAAC,CACpD;QACD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IACrC;AAEA,IAAA,MAAM,CAAC,KAA4B,EAAA;QACjC,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QAEjC,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,YAAY,CAAC;AACjE,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;QACvB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IACrC;;AAGA,IAAA,QAAQ,CAAC,IAAY,EAAA;AACnB,QAAA,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC/D;AAEA,IAAA,SAAS,CAAC,KAAoB,EAAA;AAC5B,QAAA,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,EAAE;YACzB,KAAK,CAAC,cAAc,EAAE;YACtB,IAAI,CAAC,OAAO,EAAE;QAChB;IACF;uGAjIW,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAnB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,mBAAmB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,YAAA,EAAA,EAAA,iBAAA,EAAA,cAAA,EAAA,UAAA,EAAA,cAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,KAAA,EAAA,aAAA,EAAA,WAAA,EAAA,aAAA,EAAA,SAAA,EAAA,WAAA,EAAA,WAAA,EAAA,aAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,gBAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECxChC,kiIA8IA,EAAA,MAAA,EAAA,CAAA,o6LAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EDlHI,WAAW,+mBACX,WAAW,EAAA,QAAA,EAAA,8BAAA,EAAA,MAAA,EAAA,CAAA,wBAAA,EAAA,iBAAA,EAAA,wBAAA,EAAA,IAAA,EAAA,qBAAA,EAAA,qBAAA,EAAA,4BAAA,EAAA,2BAAA,EAAA,0BAAA,EAAA,+BAAA,EAAA,2BAAA,EAAA,6BAAA,EAAA,sBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,oBAAA,EAAA,oBAAA,EAAA,mBAAA,EAAA,mBAAA,CAAA,EAAA,QAAA,EAAA,CAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACX,OAAO,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,iBAAA,EAAA,oBAAA,EAAA,iBAAA,EAAA,mBAAA,EAAA,yBAAA,EAAA,iBAAA,EAAA,0BAAA,EAAA,qBAAA,EAAA,yBAAA,EAAA,cAAA,CAAA,EAAA,OAAA,EAAA,CAAA,gBAAA,EAAA,iBAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,eAAA,EAAA,gBAAA,EAAA,cAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACP,aAAa,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,CAAA,uBAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACb,kBAAkB,EAAA,QAAA,EAAA,iCAAA,EAAA,MAAA,EAAA,CAAA,MAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAClB,eAAe,kLACf,0BAA0B,EAAA,QAAA,EAAA,qBAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAMjB,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAhB/B,SAAS;+BACE,gBAAgB,EAAA,UAAA,EACd,IAAI,EAAA,OAAA,EACP;wBACP,WAAW;wBACX,WAAW;wBACX,OAAO;wBACP,aAAa;wBACb,kBAAkB;wBAClB,eAAe;wBACf,0BAA0B;qBAC3B,EAAA,eAAA,EACgB,uBAAuB,CAAC,MAAM,EAAA,QAAA,EAAA,kiIAAA,EAAA,MAAA,EAAA,CAAA,o6LAAA,CAAA,EAAA;;sBAyE9C,WAAW;uBAAC,OAAO;;;AE7GtB;;AAEG;;;;"}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, output, inject, ElementRef, computed, HostBinding, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
-
import { IconComponent } from '@frame-kit/ui-ng/core/icon';
|
|
2
|
+
import { input, output, inject, ElementRef, computed, HostBinding, ChangeDetectionStrategy, Component, InjectionToken, Directive } from '@angular/core';
|
|
4
3
|
|
|
5
4
|
class MenuItemComponent {
|
|
6
5
|
// ===== INPUTS =====
|
|
7
|
-
/** Optional icon name rendered to the leading side of the label. */
|
|
8
|
-
icon = input(null, ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
9
6
|
/** When true, applies destructive (danger) color styling to the item. */
|
|
10
7
|
danger = input(false, ...(ngDevMode ? [{ debugName: "danger" }] : /* istanbul ignore next */ []));
|
|
11
8
|
/** When true, prevents interaction and applies disabled styling. */
|
|
@@ -43,22 +40,55 @@ class MenuItemComponent {
|
|
|
43
40
|
}
|
|
44
41
|
}
|
|
45
42
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MenuItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
46
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.
|
|
43
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: MenuItemComponent, isStandalone: true, selector: "fk-menu-item", inputs: { danger: { classPropertyName: "danger", publicName: "danger", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClick: "itemClick" }, host: { attributes: { "role": "menuitem" }, listeners: { "click": "onClick()", "keydown": "onKeydown($event)" }, properties: { "attr.tabindex": "disabled() ? null : -1", "attr.aria-disabled": "disabled() ? \"true\" : null", "class": "this.hostClass" } }, ngImport: i0, template: "<ng-content select=\"[fkMenuItemIcon]\" />\n<span class=\"fk-menu-item__label\">\n <ng-content />\n</span>\n", styles: [":host{box-sizing:border-box;display:flex;align-items:center;gap:var(--fk-menu-item-gap, var(--fk-rhythm-2, .5rem));width:100%;padding:var(--fk-menu-item-padding, var(--fk-rhythm-2, .5rem) var(--fk-rhythm-3, .75rem));border-radius:var(--fk-menu-item-radius, var(--fk-radius-md, .375rem));background:transparent;font-family:var(--fk-menu-item-font-family, var(--fk-font-family-base, sans-serif));font-size:var(--fk-menu-item-font-size, .875rem);color:var(--fk-menu-item-color, var(--fk-color-text, #1f2d3d));text-align:left;cursor:pointer;transition:background-color var(--fk-menu-item-transition-duration, var(--fk-motion-duration-fast, .12s)) var(--fk-menu-item-transition-easing, var(--fk-motion-easing-default, ease));outline:none;border:none}:host:hover:not(.fk-menu-item--disabled){background-color:var(--fk-menu-item-bg-hover, var(--fk-color-surface-muted, #f7f9fb))}:host:focus-visible{box-shadow:var(--fk-menu-item-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)))}:host.fk-menu-item--danger{color:var(--fk-menu-item-danger-color, var(--fk-color-danger, #e02424))}:host.fk-menu-item--danger:hover:not(.fk-menu-item--disabled){background-color:var(--fk-menu-item-danger-bg-hover, var(--fk-color-danger-surface, #fef2f2))}.fk-menu-item--disabled{opacity:var(--fk-menu-item-opacity-disabled, .5);cursor:not-allowed}.fk-menu-item__label{flex:1;white-space:nowrap}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
47
44
|
}
|
|
48
45
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MenuItemComponent, decorators: [{
|
|
49
46
|
type: Component,
|
|
50
|
-
args: [{ selector: 'fk-menu-item', standalone: true, imports: [
|
|
47
|
+
args: [{ selector: 'fk-menu-item', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
51
48
|
role: 'menuitem',
|
|
52
49
|
'[attr.tabindex]': 'disabled() ? null : -1',
|
|
53
50
|
'[attr.aria-disabled]': 'disabled() ? "true" : null',
|
|
54
51
|
'(click)': 'onClick()',
|
|
55
52
|
'(keydown)': 'onKeydown($event)',
|
|
56
|
-
}, template: "
|
|
57
|
-
}], propDecorators: {
|
|
53
|
+
}, template: "<ng-content select=\"[fkMenuItemIcon]\" />\n<span class=\"fk-menu-item__label\">\n <ng-content />\n</span>\n", styles: [":host{box-sizing:border-box;display:flex;align-items:center;gap:var(--fk-menu-item-gap, var(--fk-rhythm-2, .5rem));width:100%;padding:var(--fk-menu-item-padding, var(--fk-rhythm-2, .5rem) var(--fk-rhythm-3, .75rem));border-radius:var(--fk-menu-item-radius, var(--fk-radius-md, .375rem));background:transparent;font-family:var(--fk-menu-item-font-family, var(--fk-font-family-base, sans-serif));font-size:var(--fk-menu-item-font-size, .875rem);color:var(--fk-menu-item-color, var(--fk-color-text, #1f2d3d));text-align:left;cursor:pointer;transition:background-color var(--fk-menu-item-transition-duration, var(--fk-motion-duration-fast, .12s)) var(--fk-menu-item-transition-easing, var(--fk-motion-easing-default, ease));outline:none;border:none}:host:hover:not(.fk-menu-item--disabled){background-color:var(--fk-menu-item-bg-hover, var(--fk-color-surface-muted, #f7f9fb))}:host:focus-visible{box-shadow:var(--fk-menu-item-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18)))}:host.fk-menu-item--danger{color:var(--fk-menu-item-danger-color, var(--fk-color-danger, #e02424))}:host.fk-menu-item--danger:hover:not(.fk-menu-item--disabled){background-color:var(--fk-menu-item-danger-bg-hover, var(--fk-color-danger-surface, #fef2f2))}.fk-menu-item--disabled{opacity:var(--fk-menu-item-opacity-disabled, .5);cursor:not-allowed}.fk-menu-item__label{flex:1;white-space:nowrap}\n"] }]
|
|
54
|
+
}], propDecorators: { danger: [{ type: i0.Input, args: [{ isSignal: true, alias: "danger", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }], hostClass: [{
|
|
58
55
|
type: HostBinding,
|
|
59
56
|
args: ['class']
|
|
60
57
|
}] } });
|
|
61
58
|
|
|
59
|
+
/** Injection token for the leading-icon slot of `fk-menu-item`. */
|
|
60
|
+
const FK_MENU_ITEM_ICON = new InjectionToken('FK_MENU_ITEM_ICON');
|
|
61
|
+
/**
|
|
62
|
+
* Marks projected content as the leading icon of an `fk-menu-item`. Project any
|
|
63
|
+
* icon element (the app owns the icon system):
|
|
64
|
+
*
|
|
65
|
+
* ```html
|
|
66
|
+
* <fk-menu-item>
|
|
67
|
+
* <fk-icon fkMenuItemIcon name="pen-outline" />
|
|
68
|
+
* Edit
|
|
69
|
+
* </fk-menu-item>
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
class FkMenuItemIconDirective {
|
|
73
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FkMenuItemIconDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
74
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: FkMenuItemIconDirective, isStandalone: true, selector: "[fkMenuItemIcon]", host: { attributes: { "aria-hidden": "true" } }, providers: [
|
|
75
|
+
{ provide: FK_MENU_ITEM_ICON, useExisting: FkMenuItemIconDirective },
|
|
76
|
+
], ngImport: i0 });
|
|
77
|
+
}
|
|
78
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FkMenuItemIconDirective, decorators: [{
|
|
79
|
+
type: Directive,
|
|
80
|
+
args: [{
|
|
81
|
+
selector: '[fkMenuItemIcon]',
|
|
82
|
+
standalone: true,
|
|
83
|
+
providers: [
|
|
84
|
+
{ provide: FK_MENU_ITEM_ICON, useExisting: FkMenuItemIconDirective },
|
|
85
|
+
],
|
|
86
|
+
host: {
|
|
87
|
+
'aria-hidden': 'true',
|
|
88
|
+
},
|
|
89
|
+
}]
|
|
90
|
+
}] });
|
|
91
|
+
|
|
62
92
|
class MenuSeparatorComponent {
|
|
63
93
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MenuSeparatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
64
94
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.9", type: MenuSeparatorComponent, isStandalone: true, selector: "fk-menu-separator", host: { attributes: { "role": "separator" }, classAttribute: "fk-menu-separator" }, ngImport: i0, template: '', isInline: true, styles: [":host{display:block;height:1px;margin:var(--fk-rhythm-1, .25rem) 0;background-color:var(--fk-menu-separator-color, var(--fk-color-border, #d9e2ee))}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
@@ -75,5 +105,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
75
105
|
* Generated bundle index. Do not edit.
|
|
76
106
|
*/
|
|
77
107
|
|
|
78
|
-
export { MenuItemComponent, MenuSeparatorComponent };
|
|
108
|
+
export { FK_MENU_ITEM_ICON, FkMenuItemIconDirective, MenuItemComponent, MenuSeparatorComponent };
|
|
79
109
|
//# sourceMappingURL=frame-kit-ui-ng-ui-menu-item.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frame-kit-ui-ng-ui-menu-item.mjs","sources":["../../../../packages/ui-ng/ui/menu-item/menu-item.component.ts","../../../../packages/ui-ng/ui/menu-item/menu-item.component.html","../../../../packages/ui-ng/ui/menu-item/menu-separator.component.ts","../../../../packages/ui-ng/ui/menu-item/frame-kit-ui-ng-ui-menu-item.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n ElementRef,\n HostBinding,\n inject,\n input,\n output,\n} from '@angular/core';\n\
|
|
1
|
+
{"version":3,"file":"frame-kit-ui-ng-ui-menu-item.mjs","sources":["../../../../packages/ui-ng/ui/menu-item/menu-item.component.ts","../../../../packages/ui-ng/ui/menu-item/menu-item.component.html","../../../../packages/ui-ng/ui/menu-item/menu-item-icon.directive.ts","../../../../packages/ui-ng/ui/menu-item/menu-separator.component.ts","../../../../packages/ui-ng/ui/menu-item/frame-kit-ui-ng-ui-menu-item.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n ElementRef,\n HostBinding,\n inject,\n input,\n output,\n} from '@angular/core';\n\n@Component({\n selector: 'fk-menu-item',\n standalone: true,\n imports: [],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './menu-item.component.html',\n styleUrl: './menu-item.component.scss',\n host: {\n role: 'menuitem',\n '[attr.tabindex]': 'disabled() ? null : -1',\n '[attr.aria-disabled]': 'disabled() ? \"true\" : null',\n '(click)': 'onClick()',\n '(keydown)': 'onKeydown($event)',\n },\n})\nexport class MenuItemComponent {\n // ===== INPUTS =====\n /** When true, applies destructive (danger) color styling to the item. */\n readonly danger = input<boolean>(false);\n /** When true, prevents interaction and applies disabled styling. */\n readonly disabled = input<boolean>(false);\n\n // ===== OUTPUTS =====\n /** Fires when the user activates the item via click or keyboard. */\n readonly itemClick = output<void>();\n\n // ===== REFS =====\n readonly elRef = inject(ElementRef);\n\n // ===== COMPUTED =====\n readonly classes = computed(() => {\n return [\n 'fk-menu-item',\n this.danger() ? 'fk-menu-item--danger' : '',\n this.disabled() ? 'fk-menu-item--disabled' : '',\n ]\n .filter(Boolean)\n .join(' ');\n });\n\n @HostBinding('class')\n get hostClass() {\n return this.classes();\n }\n\n // ===== ACTIONS =====\n\n onClick(): void {\n if (this.disabled()) {\n return;\n }\n\n this.itemClick.emit();\n this.elRef.nativeElement.dispatchEvent(\n new CustomEvent('fkmenuitemselect', { bubbles: true }),\n );\n }\n\n onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this.onClick();\n }\n }\n}\n","<ng-content select=\"[fkMenuItemIcon]\" />\n<span class=\"fk-menu-item__label\">\n <ng-content />\n</span>\n","import { Directive, InjectionToken } from '@angular/core';\n\n/** Injection token for the leading-icon slot of `fk-menu-item`. */\nexport const FK_MENU_ITEM_ICON = new InjectionToken<FkMenuItemIconDirective>(\n 'FK_MENU_ITEM_ICON',\n);\n\n/**\n * Marks projected content as the leading icon of an `fk-menu-item`. Project any\n * icon element (the app owns the icon system):\n *\n * ```html\n * <fk-menu-item>\n * <fk-icon fkMenuItemIcon name=\"pen-outline\" />\n * Edit\n * </fk-menu-item>\n * ```\n */\n@Directive({\n selector: '[fkMenuItemIcon]',\n standalone: true,\n providers: [\n { provide: FK_MENU_ITEM_ICON, useExisting: FkMenuItemIconDirective },\n ],\n host: {\n 'aria-hidden': 'true',\n },\n})\nexport class FkMenuItemIconDirective {}\n","import { ChangeDetectionStrategy, Component } from '@angular/core';\n\n@Component({\n selector: 'fk-menu-separator',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: '',\n styleUrl: './menu-separator.component.scss',\n host: {\n role: 'separator',\n class: 'fk-menu-separator',\n },\n})\nexport class MenuSeparatorComponent {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|