From 2c762af27136d9efd964f008a8e4a5412b80e6a7 Mon Sep 17 00:00:00 2001 From: Sobyt483 Date: Tue, 19 May 2026 16:25:32 +0400 Subject: [PATCH] feat: add jsdoc fix eslint errors Signed-off-by: Sobyt483 --- README.md | 2 +- docs/dashboard.md | 7 +-- .../cards/favorites/favorites.component.html | 6 +-- .../cards/favorites/favorites.component.ts | 6 +-- .../service-status-card.component.html | 8 +-- .../service-status-card.component.ts | 11 ++-- .../stories/visited-service-card.stories.ts | 22 ++++---- .../visited-service-card.component.html | 14 +++-- .../visited-service-card.component.ts | 6 +-- .../cards/whats-new/whats-new.component.html | 6 +-- .../cards/whats-new/whats-new.component.ts | 6 +-- .../add-card-dialog.component.html | 16 +++--- .../add-card-dialog.component.spec.ts | 2 +- .../add-card-dialog.component.ts | 10 ++-- .../card/dashboard-card.component.html | 4 +- .../utils/dashboard-card-registry.spec.ts | 21 +++++--- .../dashboard/dashboard.component.html | 30 +++++------ .../dashboard/models/dashboard.model.ts | 41 ++++++++++++-- .../section/dashboard-section.component.html | 3 +- .../declarative-form.component.html | 22 ++++---- .../form/models/form-field-definition.ts | 11 ++++ .../ngx/declarative-ui/models/resource.ts | 4 ++ .../declarative-ui/models/ui-definition.ts | 53 +++++++++++++++++-- .../stories/add-card-dialog.stories.ts | 5 +- .../declarative-table-card.component.html | 28 +++++----- .../table-card/models/configs.ts | 31 +++++++++++ .../declarative-table.component.html | 2 +- .../ngx/declarative-ui/table/models/index.ts | 1 - .../table/models/table.model.ts | 17 ------ tsconfig.json | 3 ++ 30 files changed, 263 insertions(+), 135 deletions(-) delete mode 100644 projects/ngx/declarative-ui/table/models/table.model.ts diff --git a/README.md b/README.md index 73350a6..8c7da67 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ Components can be exported as native web components using Angular Elements, maki | `` | `` | [docs/declarative-table.md](docs/declarative-table.md) | | `` | `` | [docs/declarative-form.md](docs/declarative-form.md) | | `` | `` | [docs/declarative-table-card.md](docs/declarative-table-card.md) | -| `` | `` | [docs/dashboard.md](docs/declarative-dashboard.md) | +| `` | `` | [docs/dashboard.md](docs/dashboard.md) | ## NeoNephos Foundation diff --git a/docs/dashboard.md b/docs/dashboard.md index ca47777..fed2d18 100644 --- a/docs/dashboard.md +++ b/docs/dashboard.md @@ -199,9 +199,10 @@ const cards: CardConfig[] = [ ### Outputs -| Output | Payload | Description | -| ------- | ---------------------------------------------------- | ------------------------------- | -| `saved` | `{ sections: SectionConfig[]; cards: CardConfig[] }` | Emits when the user saves edits | +| Output | Payload | Description | +| -------------------- | ---------------------------------------------------- | ---------------------------------------------------------------- | +| `saved` | `{ sections: SectionConfig[]; cards: CardConfig[] }` | Emits when the user saves edits | +| `actionButtonClick` | `{ event: MouseEvent; action: ButtonSettings }` | Emits when a custom action button from `config.customActions` is clicked | ### Static methods diff --git a/projects/ngx/cards/favorites/favorites.component.html b/projects/ngx/cards/favorites/favorites.component.html index d389bfc..16c2945 100644 --- a/projects/ngx/cards/favorites/favorites.component.html +++ b/projects/ngx/cards/favorites/favorites.component.html @@ -1,11 +1,11 @@
- Favorites + Favorites
@for (item of items; track item.action) {
- + {{ item.label }} - {{ item.label }} + {{ item.label }}
}
diff --git a/projects/ngx/cards/favorites/favorites.component.ts b/projects/ngx/cards/favorites/favorites.component.ts index 7788346..5881a6c 100644 --- a/projects/ngx/cards/favorites/favorites.component.ts +++ b/projects/ngx/cards/favorites/favorites.component.ts @@ -5,10 +5,10 @@ import { Title } from '@fundamental-ngx/ui5-webcomponents/title'; @Component({ selector: 'mfp-favorites', - templateUrl: './favorites.component.html', - styleUrls: ['./favorites.component.scss'], - encapsulation: ViewEncapsulation.ShadowDom, imports: [Button, Icon, Title], + templateUrl: './favorites.component.html', + styleUrl: './favorites.component.scss', + encapsulation: ViewEncapsulation.ShadowDom }) export class Favorites { readonly items = [ diff --git a/projects/ngx/cards/service-status/service-status-card.component.html b/projects/ngx/cards/service-status/service-status-card.component.html index 784ce73..70a45c1 100644 --- a/projects/ngx/cards/service-status/service-status-card.component.html +++ b/projects/ngx/cards/service-status/service-status-card.component.html @@ -1,12 +1,12 @@
- Service Availability + Service Availability
@for (service of services; track service.name) {
- + {{ service.name }} -
- +
+ {{ statusConfig[service.status].label }}
diff --git a/projects/ngx/cards/service-status/service-status-card.component.ts b/projects/ngx/cards/service-status/service-status-card.component.ts index d942b45..d7a88b6 100644 --- a/projects/ngx/cards/service-status/service-status-card.component.ts +++ b/projects/ngx/cards/service-status/service-status-card.component.ts @@ -2,20 +2,25 @@ import { Component, ViewEncapsulation } from '@angular/core'; import { Icon } from '@fundamental-ngx/ui5-webcomponents/icon'; import { Title } from '@fundamental-ngx/ui5-webcomponents/title'; +/** Possible health states for a service. */ export type ServiceStatusValue = 'operational' | 'degraded' | 'outage' | 'maintenance'; +/** A single service entry displayed in the service-status card. */ export interface ServiceStatusItem { + /** Display name of the service. */ name: string; + /** SAP UI5 icon name used as the service icon. */ icon: string; + /** Current health status of the service. */ status: ServiceStatusValue; } @Component({ selector: 'mfp-service-status-card', - templateUrl: './service-status-card.component.html', - styleUrls: ['./service-status-card.component.scss'], - encapsulation: ViewEncapsulation.ShadowDom, imports: [Icon, Title], + templateUrl: './service-status-card.component.html', + styleUrl: './service-status-card.component.scss', + encapsulation: ViewEncapsulation.ShadowDom }) export class ServiceStatusCard { readonly services: ServiceStatusItem[] = [ diff --git a/projects/ngx/cards/stories/visited-service-card.stories.ts b/projects/ngx/cards/stories/visited-service-card.stories.ts index 2dbbb4a..9e59f47 100644 --- a/projects/ngx/cards/stories/visited-service-card.stories.ts +++ b/projects/ngx/cards/stories/visited-service-card.stories.ts @@ -4,7 +4,8 @@ import { MessageStrip } from '@fundamental-ngx/ui5-webcomponents/message-strip'; import type { Meta, StoryObj } from '@storybook/angular'; @Component({ - selector: 'visited-service-card-story', + selector: 'mfp-visited-service-card-story', + imports: [MessageStrip, VisitedServiceCard], template: ` @if (clicked) { Card clicked — would navigate to: {{ path }} } - `, - imports: [MessageStrip, VisitedServiceCard], + ` }) class VisitedServiceCardStory { @Input() serviceType = ''; @@ -28,7 +28,7 @@ class VisitedServiceCardStory { @Input() serviceIcon = ''; @Input() serviceDescription = ''; @Input() path = ''; - @Output() click = new EventEmitter(); + @Output() readonly cardClick = new EventEmitter(); clicked = false; onCardClick() { this.clicked = true; @@ -117,12 +117,12 @@ export const AllCards: Story = { render: () => ({ template: `
- - - - - - + + + + + +
`, }), diff --git a/projects/ngx/cards/visited-service-card/visited-service-card.component.html b/projects/ngx/cards/visited-service-card/visited-service-card.component.html index 51bf5a5..01d1c3a 100644 --- a/projects/ngx/cards/visited-service-card/visited-service-card.component.html +++ b/projects/ngx/cards/visited-service-card/visited-service-card.component.html @@ -1,17 +1,21 @@ -
+ +
{{ serviceType() }} + />
diff --git a/projects/ngx/cards/visited-service-card/visited-service-card.component.ts b/projects/ngx/cards/visited-service-card/visited-service-card.component.ts index 66c0e43..352ca5c 100644 --- a/projects/ngx/cards/visited-service-card/visited-service-card.component.ts +++ b/projects/ngx/cards/visited-service-card/visited-service-card.component.ts @@ -6,10 +6,10 @@ import '@ui5/webcomponents-icons/dist/AllIcons.js'; @Component({ selector: 'mfp-visited-service-card', + imports: [Card, CardHeader, Icon], templateUrl: './visited-service-card.component.html', - styleUrls: ['./visited-service-card.component.scss'], + styleUrl: './visited-service-card.component.scss', encapsulation: ViewEncapsulation.ShadowDom, - imports: [Card, CardHeader, Icon], }) export class VisitedServiceCard { serviceType = input.required(); @@ -18,5 +18,5 @@ export class VisitedServiceCard { serviceIcon = input.required(); path = input.required(); - click = output(); + readonly cardClick = output(); } diff --git a/projects/ngx/cards/whats-new/whats-new.component.html b/projects/ngx/cards/whats-new/whats-new.component.html index 224acf5..5f9dde2 100644 --- a/projects/ngx/cards/whats-new/whats-new.component.html +++ b/projects/ngx/cards/whats-new/whats-new.component.html @@ -1,8 +1,8 @@
- What's New - + What's New + @for (item of headlines; track item.title) { - + {{ item.title }} } diff --git a/projects/ngx/cards/whats-new/whats-new.component.ts b/projects/ngx/cards/whats-new/whats-new.component.ts index b9a8296..e6b8607 100644 --- a/projects/ngx/cards/whats-new/whats-new.component.ts +++ b/projects/ngx/cards/whats-new/whats-new.component.ts @@ -5,10 +5,10 @@ import { Title } from '@fundamental-ngx/ui5-webcomponents/title'; @Component({ selector: 'mfp-whats-new', - templateUrl: './whats-new.component.html', - styleUrls: ['./whats-new.component.scss'], - encapsulation: ViewEncapsulation.ShadowDom, imports: [List, ListItemStandard, Title], + templateUrl: './whats-new.component.html', + styleUrl: './whats-new.component.scss', + encapsulation: ViewEncapsulation.ShadowDom }) export class WhatsNew { readonly headlines = [ diff --git a/projects/ngx/declarative-ui/dashboard/add-card-dialog/add-card-dialog.component.html b/projects/ngx/declarative-ui/dashboard/add-card-dialog/add-card-dialog.component.html index 11b4dc2..6f13d38 100644 --- a/projects/ngx/declarative-ui/dashboard/add-card-dialog/add-card-dialog.component.html +++ b/projects/ngx/declarative-ui/dashboard/add-card-dialog/add-card-dialog.component.html @@ -1,11 +1,9 @@ - -
+ +
Add Card
- @if (availableCards().length === 0) { -

No cards available.

- } + @for (ac of availableCards(); track ac.id) { @let alreadyAdded = addedCardsIds().has(ac.id);
+ } @empty { +

No cards available.

}
- }
@@ -20,8 +20,8 @@ } @else {
diff --git a/projects/ngx/declarative-ui/dashboard/card/utils/dashboard-card-registry.spec.ts b/projects/ngx/declarative-ui/dashboard/card/utils/dashboard-card-registry.spec.ts index f4a3215..bf019d5 100644 --- a/projects/ngx/declarative-ui/dashboard/card/utils/dashboard-card-registry.spec.ts +++ b/projects/ngx/declarative-ui/dashboard/card/utils/dashboard-card-registry.spec.ts @@ -5,6 +5,7 @@ import { import { Component } from '@angular/core'; @Component({ + // eslint-disable-next-line @angular-eslint/component-selector selector: 'dashboard-test-card', standalone: true, template: 'dashboard test card', @@ -12,6 +13,7 @@ import { Component } from '@angular/core'; class DashboardTestCard {} @Component({ + // eslint-disable-next-line @angular-eslint/component-selector selector: '[dashboard-test-card]', standalone: true, template: 'dashboard attr card', @@ -19,17 +21,20 @@ class DashboardTestCard {} class DashboardAttrCard {} @Component({ + // eslint-disable-next-line @angular-eslint/component-selector selector: 'dashboard-test-card', standalone: true, + template: 'dashboard duplicate card', host: { 'data-test-duplicate': 'true', - }, - template: 'dashboard duplicate card', + } }) class DashboardDuplicateCard {} @Component({ + // eslint-disable-next-line @angular-eslint/component-selector selector: 'dashboard-non-standalone-card', + // eslint-disable-next-line @angular-eslint/prefer-standalone standalone: false, template: 'dashboard non-standalone card', }) @@ -41,27 +46,27 @@ describe('dashboard card registry', () => { }); it('registers standalone Angular components by selector', () => { - expect(() => addComponentToRegistry([DashboardTestCard])).not.toThrow(); + expect(() => { addComponentToRegistry([DashboardTestCard]); }).not.toThrow(); }); it('rejects non-component registrations', () => { class NotAComponent {} - expect(() => addComponentToRegistry([NotAComponent])).toThrowError( + expect(() => { addComponentToRegistry([NotAComponent]); }).toThrow( 'Dashboard card registration failed: "NotAComponent" is not an Angular component.', ); }); it('rejects selectors that are not a single element selector', () => { - expect(() => addComponentToRegistry([DashboardAttrCard])).toThrowError( + expect(() => { addComponentToRegistry([DashboardAttrCard]); }).toThrow( /must use a single element selector\. Received "\[dashboard-test-card\]"./, ); }); it('rejects non-standalone Angular components', () => { expect(() => - addComponentToRegistry([DashboardNonStandaloneCard]), - ).toThrowError( + { addComponentToRegistry([DashboardNonStandaloneCard]); }, + ).toThrow( 'Dashboard card registration failed: "dashboard-non-standalone-card" must be a standalone Angular component.', ); }); @@ -69,7 +74,7 @@ describe('dashboard card registry', () => { it('rejects duplicate selector registrations for different component types', () => { addComponentToRegistry([DashboardTestCard]); - expect(() => addComponentToRegistry([DashboardDuplicateCard])).toThrowError( + expect(() => { addComponentToRegistry([DashboardDuplicateCard]); }).toThrow( 'Dashboard card registration failed: selector "dashboard-test-card" is already registered.', ); }); diff --git a/projects/ngx/declarative-ui/dashboard/dashboard/dashboard.component.html b/projects/ngx/declarative-ui/dashboard/dashboard/dashboard.component.html index dd54f08..675bcd3 100644 --- a/projects/ngx/declarative-ui/dashboard/dashboard/dashboard.component.html +++ b/projects/ngx/declarative-ui/dashboard/dashboard/dashboard.component.html @@ -29,11 +29,10 @@ icon="menu2" tooltip="Actions" (click)="toolbarMenuOpen.update((v) => !v)" - > + /> @for (action of customActions(); track action.action) { + /> } @if (config().editable) { - + + /> } } @else { @for (action of customActions(); track action.action) { @for (section of sections(); track section.id) { }
- + @for (card of looseCards(); track card.id) { diff --git a/projects/ngx/declarative-ui/dashboard/models/dashboard.model.ts b/projects/ngx/declarative-ui/dashboard/models/dashboard.model.ts index 190cd82..8a8b640 100644 --- a/projects/ngx/declarative-ui/dashboard/models/dashboard.model.ts +++ b/projects/ngx/declarative-ui/dashboard/models/dashboard.model.ts @@ -1,8 +1,5 @@ import { ButtonSettings } from '../../models/ui-definition'; - - - export const CARD_TYPES = { WC: 'wc', ANGULAR: 'angular', @@ -11,40 +8,78 @@ export const CARD_TYPES = { export type CardsType = (typeof CARD_TYPES)[keyof typeof CARD_TYPES]; +/** Configuration for a single card placed in the dashboard grid or a section. */ export interface CardConfig { + /** Unique identifier for this card. Used as a stable key for position persistence. */ id: string; + /** Column span (1–12). Defaults to 12 when omitted. */ w?: number; + /** Row span — number of CSS grid rows occupied (1 row = 10 px by default). Defaults to 100 when omitted. */ h?: number; + /** Starting column index (0-based). Omit to let the grid auto-place the card. */ x?: number; + /** Starting row index (0-based). Omit to let the grid auto-place the card. */ y?: number; + /** Maximum row span in edit mode. */ maxH?: number; + /** Maximum column span in edit mode. */ maxW?: number; + /** Minimum row span in edit mode. */ minH?: number; + /** Minimum column span in edit mode. */ minW?: number; + /** ID of the parent section. Omit to place the card in the loose-card grid. */ sectionId?: string; + /** + * Custom-element tag name (for `'wc'`/omitted), Angular component selector (for `'angular'`), + * or SAP UI5 component name (for `'sap-ui'`). + */ component: string; + /** + * Render strategy for the card. + * - `'wc'` (default) — creates a custom element and sets `componentInputs` as DOM properties. + * - `'angular'` — looks up the Angular registry; warns and renders nothing if not found. + * - `'sap-ui'` — mounts via `window.sap.ui.require` + `ComponentContainer`. + */ type?: CardsType; + /** Key/value pairs passed to the rendered card. Behaviour depends on `type`. */ componentInputs?: Record; + /** Human-readable label shown in the "Add Card" dialog. */ label?: string; } +/** Configuration for a named horizontal section that groups cards. */ export interface SectionConfig { + /** Unique identifier for this section. */ id: string; + /** Column span (1–12). Defaults to 12 when omitted. */ w?: number; + /** Section heading displayed in the UI. */ title?: string; + /** When `false`, the section and its cards are excluded from edit mode. Defaults to `true` when omitted. */ editable?: boolean; } +/** Overrides for the two built-in dashboard toolbar buttons. */ export interface DashboardButtonsSettings { + /** Partial override merged on top of the Edit View button defaults. */ editViewButton?: Partial; + /** Partial override merged on top of the Add Card button defaults. */ addCardButton?: Partial; } +/** Top-level configuration for the `` component. */ export interface DashboardConfig { + /** Dashboard title rendered in the toolbar. */ title: string; + /** Optional subtitle shown below the title. */ description?: string; + /** URL of the background image applied to the dashboard host element. */ backgroundImageUrl?: string; + /** Overrides for the built-in Edit View and Add Card toolbar buttons. */ buttonsSettings?: DashboardButtonsSettings; + /** Extra action buttons rendered in the toolbar alongside the built-in ones. */ customActions?: ButtonSettings[]; + /** When `true`, shows the Edit View button in the toolbar, allowing the user to enter edit mode. */ editable?: boolean; } diff --git a/projects/ngx/declarative-ui/dashboard/section/dashboard-section.component.html b/projects/ngx/declarative-ui/dashboard/section/dashboard-section.component.html index 19eade8..05ba6fb 100644 --- a/projects/ngx/declarative-ui/dashboard/section/dashboard-section.component.html +++ b/projects/ngx/declarative-ui/dashboard/section/dashboard-section.component.html @@ -8,8 +8,7 @@ design="Default" icon="decline" (click)="removeSection.emit()" - > - + /> } @if (section().title) {
diff --git a/projects/ngx/declarative-ui/form/declarative-form/declarative-form.component.html b/projects/ngx/declarative-ui/form/declarative-form/declarative-form.component.html index ca1f8d5..6a271fc 100644 --- a/projects/ngx/declarative-ui/form/declarative-form/declarative-form.component.html +++ b/projects/ngx/declarative-ui/form/declarative-form/declarative-form.component.html @@ -1,4 +1,4 @@ -
+
@for (field of fields(); track field.name) { @let control = form.controls[field.name];
{{ field.label }} @@ -15,13 +15,13 @@ @if (getError(field.name); as error) {
{{ error }}
@@ -34,8 +34,8 @@ '-option-' + (value || 'empty') " - [value]="value" [selected]="value === control.value" + [value]="value" >{{ value }} } @@ -44,13 +44,13 @@ @if (getError(field.name); as error) {
{{ error }}
diff --git a/projects/ngx/declarative-ui/form/models/form-field-definition.ts b/projects/ngx/declarative-ui/form/models/form-field-definition.ts index fc173eb..81c5c5a 100644 --- a/projects/ngx/declarative-ui/form/models/form-field-definition.ts +++ b/projects/ngx/declarative-ui/form/models/form-field-definition.ts @@ -1,15 +1,26 @@ +/** Definition for a single form field rendered by `mfp-declarative-form`. */ export interface FormFieldDefinition { + /** JSON-path key used to read and write the field value (e.g. `metadata.name`). */ name: string; + /** Display label shown above the input. */ label?: string; + /** When `true`, passes the `required` attribute to the UI5 input — shows a visual required indicator. Validation itself is the host's responsibility via `FormFieldErrors`. */ required?: boolean; + /** Fixed list of options rendered as a select/dropdown. */ values?: string[]; + /** When `true`, the field is disabled (not interactive). */ disabled?: boolean; + /** Controls when `fieldChange` is emitted for this field. When omitted, `fieldChange` is never emitted. */ validation?: 'onBlur' | 'onChange'; } +/** Event payload emitted each time a single form field value changes. */ export interface FormFieldChangeEvent { + /** The `name` (JSON-path key) of the field that changed. */ fieldProperty: string; + /** The new value entered by the user. */ value: unknown; } +/** Map of field names to their current validation error messages (`null` = no error). */ export type FormFieldErrors = Record; diff --git a/projects/ngx/declarative-ui/models/resource.ts b/projects/ngx/declarative-ui/models/resource.ts index d725e84..91842cd 100644 --- a/projects/ngx/declarative-ui/models/resource.ts +++ b/projects/ngx/declarative-ui/models/resource.ts @@ -1,5 +1,9 @@ +/** Subset of fields of a generic resource that the table/form components rely on. */ export interface GenericResource extends Record { + /** Optional unique identifier. */ id?: string; + /** Whether the resource is available/healthy. */ isAvailable?: boolean; + /** Human-readable name used for screen readers and tooltips. */ accessibleName?: string; } diff --git a/projects/ngx/declarative-ui/models/ui-definition.ts b/projects/ngx/declarative-ui/models/ui-definition.ts index dd930c2..644d73c 100644 --- a/projects/ngx/declarative-ui/models/ui-definition.ts +++ b/projects/ngx/declarative-ui/models/ui-definition.ts @@ -1,5 +1,6 @@ import { GenericResource } from './resource'; +/** Text transformation applied to a field value before display. */ export type TransformType = | 'uppercase' | 'lowercase' @@ -7,13 +8,19 @@ export type TransformType = | 'decode' | 'encode'; +/** Resolves a field value via a property path with optional transforms. */ export interface PropertyField { + /** Dot-separated JSON path to the value (e.g. `metadata.name`). */ key: string; + /** Ordered list of transforms applied to the resolved string. */ transform?: TransformType[]; } +/** Display and interaction settings for a table cell. */ export interface UiSettings { + /** When `true`, renders the cell value as a styled badge (blue pill). */ labelDisplay?: boolean; + /** How the cell value is rendered. Defaults to plain text when omitted. */ displayAs?: | 'secret' | 'boolIcon' @@ -22,21 +29,32 @@ export interface UiSettings { | 'alert' | 'img' | 'button'; + /** Button appearance and action — only used when `displayAs` is `'button'`. */ buttonSettings?: ButtonSettings; + /** SAP UI5 icon name shown as the tooltip trigger icon. */ tooltipIcon?: string; + /** When `true`, a copy-to-clipboard button is rendered next to the value. */ withCopyButton?: boolean; + /** Inline CSS overrides applied unconditionally to the cell. */ cssCustomization?: Partial; + /** Conditional CSS rules evaluated against the cell value at render time. */ cssRules?: CssRule[]; + /** Fixed column width including unit (e.g. `'200px'`, `'20%'`). */ columnWidth?: string; } type KnownButtonActions = 'openInModal' | 'navigate' | 'edit' | 'delete'; type ButtonActions = KnownButtonActions | (string & {}); +/** Appearance and action configuration for a button rendered inside a table cell or toolbar. */ export interface ButtonSettings { + /** Button label text. */ text?: string; + /** SAP UI5 icon name placed before the label. */ icon?: string; + /** SAP UI5 icon name placed after the label. */ endIcon?: string; + /** SAP UI5 button design variant. */ design?: | 'Default' | 'Positive' @@ -44,18 +62,27 @@ export interface ButtonSettings { | 'Transparent' | 'Emphasized' | 'Attention'; + /** Tooltip shown on hover. */ tooltip?: string; + /** Action identifier. `'edit'` and `'delete'` are handled internally; all other values are forwarded to the host via `actionButtonClick`. */ action: ButtonActions; + /** Settings for the modal opened when `action` is `'openInModal'`. */ modalSettings?: ModalSettings; } +/** Size and dimension overrides for the modal opened by a button with `action: 'openInModal'`. */ export interface ModalSettings { + /** Modal title shown in the dialog header. */ title?: string; - size?: 'fullscreen' | 'l' | 'm' | 's'; // ze of the modal - width?: string; //updates the width of the modal. Allowed units are 'px', '%', 'rem', 'em', 'vh' and 'vw - height?: string; //updates the height of the modal. Allowed units are 'px', '%', 'rem', 'em', 'vh' and 'vw + /** Named size breakpoint. */ + size?: 'fullscreen' | 'l' | 'm' | 's'; + /** Explicit width override. */ + width?: string; + /** Explicit height override. */ + height?: string; } +/** Comparison operator used in a conditional CSS rule. */ export type CssRuleCondition = | 'equals' | 'notEquals' @@ -65,31 +92,51 @@ export type CssRuleCondition = | 'lessThanOrEqual' | 'contains'; +/** Conditional CSS rule: applies `styles` to the cell when `if` evaluates to `true`. */ export interface CssRule { + /** Condition evaluated against the cell's string value. */ if: { condition: CssRuleCondition; value: string }; + /** CSS properties applied when the condition is met. */ styles: Partial; } +/** Event payload emitted when a button inside a table cell is clicked. */ export interface ValueCellButtonClickEvent { + /** Original DOM click event. */ event: MouseEvent; + /** The field definition of the button cell that was clicked. */ field: TableFieldDefinition; + /** The data row associated with the clicked button. */ resource: T | undefined; } +/** Base field definition shared by table columns and form fields. */ export interface FieldDefinition { + /** Column header / form label. */ label?: string; + /** Dot-separated path to the resource property (e.g. `metadata.name`). */ property?: string | string[]; + /** Alternative path resolver with optional transforms. */ propertyField?: PropertyField; + /** JSONPath expression evaluated against the resource when `property` is not enough. */ jsonPathExpression?: string; + /** Static value — used when the cell shows a constant rather than a resource field. */ value?: string; + /** Display and interaction configuration for this cell. */ uiSettings?: UiSettings; } +/** Table column definition — extends `FieldDefinition` with optional column grouping. */ export interface TableFieldDefinition extends FieldDefinition { + /** Groups this column visually with adjacent columns that share the same `name`. */ group?: { + /** Logical group identifier. */ name: string; + /** Group header label shown above the grouped cells. */ label?: string; + /** Separator placed between values in the same group cell. */ delimiter?: string; + /** When `true`, each value is rendered on its own line. */ multiline?: boolean; }; } diff --git a/projects/ngx/declarative-ui/stories/add-card-dialog.stories.ts b/projects/ngx/declarative-ui/stories/add-card-dialog.stories.ts index de36372..146da63 100644 --- a/projects/ngx/declarative-ui/stories/add-card-dialog.stories.ts +++ b/projects/ngx/declarative-ui/stories/add-card-dialog.stories.ts @@ -20,8 +20,9 @@ const AVAILABLE_CARDS: CardConfig[] = [ }, ]; + @Component({ - selector: 'add-card-dialog-story', + selector: 'mfp-add-card-dialog-story', imports: [AddCardDialog], template: ` Open Dialog @@ -29,7 +30,7 @@ const AVAILABLE_CARDS: CardConfig[] = [ [addedCardsIds]="addedComponents" [availableCards]="availableCards" [open]="open" - (cancel)="open = false" + (cancelled)="open = false" (confirm)="onConfirm($event)" /> @if (lastAdded) { diff --git a/projects/ngx/declarative-ui/table-card/declarative-table-card.component.html b/projects/ngx/declarative-ui/table-card/declarative-table-card.component.html index 3c280d4..4c1fc22 100644 --- a/projects/ngx/declarative-ui/table-card/declarative-table-card.component.html +++ b/projects/ngx/declarative-ui/table-card/declarative-table-card.component.html @@ -7,8 +7,8 @@ } } @@ -23,8 +23,8 @@ (searchCollapsing() ? 'leave' : 'enter') " [formControl]="searchControl" - (blur)="onSearchBlur()" (animationend)="onSearchAnimationEnd()" + (blur)="onSearchBlur()" /> } @@ -53,14 +53,14 @@ @if (tableConfig(); as config) { }
@@ -71,19 +71,19 @@ [open]="createDialogOpen()" (ui5BeforeClose)="createDialogOpen.set(false)" > -
+
{{ config.title ?? 'Create' }}
-