@forgeroute/ui 0.4.55 → 0.4.56

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgeroute/ui",
3
- "version": "0.4.55",
3
+ "version": "0.4.56",
4
4
  "peerDependencies": {
5
5
  "@angular/common": ">=22.0.0",
6
6
  "@angular/core": ">=22.0.0",
@@ -1836,6 +1836,14 @@ export declare class DataTableComponent<T extends Record<string, any>> implement
1836
1836
  * zero rows, so they can change or clear it. Headers are plain labels otherwise.
1837
1837
  */
1838
1838
  protected readonly _showColumnControls: Signal<boolean>;
1839
+ /**
1840
+ * Keys of sortable columns whose cell is blank ('' or '—') on every loaded row — nothing to sort by, so the sort control is
1841
+ * hidden. Judged from the loaded page (the same text the cells show); an active sort on the column keeps its control so it
1842
+ * can be changed or cleared.
1843
+ */
1844
+ protected readonly _emptyColumnKeys: Signal<Set<string>>;
1845
+ /** A header sort control shows for a sortable column while there are rows and the column has a value somewhere. */
1846
+ protected _canShowSort(col: ColumnDef): boolean;
1839
1847
  protected readonly _hasPhoneControls: Signal<boolean>;
1840
1848
  /** Phone sort select → sets the sort directly (same state, page reset and load as the header's onSort). */
1841
1849
  protected onPhoneSort(value: string): void;
@@ -6729,6 +6737,11 @@ export type CardListIcon = 'call' | 'email' | 'sms' | 'task' | 'doc' | 'money' |
6729
6737
  * Other projected content (default slot) shows after the chips at the row end; `[card-stats]` and `[card-detail]` add a footer row
6730
6738
  * under the row (use the `.cli-stat`, `.cli-stat-label`, `.cli-stat-value`, `.cli-stat-divider` classes inside `[card-stats]`).
6731
6739
  *
6740
+ * Delete and a generic action (additive; unused = the row looks exactly as before). Row-end order: Edit, View, action, delete, then projected content.
6741
+ * - `[deletable]="true"` shows a red icon-only trash button (28px, 44px hit area on touch) -> `(delete)`; name it with `deleteLabel` (default "Delete"), `deleteTestId` sets its `data-testid`.
6742
+ * The page owns the confirmation (the component never deletes anything itself).
6743
+ * - `actionLabel="Download"` shows a grey chip button with that text -> `(action)`; `actionTestId`, `actionAriaLabel` as for the other buttons.
6744
+ *
6732
6745
  * Accessibility: the Edit / View buttons are real buttons; give them a longer name with `editAriaLabel` / `viewAriaLabel`
6733
6746
  * ("Edit task Call John") when the visible word alone is ambiguous in a list. The priority dot (`high`/`medium`/`low`) has a tooltip and an
6734
6747
  * accessible name (`High priority`, ...), is focusable so the tooltip works by keyboard; `blue`/`green` dots are decorative. The icon circle is decorative.
@@ -6757,10 +6770,22 @@ export declare class CardListItemComponent {
6757
6770
  /** Accessible names for the buttons when the visible word is not enough ("Edit task Call John"). */
6758
6771
  readonly editAriaLabel: import("@angular/core").InputSignal<string>;
6759
6772
  readonly viewAriaLabel: import("@angular/core").InputSignal<string>;
6773
+ /** Built-in icon-only trash button -> `delete`. The accessible name comes from `deleteLabel` ("Delete task Call John"). */
6774
+ readonly deletable: import("@angular/core").InputSignal<boolean>;
6775
+ readonly deleteLabel: import("@angular/core").InputSignal<string>;
6776
+ /** `data-testid` of the delete button (none when empty). */
6777
+ readonly deleteTestId: import("@angular/core").InputSignal<string>;
6778
+ /** Built-in secondary chip button (text = `actionLabel`, e.g. "Download") -> `action`; shown only while `actionLabel` is not empty. */
6779
+ readonly actionLabel: import("@angular/core").InputSignal<string>;
6780
+ readonly actionTestId: import("@angular/core").InputSignal<string>;
6781
+ readonly actionAriaLabel: import("@angular/core").InputSignal<string>;
6760
6782
  readonly editClick: import("@angular/core").OutputEmitterRef<void>;
6761
6783
  readonly viewClick: import("@angular/core").OutputEmitterRef<void>;
6784
+ readonly delete: import("@angular/core").OutputEmitterRef<void>;
6785
+ readonly action: import("@angular/core").OutputEmitterRef<void>;
6762
6786
  protected readonly calendarPath = "M5 4h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z M16 2v4 M8 2v4 M3 10h18";
6763
6787
  protected readonly editPath = "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7 M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z";
6788
+ protected readonly trashPath = "M3 6h18 M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2 M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6 M10 11v6 M14 11v6";
6764
6789
  protected readonly iconPath: import("@angular/core").Signal<string | null>;
6765
6790
  protected readonly indicatorLabel: import("@angular/core").Signal<string>;
6766
6791
  static ɵfac: i0.ɵɵFactoryDeclaration<CardListItemComponent, never>;
@@ -6830,9 +6855,41 @@ export declare class CardListItemComponent {
6830
6855
  "required": false;
6831
6856
  "isSignal": true;
6832
6857
  };
6858
+ "deletable": {
6859
+ "alias": "deletable";
6860
+ "required": false;
6861
+ "isSignal": true;
6862
+ };
6863
+ "deleteLabel": {
6864
+ "alias": "deleteLabel";
6865
+ "required": false;
6866
+ "isSignal": true;
6867
+ };
6868
+ "deleteTestId": {
6869
+ "alias": "deleteTestId";
6870
+ "required": false;
6871
+ "isSignal": true;
6872
+ };
6873
+ "actionLabel": {
6874
+ "alias": "actionLabel";
6875
+ "required": false;
6876
+ "isSignal": true;
6877
+ };
6878
+ "actionTestId": {
6879
+ "alias": "actionTestId";
6880
+ "required": false;
6881
+ "isSignal": true;
6882
+ };
6883
+ "actionAriaLabel": {
6884
+ "alias": "actionAriaLabel";
6885
+ "required": false;
6886
+ "isSignal": true;
6887
+ };
6833
6888
  }, {
6834
6889
  "editClick": "editClick";
6835
6890
  "viewClick": "viewClick";
6891
+ "delete": "delete";
6892
+ "action": "action";
6836
6893
  }, never, ["[card-list-inline]", "[card-list-action]", "*", "[card-stats]", "[card-detail]"], true, never>;
6837
6894
  }
6838
6895
  /** A note as the notes API returns it. */
@@ -6870,8 +6927,22 @@ export declare class NotesComponent {
6870
6927
  /** What the notes belong to, as the API names it: `contact`, `transaction`, `property`, `task`, ... */
6871
6928
  readonly resourceType: import("@angular/core").InputSignal<string>;
6872
6929
  readonly resourceId: import("@angular/core").InputSignal<string>;
6930
+ /**
6931
+ * Resource-specific notes API (optional). When set (e.g. `/permits/42/notes`, relative to `FORGEROUTE_CONFIG.baseUrl`), the component uses it instead of
6932
+ * the generic `/notes/{resourceType}/{resourceId}` API and `resourceType` / `resourceId` are not needed:
6933
+ * - `GET {basePath}?page=<0-based>&size=5` -> `{ content, totalElements, ... }` (`page` or Spring's `number` is accepted for the page index)
6934
+ * - `POST {basePath}` `{ content }` -> the new note
6935
+ * - `PUT {basePath}/{noteId}` `{ content }` (only when `editable` is true)
6936
+ * - `DELETE {basePath}/{noteId}`
6937
+ * A note's text may come as `body` or `content`; a missing `updatedAt` counts as `createdAt` (no "edited" tag). Empty (default) = the generic API.
6938
+ */
6939
+ readonly basePath: import("@angular/core").InputSignal<string>;
6873
6940
  /** True: list only, no add box, edit or delete. */
6874
6941
  readonly readOnly: import("@angular/core").InputSignal<boolean>;
6942
+ /** False hides the edit icon (for APIs without an update endpoint). Default true. */
6943
+ readonly editable: import("@angular/core").InputSignal<boolean>;
6944
+ /** Longest note, in characters after trimming (default `NOTES_MAX_LENGTH`, 10000). Set it to the API's column size, e.g. 255 for customer notes. */
6945
+ readonly maxLength: import("@angular/core").InputSignal<number>;
6875
6946
  /** Total number of notes after every load / add / delete. */
6876
6947
  readonly totalChange: import("@angular/core").OutputEmitterRef<number>;
6877
6948
  private readonly http;
@@ -6879,8 +6950,6 @@ export declare class NotesComponent {
6879
6950
  private readonly destroyRef;
6880
6951
  private readonly apiBase;
6881
6952
  readonly pageSize = 5;
6882
- /** The character limit of a note (see `NOTES_MAX_LENGTH`). */
6883
- readonly maxLength = 10000;
6884
6953
  readonly notes: import("@angular/core").WritableSignal<NoteItem[]>;
6885
6954
  readonly loading: import("@angular/core").WritableSignal<boolean>;
6886
6955
  readonly saving: import("@angular/core").WritableSignal<boolean>;
@@ -6898,6 +6967,12 @@ export declare class NotesComponent {
6898
6967
  /** True when the trimmed text is not empty and within the limit. */
6899
6968
  protected validBody(text: string): boolean;
6900
6969
  private get listUrl();
6970
+ private noteUrl;
6971
+ private get ready();
6972
+ /** Request body for create / update: `{ content }` for a `basePath` API, `{ body }` for the generic one. */
6973
+ private payload;
6974
+ /** Accepts `body` or `content` as the text and a missing `updatedAt`. */
6975
+ private normalize;
6901
6976
  constructor();
6902
6977
  loadPage(p: number): void;
6903
6978
  addNote(): void;
@@ -6918,11 +6993,26 @@ export declare class NotesComponent {
6918
6993
  "required": false;
6919
6994
  "isSignal": true;
6920
6995
  };
6996
+ "basePath": {
6997
+ "alias": "basePath";
6998
+ "required": false;
6999
+ "isSignal": true;
7000
+ };
6921
7001
  "readOnly": {
6922
7002
  "alias": "readOnly";
6923
7003
  "required": false;
6924
7004
  "isSignal": true;
6925
7005
  };
7006
+ "editable": {
7007
+ "alias": "editable";
7008
+ "required": false;
7009
+ "isSignal": true;
7010
+ };
7011
+ "maxLength": {
7012
+ "alias": "maxLength";
7013
+ "required": false;
7014
+ "isSignal": true;
7015
+ };
6926
7016
  }, {
6927
7017
  "totalChange": "totalChange";
6928
7018
  }, never, never, true, never>;