@forgeroute/ui 0.4.14 → 0.4.16

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.14",
3
+ "version": "0.4.16",
4
4
  "peerDependencies": {
5
5
  "@angular/common": ">=22.0.0",
6
6
  "@angular/core": ">=22.0.0",
@@ -398,6 +398,18 @@ export interface BulkActionEvent {
398
398
  value?: string;
399
399
  skippedCount: number;
400
400
  }
401
+ /** Emitted by (rowReorder) after the user moves a row (`reorderable`). */
402
+ export interface TableRowReorderEvent<T = any> {
403
+ /** The row that was moved. */
404
+ item: T;
405
+ /** Its index on the page before and after the move (0-based). */
406
+ from: number;
407
+ to: number;
408
+ /** The rows on the page in their new order. */
409
+ items: T[];
410
+ /** How many rows come before this page (0 on the first page), so `offset + to` is the row's position in the whole list. */
411
+ offset: number;
412
+ }
401
413
  export interface PageResponse<T> {
402
414
  content: T[];
403
415
  totalElements: number;
@@ -1307,6 +1319,16 @@ export declare class DataTableComponent<T extends Record<string, any>> implement
1307
1319
  readonly bulkAction: import("@angular/core").OutputEmitterRef<BulkActionEvent>;
1308
1320
  /** Emitted after a built-in single-row delete completes successfully. */
1309
1321
  readonly rowDeleted: import("@angular/core").OutputEmitterRef<T>;
1322
+ /**
1323
+ * Optional drag-and-drop ordering of the rows. Off by default; when `true` (and the user has full access) every row gets a grip
1324
+ * (drag it, or focus it and use the arrow keys / Home / End; phone cards get Move up / Move down buttons). Reordering is only
1325
+ * offered while the list is in its stored order: with a sort, search, quick tab or column filter active the grips are disabled
1326
+ * (their tooltip says why), because the visible order is then not the stored one. The move is applied to the page on screen at
1327
+ * once and announced as `(rowReorder)`; the host saves it (a failed save should call `refresh()` to bring back the stored order).
1328
+ */
1329
+ readonly reorderable: import("@angular/core").InputSignal<boolean>;
1330
+ /** Emitted after the user moves a row: `items` is the page in its new order, `from` / `to` are page indexes, `offset` is the number of rows on earlier pages. */
1331
+ readonly rowReorder: import("@angular/core").OutputEmitterRef<TableRowReorderEvent<T>>;
1310
1332
  private readonly config;
1311
1333
  private readonly http;
1312
1334
  private readonly destroyRef;
@@ -1400,6 +1422,33 @@ export declare class DataTableComponent<T extends Record<string, any>> implement
1400
1422
  protected readonly _toolbarButtons: Signal<ToolbarAction[]>;
1401
1423
  /** True while the table is empty and unfiltered but the host kept a More Actions item (`keepWhenEmpty`) — the menu stays. */
1402
1424
  protected readonly _keepMoreActions: Signal<boolean>;
1425
+ /** The reorder column is part of the table (the grips may still be disabled, see `_reorderActive`). */
1426
+ protected readonly _reorderOn: Signal<boolean>;
1427
+ /** Moves are allowed: the list is in its stored order (no sort / search / tab / filter), loaded, and has more than one row. */
1428
+ protected readonly _reorderActive: Signal<boolean>;
1429
+ protected readonly _reorderHint: Signal<"There is nothing to reorder" | "Clear the sort, search and filters to change the order">;
1430
+ /** One id per table, so each grip can point to the instructions (aria-describedby) even with several tables on a page. */
1431
+ protected readonly _reorderHelpId: string;
1432
+ protected readonly _dragFrom: import("@angular/core").WritableSignal<number | null>;
1433
+ /** Key of the row being dragged: the index can go stale if the page reloads mid-drag, the key cannot. */
1434
+ private _dragKey;
1435
+ protected readonly _dragOver: import("@angular/core").WritableSignal<number | null>;
1436
+ /** Polite screen-reader message after a move. */
1437
+ protected readonly _reorderAnnouncement: import("@angular/core").WritableSignal<string>;
1438
+ private readonly _host;
1439
+ protected reorderLabel(item: T): string;
1440
+ protected onGripDragStart(e: DragEvent, index: number): void;
1441
+ protected onGripDragEnd(): void;
1442
+ protected onRowDragOver(e: DragEvent, index: number): void;
1443
+ protected onRowDrop(e: DragEvent, index: number): void;
1444
+ protected onGripKeydown(e: KeyboardEvent, index: number): void;
1445
+ /**
1446
+ * A Move up / Move down button (touch screens and phone cards). The pressed button can end up disabled (the row reached an end), and a
1447
+ * focused control that gets disabled drops focus to the page, so focus goes to the row's other Move button then.
1448
+ */
1449
+ protected moveByButton(index: number, direction: -1 | 1): void;
1450
+ /** Moves the row at `from` to `to` (both page indexes) in the table and tells the host. false = nothing changed. */
1451
+ protected moveRow(from: number, to: number): boolean;
1403
1452
  protected readonly _hasActiveFilters: Signal<boolean>;
1404
1453
  /** Host `params` with empty values dropped; equal by content so a new object with the same values doesn't reload. */
1405
1454
  protected readonly _extraParams: Signal<Record<string, string>>;
@@ -1455,7 +1504,7 @@ export declare class DataTableComponent<T extends Record<string, any>> implement
1455
1504
  */
1456
1505
  private readonly _rowNameSuffix;
1457
1506
  /** A row's accessible name: its name, plus the position among rows of the same name when that name repeats on the page. */
1458
- private rowAccessibleName;
1507
+ protected rowAccessibleName(item: T): string;
1459
1508
  /** "Select Acme Electric" — a row's selection checkbox name ("Select Acme Electric (2 of 3)" when the name repeats on the page). */
1460
1509
  protected selectRowLabel(item: T): string;
1461
1510
  /**
@@ -1769,6 +1818,11 @@ export declare class DataTableComponent<T extends Record<string, any>> implement
1769
1818
  "required": false;
1770
1819
  "isSignal": true;
1771
1820
  };
1821
+ "reorderable": {
1822
+ "alias": "reorderable";
1823
+ "required": false;
1824
+ "isSignal": true;
1825
+ };
1772
1826
  }, {
1773
1827
  "rowClick": "rowClick";
1774
1828
  "linkClick": "linkClick";
@@ -1782,6 +1836,7 @@ export declare class DataTableComponent<T extends Record<string, any>> implement
1782
1836
  "tabChange": "tabChange";
1783
1837
  "bulkAction": "bulkAction";
1784
1838
  "rowDeleted": "rowDeleted";
1839
+ "rowReorder": "rowReorder";
1785
1840
  }, never, never, true, never>;
1786
1841
  }
1787
1842
  /**
@@ -2390,7 +2445,8 @@ export declare class TooltipDirective {
2390
2445
  /**
2391
2446
  * A small gold star with a hover / focus tooltip: `<ui-star tooltip="Authorization Form" />`.
2392
2447
  *
2393
- * The star is always gold (there is no color input). `tooltip` is the text the user sees on hover or keyboard focus (library `uiTooltip`);
2448
+ * The star is gold by default (there is no color input); `[filled]="false"` draws an uncolored outline star instead, and `[interactive]="true"`
2449
+ * makes it a button that emits `(starClick)` — e.g. an outline star "Click to make primary photo" next to the gold primary one. `tooltip` is the text the user sees on hover or keyboard focus (library `uiTooltip`);
2394
2450
  * it is also the star's accessible name, so a screen reader reads it too. Without a tooltip the star is decorative (hidden from assistive tech).
2395
2451
  * In `<ui-data-table>` use `ColumnDef.starFn` to put one to the left of a text cell (e.g. the name column).
2396
2452
  */
@@ -2399,6 +2455,11 @@ export declare class StarComponent {
2399
2455
  readonly tooltip: import("@angular/core").InputSignal<string>;
2400
2456
  /** Star size in px. Default 16. */
2401
2457
  readonly size: import("@angular/core").InputSignal<number>;
2458
+ /** true (default) = the gold star. false = an uncolored outline star (e.g. "not the primary one"). */
2459
+ readonly filled: import("@angular/core").InputSignal<boolean>;
2460
+ /** true = the star is a real button (keyboard + click) that emits `starClick`; `tooltip` is then its accessible name. Default false (a plain marker). */
2461
+ readonly interactive: import("@angular/core").InputSignal<boolean>;
2462
+ readonly starClick: import("@angular/core").OutputEmitterRef<MouseEvent>;
2402
2463
  protected readonly hasTooltip: import("@angular/core").Signal<boolean>;
2403
2464
  static ɵfac: i0.ɵɵFactoryDeclaration<StarComponent, never>;
2404
2465
  static ɵcmp: i0.ɵɵComponentDeclaration<StarComponent, "ui-star", never, {
@@ -2412,7 +2473,19 @@ export declare class StarComponent {
2412
2473
  "required": false;
2413
2474
  "isSignal": true;
2414
2475
  };
2415
- }, {}, never, never, true, never>;
2476
+ "filled": {
2477
+ "alias": "filled";
2478
+ "required": false;
2479
+ "isSignal": true;
2480
+ };
2481
+ "interactive": {
2482
+ "alias": "interactive";
2483
+ "required": false;
2484
+ "isSignal": true;
2485
+ };
2486
+ }, {
2487
+ "starClick": "starClick";
2488
+ }, never, never, true, never>;
2416
2489
  }
2417
2490
  export type ImageRepositionShape = 'circle' | 'rounded';
2418
2491
  /**
@@ -4085,6 +4158,54 @@ export declare class ErrorStateComponent {
4085
4158
  "retry": "retry";
4086
4159
  }, never, never, true, never>;
4087
4160
  }
4161
+ /** One password rule: `test` decides whether the typed password satisfies it. */
4162
+ export interface PasswordRule {
4163
+ id: string;
4164
+ label: string;
4165
+ test: (password: string) => boolean;
4166
+ }
4167
+ /** The default rules (same as the backends): 8+ characters, an uppercase letter, a lowercase letter, a digit and a special character. */
4168
+ export declare const DEFAULT_PASSWORD_RULES: readonly PasswordRule[];
4169
+ /** True when the password satisfies every rule (default: {@link DEFAULT_PASSWORD_RULES}). Use it to gate Save. */
4170
+ export declare function passwordMeetsRules(password: string, rules?: readonly PasswordRule[]): boolean;
4171
+ /**
4172
+ * The password requirements checklist. Pass the typed password; each rule shows as a row that turns green with a check mark once it is
4173
+ * satisfied, and stays grey with an empty circle until then. There is no "(met)" text: the state is also in `data-met` and in
4174
+ * visually hidden text for screen readers, so it is not colour alone.
4175
+ *
4176
+ * Also available as `<ui-text-input type="password" [passwordRequirements]="true">`, which shows this list under the field.
4177
+ */
4178
+ export declare class PasswordRequirementsComponent {
4179
+ /** The password to check. */
4180
+ readonly value: import("@angular/core").InputSignal<string>;
4181
+ /** Rules to show; default {@link DEFAULT_PASSWORD_RULES}. */
4182
+ readonly rules: import("@angular/core").InputSignal<readonly PasswordRule[]>;
4183
+ readonly title: import("@angular/core").InputSignal<string>;
4184
+ protected readonly _check: string;
4185
+ protected readonly _results: import("@angular/core").Signal<{
4186
+ id: string;
4187
+ label: string;
4188
+ met: boolean;
4189
+ }[]>;
4190
+ static ɵfac: i0.ɵɵFactoryDeclaration<PasswordRequirementsComponent, never>;
4191
+ static ɵcmp: i0.ɵɵComponentDeclaration<PasswordRequirementsComponent, "ui-password-requirements", never, {
4192
+ "value": {
4193
+ "alias": "value";
4194
+ "required": false;
4195
+ "isSignal": true;
4196
+ };
4197
+ "rules": {
4198
+ "alias": "rules";
4199
+ "required": false;
4200
+ "isSignal": true;
4201
+ };
4202
+ "title": {
4203
+ "alias": "title";
4204
+ "required": false;
4205
+ "isSignal": true;
4206
+ };
4207
+ }, {}, never, never, true, never>;
4208
+ }
4088
4209
  export declare class TextInputComponent implements ControlValueAccessor, Validator, UiFieldValidity {
4089
4210
  readonly label: import("@angular/core").InputSignal<string>;
4090
4211
  /** Accessible name for a field with no visible label (e.g. an inline cell or title input). */
@@ -4096,6 +4217,18 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
4096
4217
  * Meant for a short mark of 1-3 characters.
4097
4218
  */
4098
4219
  readonly prefix: import("@angular/core").InputSignal<string>;
4220
+ /**
4221
+ * `type="password"` only: puts an eye button inside the field, at its right end, that shows / hides the typed text (the eye with a slash
4222
+ * means "hidden again"). Per field, starts hidden; the button is a toggle (`aria-pressed`) named "Show password". Ignored for other types.
4223
+ */
4224
+ readonly revealable: import("@angular/core").InputSignal<boolean>;
4225
+ /**
4226
+ * `type="password"` only: shows the password requirements checklist under the field (`ui-password-requirements`) once the user has typed
4227
+ * (it hides again when the host clears the field, e.g. after a successful change). Each rule turns green with a check when satisfied. Off by default; ignored for other types.
4228
+ */
4229
+ readonly passwordRequirements: import("@angular/core").InputSignal<boolean>;
4230
+ /** Rules for `passwordRequirements`; default = the library's five rules (8+ characters, upper, lower, digit, special). */
4231
+ readonly passwordRules: import("@angular/core").InputSignal<readonly PasswordRule[] | undefined>;
4099
4232
  readonly type: import("@angular/core").InputSignal<"number" | "text" | "email" | "tel" | "password" | "url">;
4100
4233
  readonly maxlength: import("@angular/core").InputSignal<number | undefined>;
4101
4234
  readonly required: import("@angular/core").InputSignal<boolean>;
@@ -4167,6 +4300,17 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
4167
4300
  private readonly _numeric;
4168
4301
  /** The native `step` attribute: only for `type="number"` and only for a finite number above 0; otherwise none (the browser's step of 1). */
4169
4302
  protected readonly _stepAttr: import("@angular/core").Signal<string | null>;
4303
+ protected readonly _revealable: import("@angular/core").Signal<boolean>;
4304
+ protected readonly _shown: import("@angular/core").WritableSignal<boolean>;
4305
+ protected readonly _inputType: import("@angular/core").Signal<"number" | "text" | "email" | "tel" | "password" | "url">;
4306
+ protected readonly _eyePath: string;
4307
+ protected readonly _eyeOffPath: string;
4308
+ protected readonly _showRequirements: import("@angular/core").Signal<boolean>;
4309
+ /** `aria-describedby`: the error / hint text and, while the requirements checklist is shown, the checklist (so a screen reader reads the rules with the field). */
4310
+ protected readonly _describedBy: import("@angular/core").Signal<string | null>;
4311
+ /** True once the user typed in the field; a host-written empty value (a form reset) puts it back to false. */
4312
+ private readonly _typed;
4313
+ protected readonly _defaultRules: readonly PasswordRule[];
4170
4314
  private _warned;
4171
4315
  private readonly _formatting;
4172
4316
  private readonly _issue;
@@ -4221,6 +4365,21 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
4221
4365
  "required": false;
4222
4366
  "isSignal": true;
4223
4367
  };
4368
+ "revealable": {
4369
+ "alias": "revealable";
4370
+ "required": false;
4371
+ "isSignal": true;
4372
+ };
4373
+ "passwordRequirements": {
4374
+ "alias": "passwordRequirements";
4375
+ "required": false;
4376
+ "isSignal": true;
4377
+ };
4378
+ "passwordRules": {
4379
+ "alias": "passwordRules";
4380
+ "required": false;
4381
+ "isSignal": true;
4382
+ };
4224
4383
  "type": {
4225
4384
  "alias": "type";
4226
4385
  "required": false;
@@ -6716,7 +6875,7 @@ export declare class AlertComponent {
6716
6875
  /** The SVG path (24×24 stroke icon) for an icon key, or undefined when the key is unknown. */
6717
6876
  export declare function iconPath(name: string): string | undefined;
6718
6877
  /** Keys with an icon of their own (the data-table action keys are accepted too — see `builtInActionIcon`). */
6719
- export type IconName = 'add' | 'close' | 'check' | 'upload' | 'image' | 'chevron-up' | 'chevron-down' | 'arrow-left' | 'bell' | 'print' | 'lock' | 'shield' | 'arrow-up' | 'arrow-down' | 'arrow-right' | 'document' | 'grip' | 'card' | 'bank' | 'view' | 'edit' | 'delete' | 'download' | 'duplicate' | 'archive' | 'restore' | 'share' | 'email' | 'message' | 'call';
6878
+ export type IconName = 'add' | 'close' | 'check' | 'upload' | 'image' | 'chevron-up' | 'chevron-down' | 'arrow-left' | 'bell' | 'print' | 'lock' | 'shield' | 'arrow-up' | 'arrow-down' | 'arrow-right' | 'document' | 'grip' | 'card' | 'bank' | 'view' | 'view-off' | 'edit' | 'delete' | 'download' | 'duplicate' | 'archive' | 'restore' | 'share' | 'email' | 'message' | 'call';
6720
6879
  /**
6721
6880
  * A clickable icon. The host passes a key (`name="delete"`) and the library draws that icon; clicking it emits
6722
6881
  * `iconClick`, and the host does the actual work (delete the row, open a panel, …).