@mintplayer/ng-spark 22.23.0 → 22.24.0

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.
Files changed (68) hide show
  1. package/README.md +181 -0
  2. package/fesm2022/mintplayer-ng-spark-attribute-description.mjs +100 -47
  3. package/fesm2022/mintplayer-ng-spark-attribute-description.mjs.map +1 -1
  4. package/fesm2022/mintplayer-ng-spark-client-operations.mjs +308 -329
  5. package/fesm2022/mintplayer-ng-spark-client-operations.mjs.map +1 -1
  6. package/fesm2022/mintplayer-ng-spark-column-filter.mjs +175 -135
  7. package/fesm2022/mintplayer-ng-spark-column-filter.mjs.map +1 -1
  8. package/fesm2022/mintplayer-ng-spark-grid.mjs +2259 -1119
  9. package/fesm2022/mintplayer-ng-spark-grid.mjs.map +1 -1
  10. package/fesm2022/mintplayer-ng-spark-history.mjs +611 -0
  11. package/fesm2022/mintplayer-ng-spark-history.mjs.map +1 -0
  12. package/fesm2022/mintplayer-ng-spark-icon.mjs +64 -27
  13. package/fesm2022/mintplayer-ng-spark-icon.mjs.map +1 -1
  14. package/fesm2022/mintplayer-ng-spark-models.mjs +366 -762
  15. package/fesm2022/mintplayer-ng-spark-models.mjs.map +1 -1
  16. package/fesm2022/mintplayer-ng-spark-moderation.mjs +1212 -0
  17. package/fesm2022/mintplayer-ng-spark-moderation.mjs.map +1 -0
  18. package/fesm2022/mintplayer-ng-spark-panels.mjs +52 -0
  19. package/fesm2022/mintplayer-ng-spark-panels.mjs.map +1 -0
  20. package/fesm2022/mintplayer-ng-spark-pipes.mjs +1122 -765
  21. package/fesm2022/mintplayer-ng-spark-pipes.mjs.map +1 -1
  22. package/fesm2022/mintplayer-ng-spark-po-create.mjs +273 -169
  23. package/fesm2022/mintplayer-ng-spark-po-create.mjs.map +1 -1
  24. package/fesm2022/mintplayer-ng-spark-po-detail.mjs +786 -410
  25. package/fesm2022/mintplayer-ng-spark-po-detail.mjs.map +1 -1
  26. package/fesm2022/mintplayer-ng-spark-po-edit.mjs +292 -284
  27. package/fesm2022/mintplayer-ng-spark-po-edit.mjs.map +1 -1
  28. package/fesm2022/mintplayer-ng-spark-po-form.mjs +2187 -1225
  29. package/fesm2022/mintplayer-ng-spark-po-form.mjs.map +1 -1
  30. package/fesm2022/mintplayer-ng-spark-query-list.mjs +516 -303
  31. package/fesm2022/mintplayer-ng-spark-query-list.mjs.map +1 -1
  32. package/fesm2022/mintplayer-ng-spark-renderers.mjs +17 -55
  33. package/fesm2022/mintplayer-ng-spark-renderers.mjs.map +1 -1
  34. package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs +216 -177
  35. package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs.map +1 -1
  36. package/fesm2022/mintplayer-ng-spark-routes.mjs +24 -28
  37. package/fesm2022/mintplayer-ng-spark-routes.mjs.map +1 -1
  38. package/fesm2022/mintplayer-ng-spark-services.mjs +625 -640
  39. package/fesm2022/mintplayer-ng-spark-services.mjs.map +1 -1
  40. package/fesm2022/mintplayer-ng-spark-shell.mjs +1013 -397
  41. package/fesm2022/mintplayer-ng-spark-shell.mjs.map +1 -1
  42. package/fesm2022/mintplayer-ng-spark-soft-delete.mjs +294 -0
  43. package/fesm2022/mintplayer-ng-spark-soft-delete.mjs.map +1 -0
  44. package/fesm2022/mintplayer-ng-spark.mjs +13 -50
  45. package/fesm2022/mintplayer-ng-spark.mjs.map +1 -1
  46. package/package.json +17 -1
  47. package/types/mintplayer-ng-spark-attribute-description.d.ts +25 -18
  48. package/types/mintplayer-ng-spark-client-operations.d.ts +133 -160
  49. package/types/mintplayer-ng-spark-column-filter.d.ts +73 -55
  50. package/types/mintplayer-ng-spark-grid.d.ts +885 -448
  51. package/types/mintplayer-ng-spark-history.d.ts +223 -0
  52. package/types/mintplayer-ng-spark-icon.d.ts +15 -13
  53. package/types/mintplayer-ng-spark-models.d.ts +624 -573
  54. package/types/mintplayer-ng-spark-moderation.d.ts +402 -0
  55. package/types/mintplayer-ng-spark-panels.d.ts +108 -0
  56. package/types/mintplayer-ng-spark-pipes.d.ts +120 -149
  57. package/types/mintplayer-ng-spark-po-create.d.ts +46 -37
  58. package/types/mintplayer-ng-spark-po-detail.d.ts +177 -117
  59. package/types/mintplayer-ng-spark-po-edit.d.ts +64 -65
  60. package/types/mintplayer-ng-spark-po-form.d.ts +507 -371
  61. package/types/mintplayer-ng-spark-query-list.d.ts +118 -82
  62. package/types/mintplayer-ng-spark-renderers.d.ts +79 -85
  63. package/types/mintplayer-ng-spark-retry-action-modal.d.ts +31 -34
  64. package/types/mintplayer-ng-spark-routes.d.ts +7 -11
  65. package/types/mintplayer-ng-spark-services.d.ts +377 -261
  66. package/types/mintplayer-ng-spark-shell.d.ts +209 -128
  67. package/types/mintplayer-ng-spark-soft-delete.d.ts +90 -0
  68. package/types/mintplayer-ng-spark.d.ts +7 -12
@@ -1,23 +1,21 @@
1
- import * as _angular_core from '@angular/core';
2
- import { Type } from '@angular/core';
3
- import { CdkDragDrop } from '@angular/cdk/drag-drop';
4
- import { Color } from '@mintplayer/ng-bootstrap';
5
- import { InMemoryTreeSelectProvider, TreeNode } from '@mintplayer/ng-bootstrap/tree-select';
6
- import * as _mintplayer_ng_spark_models from '@mintplayer/ng-spark/models';
7
- import { PersistentObject, EntityType, ValidationError, RefreshOverlay, QueryResultItem, LookupReference, EntityAttributeDefinition, EntityPermissions, ELookupDisplayType, EReferenceDisplayType, AttributeTab, AttributeGroup, LookupReferenceValue, RuleFailure } from '@mintplayer/ng-spark/models';
8
- import { DatatableSettings } from '@mintplayer/ng-bootstrap/datatable';
9
- import { PaginationResponse } from '@mintplayer/pagination';
10
-
1
+ import * as i0 from "@angular/core";
2
+ import { Type } from "@angular/core";
3
+ import { CdkDragDrop } from "@angular/cdk/drag-drop";
4
+ import { Color } from "@mintplayer/ng-bootstrap";
5
+ import { InMemoryTreeSelectProvider, TreeNode } from "@mintplayer/ng-bootstrap/tree-select";
6
+ import { AttributeGroup, AttributeTab, ELookupDisplayType, EReferenceDisplayType, EntityAttributeDefinition, EntityPermissions, EntityType, LookupReference, LookupReferenceValue, PersistentObject, QueryResultItem, RefreshOverlay, RuleFailure, ValidationError } from "@mintplayer/ng-spark/models";
7
+ import { DatatableSettings } from "@mintplayer/ng-bootstrap/datatable";
8
+ import { PaginationResponse } from "@mintplayer/pagination";
11
9
  /** What the coordinator needs from its host, so it can be tested without mounting a form. */
12
10
  interface RefreshCoordinatorHost {
13
- /** POSTs the object and resolves with the reshaped one. */
14
- send(triggeredBy: string): Promise<PersistentObject>;
15
- /** Values as they are right now — read at dispatch time to snapshot what is being sent. */
16
- currentValues(): Record<string, any>;
17
- /** Applies a settled response. Not called for a superseded one. */
18
- apply(response: PersistentObject, sent: Record<string, any>): void;
19
- /** Surfaced so the host can show a busy affordance. Never used to disable fields. */
20
- setBusy(busy: boolean): void;
11
+ /** POSTs the object and resolves with the reshaped one. */
12
+ send(triggeredBy: string): Promise<PersistentObject>;
13
+ /** Values as they are right now — read at dispatch time to snapshot what is being sent. */
14
+ currentValues(): Record<string, any>;
15
+ /** Applies a settled response. Not called for a superseded one. */
16
+ apply(response: PersistentObject, sent: Record<string, any>): void;
17
+ /** Surfaced so the host can show a busy affordance. Never used to disable fields. */
18
+ setBusy(busy: boolean): void;
21
19
  }
22
20
  /**
23
21
  * Serializes refreshes for **one** form instance and drops superseded ones.
@@ -32,308 +30,389 @@ interface RefreshCoordinatorHost {
32
30
  * response *will* arrive. It is discarded by sequence number rather than prevented.
33
31
  */
34
32
  declare class RefreshCoordinator {
35
- private readonly host;
36
- private queue;
37
- private sequence;
38
- private settled;
39
- private pending;
40
- constructor(host: RefreshCoordinatorHost);
41
- /** Whether a refresh is in flight. */
42
- get isRefreshing(): boolean;
43
- /**
44
- * Marks `attributeName` as needing a refresh without sending one — for free-text editors, which
45
- * would otherwise issue a request per keystroke. Flushed by {@link blur} or {@link flush}.
46
- */
47
- markPending(attributeName: string): void;
48
- /** Sends a pending refresh for `attributeName`, if one was marked. */
49
- blur(attributeName: string): Promise<void>;
50
- /**
51
- * Sends every refresh still marked pending. Called before save, so a value typed and never blurred
52
- * — the user tabbing straight to the save button — is still reflected before the object goes.
53
- */
54
- flush(): Promise<void>;
55
- /** Sends a refresh immediately — discrete editors, where every change is a committed one. */
56
- trigger(attributeName: string): Promise<void>;
33
+ private readonly host;
34
+ private queue;
35
+ private sequence;
36
+ private settled;
37
+ private pending;
38
+ constructor(host: RefreshCoordinatorHost);
39
+ /** Whether a refresh is in flight. */
40
+ get isRefreshing(): boolean;
41
+ /**
42
+ * Marks `attributeName` as needing a refresh without sending one — for free-text editors, which
43
+ * would otherwise issue a request per keystroke. Flushed by {@link blur} or {@link flush}.
44
+ */
45
+ markPending(attributeName: string): void;
46
+ /** Sends a pending refresh for `attributeName`, if one was marked. */
47
+ blur(attributeName: string): Promise<void>;
48
+ /**
49
+ * Sends every refresh still marked pending. Called before save, so a value typed and never blurred
50
+ * — the user tabbing straight to the save button — is still reflected before the object goes.
51
+ */
52
+ flush(): Promise<void>;
53
+ /** Sends a refresh immediately — discrete editors, where every change is a committed one. */
54
+ trigger(attributeName: string): Promise<void>;
55
+ }
56
+ /** The subset of an attribute definition that decides how its editor behaves. */
57
+ interface RefreshTriggerShape {
58
+ dataType?: string;
59
+ lookupReferenceType?: string;
60
+ isArray?: boolean;
57
61
  }
58
-
62
+ /**
63
+ * Editors where every change is a deliberate, committed one, so a refresh fires immediately.
64
+ * Everything else is free text, where firing per keystroke would be unacceptable and the refresh
65
+ * waits for blur.
66
+ *
67
+ * ⚠️ This asks how the attribute is **rendered**, not what its `dataType` says, and the difference
68
+ * is not academic. A lookup attribute carries the data type of its *key* — Fleet's `Car.Status` is
69
+ * `dataType: "string"` with `lookupReferenceType: "CarStatus"` — so keying on `dataType` alone
70
+ * classifies a `<bs-select>` as free text. It then waits for a blur that a select never emits, and
71
+ * the refresh simply never fires: no request, no error, nothing to see.
72
+ */
73
+ declare function triggersImmediately(attr: RefreshTriggerShape | undefined): boolean;
74
+ /** Empty overlay, so callers do not have to spell the type. */
75
+ declare const NO_OVERLAY: RefreshOverlay;
59
76
  /**
60
77
  * A refresh a form embedded in another form is asking its host to issue on its behalf.
61
78
  *
62
79
  * `immediate` mirrors the distinction the host's own editors make: a discrete editor fires on
63
80
  * change, free text only marks itself pending and fires on blur.
64
81
  */
65
- interface NestedTriggerRequest {
66
- /** The full path the server addresses, e.g. `Gate.ProjectMode`. */
67
- path: string;
68
- immediate: boolean;
82
+ export interface NestedTriggerRequest {
83
+ /** The full path the server addresses, e.g. `Gate.ProjectMode`. */
84
+ path: string;
85
+ immediate: boolean;
69
86
  }
70
- declare class SparkPoFormComponent {
71
- private readonly sparkService;
72
- private readonly translations;
73
- private readonly rendererRegistry;
74
- entityType: _angular_core.InputSignal<EntityType | null>;
75
- formData: _angular_core.ModelSignal<Record<string, any>>;
76
- validationErrors: _angular_core.InputSignal<ValidationError[]>;
77
- showButtons: _angular_core.InputSignal<boolean>;
78
- isSaving: _angular_core.InputSignal<boolean>;
79
- parentId: _angular_core.InputSignal<string | undefined>;
80
- parentType: _angular_core.InputSignal<string | undefined>;
81
- save: _angular_core.OutputEmitterRef<void>;
82
- cancel: _angular_core.OutputEmitterRef<void>;
83
- /**
84
- * The type id to refresh against. Absent means refresh is unavailable — the form still renders and
85
- * edits normally, so a host that has not opted in loses nothing.
86
- */
87
- objectTypeId: _angular_core.InputSignal<string | undefined>;
88
- /** The id of the object being edited; absent for a create. */
89
- objectId: _angular_core.InputSignal<string | undefined>;
90
- /**
91
- * Set when this form renders a single embedded AsDetail object inside a host form: the name of
92
- * the attribute holding it, e.g. `"Gate"`. Presence of a prefix switches the form from issuing
93
- * its own refreshes to reporting them upward, because an embedded object is not something the
94
- * server can be asked about on its own — the request must describe, and be authorized against,
95
- * the object that owns it.
96
- */
97
- triggerPathPrefix: _angular_core.InputSignal<string | null>;
98
- /** Raised instead of self-issuing when {@link triggerPathPrefix} is set. */
99
- nestedTriggerRequested: _angular_core.OutputEmitterRef<NestedTriggerRequest>;
100
- /** Blur counterpart, flushing a trigger the host only marked pending. */
101
- nestedTriggerBlurred: _angular_core.OutputEmitterRef<string>;
102
- /**
103
- * What the last refresh changed about each attribute's presentation, keyed by attribute name.
104
- *
105
- * Deliberately NOT folded back into `entityType`. All option loading hangs off one effect keyed on
106
- * `entityType` identity and `SparkService` caches nothing, so re-setting it would re-issue every
107
- * reference query and lookup fetch on every refresh; mutating it in place would not re-render at
108
- * all.
109
- *
110
- * ⚠️ A `model`, not a plain signal, because the page that owns the save has to see it. This form
111
- * renders from the overlaid attribute list; `spark-po-edit` and `spark-po-create` build the
112
- * payload from their own copy of the same filter. While the overlay stopped here, those two
113
- * filtered on the attribute's state *as loaded* — so an attribute a refresh hook revealed was
114
- * rendered, filled in by the user, and then silently left out of the save. When the same hook also
115
- * made it required (the ordinary case — a field appears *because* it is now needed) the server
116
- * refused the save for the very field the user had just filled, and the form became a dead end
117
- * with no way forward from inside it.
118
- */
119
- refreshOverlay: _angular_core.ModelSignal<RefreshOverlay>;
120
- isRefreshing: _angular_core.WritableSignal<boolean>;
121
- colors: typeof Color;
122
- referenceOptions: _angular_core.WritableSignal<Record<string, QueryResultItem[]>>;
123
- referenceProviders: _angular_core.WritableSignal<Record<string, InMemoryTreeSelectProvider>>;
124
- referenceNodes: _angular_core.WritableSignal<Record<string, Record<string, TreeNode>>>;
125
- asDetailTypes: _angular_core.WritableSignal<Record<string, EntityType>>;
126
- lookupReferenceOptions: _angular_core.WritableSignal<Record<string, LookupReference>>;
127
- editingAsDetailAttr: _angular_core.WritableSignal<EntityAttributeDefinition | null>;
128
- asDetailFormData: _angular_core.WritableSignal<Record<string, any>>;
129
- showAsDetailModal: _angular_core.WritableSignal<boolean>;
130
- editingArrayIndex: _angular_core.WritableSignal<number | null>;
131
- asDetailPermissions: _angular_core.WritableSignal<Record<string, EntityPermissions>>;
132
- /**
133
- * What the server said when it refused to construct or release a row.
134
- *
135
- * A local signal rather than the `validationErrors` input, because this is the one class of error
136
- * the form raises on its own behalf: `validationErrors` is owned by the host (po-edit / po-create)
137
- * and arrives from a save. Cleared at the start of each lifecycle call, so a stale refusal never
138
- * outlives the click that caused it.
139
- *
140
- * Keyed by attribute name so a message renders against the grid it came from. A single global
141
- * alert would have been less code and worse: a form with two detail grids would show one grid's
142
- * refusal above the other, and the user's next click is on the grid, not the top of the page.
143
- */
144
- rowLifecycleErrors: _angular_core.WritableSignal<Record<string, ValidationError[]>>;
145
- /** The refusal to render under `attrName`'s grid, if any. */
146
- rowLifecycleErrorsFor(attrName: string): ValidationError[];
147
- asDetailReferenceOptions: _angular_core.WritableSignal<Record<string, Record<string, QueryResultItem[]>>>;
148
- ELookupDisplayType: typeof ELookupDisplayType;
149
- EReferenceDisplayType: typeof EReferenceDisplayType;
150
- /**
151
- * Every attribute this form could ever need option data for — including ones the model hides,
152
- * because a refresh may reveal them.
153
- *
154
- * Read by the option-loading effect, and deliberately independent of `refreshOverlay`: the loaders
155
- * read this synchronously, so an overlay dependency here would make every refresh re-issue every
156
- * reference query and lookup fetch. That is the whole reason the overlay is a separate signal.
157
- */
158
- optionSourceAttributes: _angular_core.Signal<EntityAttributeDefinition[]>;
159
- editableAttributes: _angular_core.Signal<EntityAttributeDefinition[]>;
160
- private static readonly DEFAULT_TAB;
161
- ungroupedAttributes: _angular_core.Signal<EntityAttributeDefinition[]>;
162
- resolvedTabs: _angular_core.Signal<AttributeTab[]>;
163
- groupsForTab(tab: AttributeTab): AttributeGroup[];
164
- attrsForGroup(group: AttributeGroup): EntityAttributeDefinition[];
165
- constructor();
166
- private toRecord;
167
- loadReferenceOptions(): Promise<void>;
168
- /**
169
- * Stable TreeNode[] value per multi-reference attribute, derived from the id array
170
- * in formData and the resolved node map. Recomputes only when formData or the node
171
- * map changes, so binding it into <bs-tree-select> doesn't churn on every CD pass.
172
- * Ids without a resolved node fall back to a label of the id itself.
173
- */
174
- referenceTreeValues: _angular_core.Signal<Record<string, TreeNode[]>>;
175
- getReferenceProvider(attr: EntityAttributeDefinition): InMemoryTreeSelectProvider | undefined;
176
- onReferenceTreeChange(attr: EntityAttributeDefinition, value: TreeNode | TreeNode[] | null): void;
177
- loadAsDetailTypes(): Promise<void>;
178
- loadLookupReferenceOptions(): Promise<void>;
179
- getLookupOptions(attr: EntityAttributeDefinition): LookupReferenceValue[];
180
- onReferenceValueChange(attr: EntityAttributeDefinition, id: string | null): void;
181
- onLookupValueChange(attr: EntityAttributeDefinition, key: string | null): void;
182
- getEditRendererComponent(attr: EntityAttributeDefinition): Type<any> | null;
183
- getEditRendererInputs(component: Type<any>, attr: EntityAttributeDefinition): Record<string, any>;
184
- /** Column renderer for a cell of an AsDetail sub-table (so embedded rows honor `col.renderer` too). */
185
- getAsDetailCellRendererComponent(col: EntityAttributeDefinition): Type<any> | null;
186
- getAsDetailCellRendererInputs(component: Type<any>, row: Record<string, any>, col: EntityAttributeDefinition): Record<string, any>;
187
- /** Edit-renderer for an inline AsDetail cell (so inline editing honors `col.renderer`, not just display). */
188
- getAsDetailCellEditRenderer(col: EntityAttributeDefinition): Type<any> | null;
189
- getAsDetailCellEditRendererInputs(component: Type<any>, row: Record<string, any>, col: EntityAttributeDefinition): Record<string, any>;
190
- /**
191
- * Rules evaluated in the browser, against the *effective* metadata — so a rule a refresh hook
192
- * imposed is visible before the round-trip rather than only after the server rejects the save.
193
- */
194
- clientRuleFailures: _angular_core.Signal<RuleFailure[]>;
195
- hasError(attrName: string): boolean;
196
- private inlineErrorPath;
197
- hasInlineError(attr: EntityAttributeDefinition, rowIndex: number, col: EntityAttributeDefinition): boolean;
198
- inlineErrorMessage(attr: EntityAttributeDefinition, rowIndex: number, col: EntityAttributeDefinition): string | null;
199
- /**
200
- * The single funnel every scalar / boolean / inline-cell edit passes through.
201
- *
202
- * `attr` is optional because some editors have nothing useful to say about which attribute moved.
203
- * A caller that knows should always say so — without it no refresh can fire.
204
- */
205
- onFieldChange(attr?: EntityAttributeDefinition): void;
206
- /**
207
- * A trigger inside an AsDetail row. Addressed by the same `{attr}[{index}].{col}` path the inline
208
- * validation errors already use, so the server can tell which row asked without a second
209
- * addressing scheme being invented for it.
210
- */
211
- onInlineCellChange(attr: EntityAttributeDefinition, rowIndex: number, col: EntityAttributeDefinition): void;
212
- /**
213
- * Which embedded target the in-flight refresh belongs to, if any.
214
- *
215
- * ⚠️ Tagged, not a nullable `rowIndex`. The two arms write to different places — a row inside
216
- * `formData`, versus the modal's working copy in `asDetailFormData` — and an index that happens
217
- * to be absent is not the same statement as "this attribute holds one object". With a nullable
218
- * index, a row refresh carrying a bad index would fall silently into the object arm.
219
- */
220
- private pendingNestedTrigger;
221
- /**
222
- * A trigger inside a single embedded AsDetail object, raised by the modal's recursive form.
223
- *
224
- * The child form does not issue the request itself, for two reasons that both bite. Its
225
- * `entityType` is the embedded type, so a payload built there describes `GateSettings` while the
226
- * request must describe the Repository that owns it. And nested AsDetail types carry no rights of
227
- * their own — the server authorizes a nested refresh on the OWNING type — so a child-issued
228
- * request would be asking the wrong question of security.json.
229
- */
230
- onEmbeddedTrigger(attributeName: string, event: NestedTriggerRequest): void;
231
- /** Blur counterpart of {@link onEmbeddedTrigger}, for the child's free-text editors. */
232
- onEmbeddedTriggerBlur(path: string): void;
233
- /**
234
- * Applies a refresh that ran against a detail row: the row's own values, and the column metadata
235
- * for the grid it lives in.
236
- *
237
- * The column metadata comes from `asDetailTypes` — a different signal from `entityType` — which is
238
- * why a nested response cannot go through the top-level overlay.
239
- *
240
- * ⚠️ The row array is mutated in place rather than replaced. Rows are tracked by index, so handing
241
- * the template a new array destroys and rebuilds every row's DOM and takes focus with it, mid-edit.
242
- */
243
- private applyNestedResponse;
244
- onInlineCellBlur(attr: EntityAttributeDefinition, rowIndex: number, col: EntityAttributeDefinition): void;
245
- /** Blur handler for free-text editors — sends the refresh their keystrokes only marked pending. */
246
- onFieldBlur(attr: EntityAttributeDefinition): void;
247
- private noteChange;
248
- /** `Gate.ProjectMode` — the index-free counterpart of the inline grid's `Jobs[1].Kind`. */
249
- private nestedTriggerPath;
250
- private canRefresh;
251
- /**
252
- * Per-instance, never a service: the retry-action modal renders its own `spark-po-form`, and a
253
- * refresh may carry a retry operation — so a refresh can open a modal containing a form that
254
- * refreshes. A shared coordinator would let the nested form supersede this one's request.
255
- */
256
- protected readonly refreshCoordinator: RefreshCoordinator;
257
- private buildRefreshPayload;
258
- /**
259
- * The values to post, with the open modal's working copy substituted for the attribute it edits.
260
- *
261
- * ⚠️ Without this the server receives the embedded object as it was when the modal opened — `{}`
262
- * for a gate that has never been set — and the hook decides against values the user cannot see it
263
- * ignoring. `formData` deliberately does not hold the in-progress edit (cancelling the modal has
264
- * to discard it), so the refresh has to reach into `asDetailFormData` instead. Only the attribute
265
- * under edit is substituted; everything else is the form's own state.
266
- */
267
- private embeddedValues;
268
- /**
269
- * Folds replaced option lists into the signals the editors already read, so a refreshed dropdown
270
- * renders through the same path as a loaded one.
271
- *
272
- * `undefined` means the hook did not touch this attribute's options and the loaded set stands; an
273
- * empty array means it deliberately left none. Collapsing the two would blank every dropdown the
274
- * hook never mentioned.
275
- */
276
- private applyRefreshedOptions;
277
- /** Sends anything still pending, so a typed-but-never-blurred trigger is reflected before save. */
278
- flushPendingRefresh(): Promise<void>;
279
- onSave(): Promise<void>;
280
- onCancel(): void;
281
- openAsDetailEditor(attr: EntityAttributeDefinition): void;
282
- saveAsDetailObject(): void;
283
- closeAsDetailModal(): void;
284
- /**
285
- * Whether `attr`'s row type asks the server before a row is added or removed.
286
- *
287
- * Read off the ROW type, never the parent. `asDetailTypes` already resolves it from the Query-gated
288
- * catalogue first and the parent's `detailTypes` second, and the flag survives the server-side
289
- * pruning of the embedded copy, so both sources give the same answer.
290
- */
291
- private roundTripsRowLifecycle;
292
- /** The type id to address the row type by on the wire. */
293
- private rowTypeId;
294
- /**
295
- * How to name the PARENT's type on the wire.
296
- *
297
- * ⚠️ The fallback must be the type **id**, never `clrType`. The server resolves this through
298
- * `ModelLoader.ResolveEntityType`, which accepts a GUID or a declared alias and nothing else — so
299
- * a CLR name resolves to null and the request is refused, indistinguishably from an unknown type.
300
- * The user would see "the server refused this change" on a perfectly ordinary Add.
301
- *
302
- * It is a live path, not a theoretical one: `spark-po-create` binds no `parentType` (there is no
303
- * parent route segment on a create page), so every host that creates an object with an opted-in
304
- * detail grid lands here.
305
- */
306
- private parentTypeForWire;
307
- /**
308
- * Builds the dict a new row starts from: `{}` as before, or the object the server constructed.
309
- *
310
- * Returns null when the server refused — the caller must then add nothing, which is the whole
311
- * difference between a veto and a message.
312
- */
313
- private buildNewRow;
314
- /**
315
- * Asks whether a stored row may be removed. True when it may — including every case where there
316
- * is nothing to ask about: a type that has not opted in, a parent that has never been saved, or a
317
- * row with no key yet because it was added in this same editing session and never persisted.
318
- */
319
- private mayRemoveRow;
320
- /**
321
- * Turns a rejected lifecycle call into something the user can read.
322
- *
323
- * The envelope puts validation errors under `result`, the same place the save path reads them
324
- * from — reading `error.error.errors` matched nothing and made every veto silent.
325
- */
326
- private clearRowLifecycleError;
327
- private captureRowLifecycleError;
328
- addInlineRow(attr: EntityAttributeDefinition): Promise<void>;
329
- addArrayItem(attr: EntityAttributeDefinition): Promise<void>;
330
- editArrayItem(attr: EntityAttributeDefinition, index: number): void;
331
- removeArrayItem(attr: EntityAttributeDefinition, index: number): Promise<void>;
332
- onAsDetailReorder(attr: EntityAttributeDefinition, event: CdkDragDrop<Record<string, any>[]>): void;
333
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<SparkPoFormComponent, never>;
334
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<SparkPoFormComponent, "spark-po-form", never, { "entityType": { "alias": "entityType"; "required": false; "isSignal": true; }; "formData": { "alias": "formData"; "required": false; "isSignal": true; }; "validationErrors": { "alias": "validationErrors"; "required": false; "isSignal": true; }; "showButtons": { "alias": "showButtons"; "required": false; "isSignal": true; }; "isSaving": { "alias": "isSaving"; "required": false; "isSignal": true; }; "parentId": { "alias": "parentId"; "required": false; "isSignal": true; }; "parentType": { "alias": "parentType"; "required": false; "isSignal": true; }; "objectTypeId": { "alias": "objectTypeId"; "required": false; "isSignal": true; }; "objectId": { "alias": "objectId"; "required": false; "isSignal": true; }; "triggerPathPrefix": { "alias": "triggerPathPrefix"; "required": false; "isSignal": true; }; "refreshOverlay": { "alias": "refreshOverlay"; "required": false; "isSignal": true; }; }, { "formData": "formDataChange"; "save": "save"; "cancel": "cancel"; "nestedTriggerRequested": "nestedTriggerRequested"; "nestedTriggerBlurred": "nestedTriggerBlurred"; "refreshOverlay": "refreshOverlayChange"; }, never, never, true, never>;
87
+ export declare class SparkPoFormComponent {
88
+ private readonly sparkService;
89
+ private readonly translations;
90
+ private readonly rendererRegistry;
91
+ entityType: import("@angular/core").InputSignal<EntityType | null>;
92
+ formData: import("@angular/core").ModelSignal<Record<string, any>>;
93
+ validationErrors: import("@angular/core").InputSignal<ValidationError[]>;
94
+ showButtons: import("@angular/core").InputSignal<boolean>;
95
+ isSaving: import("@angular/core").InputSignal<boolean>;
96
+ parentId: import("@angular/core").InputSignal<string | undefined>;
97
+ parentType: import("@angular/core").InputSignal<string | undefined>;
98
+ save: import("@angular/core").OutputEmitterRef<void>;
99
+ cancel: import("@angular/core").OutputEmitterRef<void>;
100
+ /**
101
+ * The type id to refresh against. Absent means refresh is unavailable — the form still renders and
102
+ * edits normally, so a host that has not opted in loses nothing.
103
+ */
104
+ objectTypeId: import("@angular/core").InputSignal<string | undefined>;
105
+ /** The id of the object being edited; absent for a create. */
106
+ objectId: import("@angular/core").InputSignal<string | undefined>;
107
+ /**
108
+ * Set when this form renders a single embedded AsDetail object inside a host form: the name of
109
+ * the attribute holding it, e.g. `"Gate"`. Presence of a prefix switches the form from issuing
110
+ * its own refreshes to reporting them upward, because an embedded object is not something the
111
+ * server can be asked about on its own — the request must describe, and be authorized against,
112
+ * the object that owns it.
113
+ */
114
+ triggerPathPrefix: import("@angular/core").InputSignal<string | null>;
115
+ /** Raised instead of self-issuing when {@link triggerPathPrefix} is set. */
116
+ nestedTriggerRequested: import("@angular/core").OutputEmitterRef<NestedTriggerRequest>;
117
+ /** Blur counterpart, flushing a trigger the host only marked pending. */
118
+ nestedTriggerBlurred: import("@angular/core").OutputEmitterRef<string>;
119
+ /**
120
+ * What the last refresh changed about each attribute's presentation, keyed by attribute name.
121
+ *
122
+ * Deliberately NOT folded back into `entityType`. All option loading hangs off one effect keyed on
123
+ * `entityType` identity and `SparkService` caches nothing, so re-setting it would re-issue every
124
+ * reference query and lookup fetch on every refresh; mutating it in place would not re-render at
125
+ * all.
126
+ *
127
+ * ⚠️ A `model`, not a plain signal, because the page that owns the save has to see it. This form
128
+ * renders from the overlaid attribute list; `spark-po-edit` and `spark-po-create` build the
129
+ * payload from their own copy of the same filter. While the overlay stopped here, those two
130
+ * filtered on the attribute's state *as loaded* — so an attribute a refresh hook revealed was
131
+ * rendered, filled in by the user, and then silently left out of the save. When the same hook also
132
+ * made it required (the ordinary case — a field appears *because* it is now needed) the server
133
+ * refused the save for the very field the user had just filled, and the form became a dead end
134
+ * with no way forward from inside it.
135
+ */
136
+ refreshOverlay: import("@angular/core").ModelSignal<RefreshOverlay>;
137
+ isRefreshing: import("@angular/core").WritableSignal<boolean>;
138
+ colors: typeof Color;
139
+ referenceOptions: import("@angular/core").WritableSignal<Record<string, QueryResultItem[]>>;
140
+ referenceProviders: import("@angular/core").WritableSignal<Record<string, InMemoryTreeSelectProvider>>;
141
+ referenceNodes: import("@angular/core").WritableSignal<Record<string, Record<string, TreeNode>>>;
142
+ asDetailTypes: import("@angular/core").WritableSignal<Record<string, EntityType>>;
143
+ lookupReferenceOptions: import("@angular/core").WritableSignal<Record<string, LookupReference>>;
144
+ editingAsDetailAttr: import("@angular/core").WritableSignal<EntityAttributeDefinition | null>;
145
+ asDetailFormData: import("@angular/core").WritableSignal<Record<string, any>>;
146
+ showAsDetailModal: import("@angular/core").WritableSignal<boolean>;
147
+ editingArrayIndex: import("@angular/core").WritableSignal<number | null>;
148
+ asDetailPermissions: import("@angular/core").WritableSignal<Record<string, EntityPermissions>>;
149
+ /**
150
+ * What the server said when it refused to construct or release a row.
151
+ *
152
+ * A local signal rather than the `validationErrors` input, because this is the one class of error
153
+ * the form raises on its own behalf: `validationErrors` is owned by the host (po-edit / po-create)
154
+ * and arrives from a save. Cleared at the start of each lifecycle call, so a stale refusal never
155
+ * outlives the click that caused it.
156
+ *
157
+ * Keyed by attribute name so a message renders against the grid it came from. A single global
158
+ * alert would have been less code and worse: a form with two detail grids would show one grid's
159
+ * refusal above the other, and the user's next click is on the grid, not the top of the page.
160
+ */
161
+ rowLifecycleErrors: import("@angular/core").WritableSignal<Record<string, ValidationError[]>>;
162
+ /** The refusal to render under `attrName`'s grid, if any. */
163
+ rowLifecycleErrorsFor(attrName: string): ValidationError[];
164
+ asDetailReferenceOptions: import("@angular/core").WritableSignal<Record<string, Record<string, QueryResultItem[]>>>;
165
+ ELookupDisplayType: typeof ELookupDisplayType;
166
+ EReferenceDisplayType: typeof EReferenceDisplayType;
167
+ /**
168
+ * Every attribute this form could ever need option data for — including ones the model hides,
169
+ * because a refresh may reveal them.
170
+ *
171
+ * Read by the option-loading effect, and deliberately independent of `refreshOverlay`: the loaders
172
+ * read this synchronously, so an overlay dependency here would make every refresh re-issue every
173
+ * reference query and lookup fetch. That is the whole reason the overlay is a separate signal.
174
+ */
175
+ optionSourceAttributes: import("@angular/core").Signal<EntityAttributeDefinition[]>;
176
+ editableAttributes: import("@angular/core").Signal<EntityAttributeDefinition[]>;
177
+ private static readonly DEFAULT_TAB;
178
+ ungroupedAttributes: import("@angular/core").Signal<EntityAttributeDefinition[]>;
179
+ resolvedTabs: import("@angular/core").Signal<AttributeTab[]>;
180
+ groupsForTab(tab: AttributeTab): AttributeGroup[];
181
+ attrsForGroup(group: AttributeGroup): EntityAttributeDefinition[];
182
+ constructor();
183
+ private toRecord;
184
+ loadReferenceOptions(): Promise<void>;
185
+ /**
186
+ * Stable TreeNode[] value per multi-reference attribute, derived from the id array
187
+ * in formData and the resolved node map. Recomputes only when formData or the node
188
+ * map changes, so binding it into <bs-tree-select> doesn't churn on every CD pass.
189
+ * Ids without a resolved node fall back to a label of the id itself.
190
+ */
191
+ referenceTreeValues: import("@angular/core").Signal<Record<string, TreeNode[]>>;
192
+ getReferenceProvider(attr: EntityAttributeDefinition): InMemoryTreeSelectProvider | undefined;
193
+ onReferenceTreeChange(attr: EntityAttributeDefinition, value: TreeNode | TreeNode[] | null): void;
194
+ loadAsDetailTypes(): Promise<void>;
195
+ loadLookupReferenceOptions(): Promise<void>;
196
+ getLookupOptions(attr: EntityAttributeDefinition): LookupReferenceValue[];
197
+ onReferenceValueChange(attr: EntityAttributeDefinition, id: string | null): void;
198
+ onLookupValueChange(attr: EntityAttributeDefinition, key: string | null): void;
199
+ getEditRendererComponent(attr: EntityAttributeDefinition): Type<any> | null;
200
+ getEditRendererInputs(component: Type<any>, attr: EntityAttributeDefinition): Record<string, any>;
201
+ /** Column renderer for a cell of an AsDetail sub-table (so embedded rows honor `col.renderer` too). */
202
+ getAsDetailCellRendererComponent(col: EntityAttributeDefinition): Type<any> | null;
203
+ getAsDetailCellRendererInputs(component: Type<any>, row: Record<string, any>, col: EntityAttributeDefinition): Record<string, any>;
204
+ /** Edit-renderer for an inline AsDetail cell (so inline editing honors `col.renderer`, not just display). */
205
+ getAsDetailCellEditRenderer(col: EntityAttributeDefinition): Type<any> | null;
206
+ getAsDetailCellEditRendererInputs(component: Type<any>, row: Record<string, any>, col: EntityAttributeDefinition): Record<string, any>;
207
+ /**
208
+ * Rules evaluated in the browser, against the *effective* metadata — so a rule a refresh hook
209
+ * imposed is visible before the round-trip rather than only after the server rejects the save.
210
+ */
211
+ clientRuleFailures: import("@angular/core").Signal<RuleFailure[]>;
212
+ hasError(attrName: string): boolean;
213
+ private inlineErrorPath;
214
+ hasInlineError(attr: EntityAttributeDefinition, rowIndex: number, col: EntityAttributeDefinition): boolean;
215
+ inlineErrorMessage(attr: EntityAttributeDefinition, rowIndex: number, col: EntityAttributeDefinition): string | null;
216
+ /**
217
+ * The single funnel every scalar / boolean / inline-cell edit passes through.
218
+ *
219
+ * `attr` is optional because some editors have nothing useful to say about which attribute moved.
220
+ * A caller that knows should always say so — without it no refresh can fire.
221
+ */
222
+ onFieldChange(attr?: EntityAttributeDefinition): void;
223
+ /**
224
+ * A trigger inside an AsDetail row. Addressed by the same `{attr}[{index}].{col}` path the inline
225
+ * validation errors already use, so the server can tell which row asked without a second
226
+ * addressing scheme being invented for it.
227
+ */
228
+ onInlineCellChange(attr: EntityAttributeDefinition, rowIndex: number, col: EntityAttributeDefinition): void;
229
+ /**
230
+ * Which embedded target the in-flight refresh belongs to, if any.
231
+ *
232
+ * ⚠️ Tagged, not a nullable `rowIndex`. The two arms write to different places — a row inside
233
+ * `formData`, versus the modal's working copy in `asDetailFormData` — and an index that happens
234
+ * to be absent is not the same statement as "this attribute holds one object". With a nullable
235
+ * index, a row refresh carrying a bad index would fall silently into the object arm.
236
+ */
237
+ private pendingNestedTrigger;
238
+ /**
239
+ * A trigger inside a single embedded AsDetail object, raised by the modal's recursive form.
240
+ *
241
+ * The child form does not issue the request itself, for two reasons that both bite. Its
242
+ * `entityType` is the embedded type, so a payload built there describes `GateSettings` while the
243
+ * request must describe the Repository that owns it. And nested AsDetail types carry no rights of
244
+ * their own — the server authorizes a nested refresh on the OWNING type — so a child-issued
245
+ * request would be asking the wrong question of security.json.
246
+ */
247
+ onEmbeddedTrigger(attributeName: string, event: NestedTriggerRequest): void;
248
+ /** Blur counterpart of {@link onEmbeddedTrigger}, for the child's free-text editors. */
249
+ onEmbeddedTriggerBlur(path: string): void;
250
+ /**
251
+ * Applies a refresh that ran against a detail row: the row's own values, and the column metadata
252
+ * for the grid it lives in.
253
+ *
254
+ * The column metadata comes from `asDetailTypes` — a different signal from `entityType` — which is
255
+ * why a nested response cannot go through the top-level overlay.
256
+ *
257
+ * ⚠️ The row array is mutated in place rather than replaced. Rows are tracked by index, so handing
258
+ * the template a new array destroys and rebuilds every row's DOM and takes focus with it, mid-edit.
259
+ */
260
+ private applyNestedResponse;
261
+ onInlineCellBlur(attr: EntityAttributeDefinition, rowIndex: number, col: EntityAttributeDefinition): void;
262
+ /** Blur handler for free-text editors — sends the refresh their keystrokes only marked pending. */
263
+ onFieldBlur(attr: EntityAttributeDefinition): void;
264
+ private noteChange;
265
+ /** `Gate.ProjectMode` — the index-free counterpart of the inline grid's `Jobs[1].Kind`. */
266
+ private nestedTriggerPath;
267
+ private canRefresh;
268
+ /**
269
+ * Per-instance, never a service: the retry-action modal renders its own `spark-po-form`, and a
270
+ * refresh may carry a retry operation — so a refresh can open a modal containing a form that
271
+ * refreshes. A shared coordinator would let the nested form supersede this one's request.
272
+ */
273
+ protected readonly refreshCoordinator: RefreshCoordinator;
274
+ private buildRefreshPayload;
275
+ /**
276
+ * The values to post, with the open modal's working copy substituted for the attribute it edits.
277
+ *
278
+ * ⚠️ Without this the server receives the embedded object as it was when the modal opened — `{}`
279
+ * for a gate that has never been set — and the hook decides against values the user cannot see it
280
+ * ignoring. `formData` deliberately does not hold the in-progress edit (cancelling the modal has
281
+ * to discard it), so the refresh has to reach into `asDetailFormData` instead. Only the attribute
282
+ * under edit is substituted; everything else is the form's own state.
283
+ */
284
+ private embeddedValues;
285
+ /**
286
+ * Folds replaced option lists into the signals the editors already read, so a refreshed dropdown
287
+ * renders through the same path as a loaded one.
288
+ *
289
+ * `undefined` means the hook did not touch this attribute's options and the loaded set stands; an
290
+ * empty array means it deliberately left none. Collapsing the two would blank every dropdown the
291
+ * hook never mentioned.
292
+ */
293
+ private applyRefreshedOptions;
294
+ /** Sends anything still pending, so a typed-but-never-blurred trigger is reflected before save. */
295
+ flushPendingRefresh(): Promise<void>;
296
+ onSave(): Promise<void>;
297
+ onCancel(): void;
298
+ openAsDetailEditor(attr: EntityAttributeDefinition): void;
299
+ saveAsDetailObject(): void;
300
+ closeAsDetailModal(): void;
301
+ /**
302
+ * Whether `attr`'s row type asks the server before a row is added or removed.
303
+ *
304
+ * Read off the ROW type, never the parent. `asDetailTypes` already resolves it from the Query-gated
305
+ * catalogue first and the parent's `detailTypes` second, and the flag survives the server-side
306
+ * pruning of the embedded copy, so both sources give the same answer.
307
+ */
308
+ private roundTripsRowLifecycle;
309
+ /** The type id to address the row type by on the wire. */
310
+ private rowTypeId;
311
+ /**
312
+ * How to name the PARENT's type on the wire.
313
+ *
314
+ * ⚠️ The fallback must be the type **id**, never `clrType`. The server resolves this through
315
+ * `ModelLoader.ResolveEntityType`, which accepts a GUID or a declared alias and nothing else — so
316
+ * a CLR name resolves to null and the request is refused, indistinguishably from an unknown type.
317
+ * The user would see "the server refused this change" on a perfectly ordinary Add.
318
+ *
319
+ * It is a live path, not a theoretical one: `spark-po-create` binds no `parentType` (there is no
320
+ * parent route segment on a create page), so every host that creates an object with an opted-in
321
+ * detail grid lands here.
322
+ */
323
+ private parentTypeForWire;
324
+ /**
325
+ * Builds the dict a new row starts from: `{}` as before, or the object the server constructed.
326
+ *
327
+ * Returns null when the server refused — the caller must then add nothing, which is the whole
328
+ * difference between a veto and a message.
329
+ */
330
+ private buildNewRow;
331
+ /**
332
+ * Asks whether a stored row may be removed. True when it may — including every case where there
333
+ * is nothing to ask about: a type that has not opted in, a parent that has never been saved, or a
334
+ * row with no key yet because it was added in this same editing session and never persisted.
335
+ */
336
+ private mayRemoveRow;
337
+ /**
338
+ * Turns a rejected lifecycle call into something the user can read.
339
+ *
340
+ * The envelope puts validation errors under `result`, the same place the save path reads them
341
+ * from — reading `error.error.errors` matched nothing and made every veto silent.
342
+ */
343
+ private clearRowLifecycleError;
344
+ private captureRowLifecycleError;
345
+ addInlineRow(attr: EntityAttributeDefinition): Promise<void>;
346
+ addArrayItem(attr: EntityAttributeDefinition): Promise<void>;
347
+ editArrayItem(attr: EntityAttributeDefinition, index: number): void;
348
+ removeArrayItem(attr: EntityAttributeDefinition, index: number): Promise<void>;
349
+ onAsDetailReorder(attr: EntityAttributeDefinition, event: CdkDragDrop<Record<string, any>[]>): void;
350
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkPoFormComponent, never>;
351
+ static ɵcmp: i0.ɵɵComponentDeclaration<SparkPoFormComponent, "spark-po-form", never, {
352
+ "entityType": {
353
+ "alias": "entityType";
354
+ "required": false;
355
+ "isSignal": true;
356
+ };
357
+ "formData": {
358
+ "alias": "formData";
359
+ "required": false;
360
+ "isSignal": true;
361
+ };
362
+ "validationErrors": {
363
+ "alias": "validationErrors";
364
+ "required": false;
365
+ "isSignal": true;
366
+ };
367
+ "showButtons": {
368
+ "alias": "showButtons";
369
+ "required": false;
370
+ "isSignal": true;
371
+ };
372
+ "isSaving": {
373
+ "alias": "isSaving";
374
+ "required": false;
375
+ "isSignal": true;
376
+ };
377
+ "parentId": {
378
+ "alias": "parentId";
379
+ "required": false;
380
+ "isSignal": true;
381
+ };
382
+ "parentType": {
383
+ "alias": "parentType";
384
+ "required": false;
385
+ "isSignal": true;
386
+ };
387
+ "objectTypeId": {
388
+ "alias": "objectTypeId";
389
+ "required": false;
390
+ "isSignal": true;
391
+ };
392
+ "objectId": {
393
+ "alias": "objectId";
394
+ "required": false;
395
+ "isSignal": true;
396
+ };
397
+ "triggerPathPrefix": {
398
+ "alias": "triggerPathPrefix";
399
+ "required": false;
400
+ "isSignal": true;
401
+ };
402
+ "refreshOverlay": {
403
+ "alias": "refreshOverlay";
404
+ "required": false;
405
+ "isSignal": true;
406
+ };
407
+ }, {
408
+ "formData": "formDataChange";
409
+ "save": "save";
410
+ "cancel": "cancel";
411
+ "nestedTriggerRequested": "nestedTriggerRequested";
412
+ "nestedTriggerBlurred": "nestedTriggerBlurred";
413
+ "refreshOverlay": "refreshOverlayChange";
414
+ }, never, never, true, never>;
335
415
  }
336
-
337
416
  /**
338
417
  * Reusable Reference value picker: a readonly textbox showing the current selection's
339
418
  * breadcrumb/name plus a "…" button that opens a searchable modal grid over the candidate
@@ -344,70 +423,127 @@ declare class SparkPoFormComponent {
344
423
  * CLR type); the component lazily loads that EntityType's metadata on first open to render
345
424
  * the grid's column headers. Emits the picked id via `valueChange`.
346
425
  */
347
- declare class SparkReferencePickerComponent {
348
- private readonly sparkService;
349
- private readonly lang;
350
- /** Currently selected referenced id (or null when unset). */
351
- value: _angular_core.InputSignal<string | null>;
352
- /** Candidate items to pick from (the full query result, pre-loaded by the parent). */
353
- options: _angular_core.InputSignal<QueryResultItem[]>;
354
- /** Target entity type's CLR type name; used to load the grid's column headers. */
355
- referenceType: _angular_core.InputSignal<string | undefined>;
356
- /** Renders the field with the Bootstrap is-invalid state. */
357
- isInvalid: _angular_core.InputSignal<boolean>;
358
- /** Optional id forwarded to the readonly input (for label association). */
359
- inputId: _angular_core.InputSignal<string | undefined>;
360
- /** Optional resolved label appended to the modal header ("Select {title}"). */
361
- title: _angular_core.InputSignal<string>;
362
- valueChange: _angular_core.OutputEmitterRef<string | null>;
363
- colors: typeof Color;
364
- showModal: _angular_core.WritableSignal<boolean>;
365
- entityType: _angular_core.WritableSignal<EntityType | null>;
366
- pagination: _angular_core.WritableSignal<PaginationResponse<QueryResultItem> | undefined>;
367
- settings: _angular_core.WritableSignal<DatatableSettings>;
368
- searchTerm: string;
369
- visibleAttributes: _angular_core.Signal<_mintplayer_ng_spark_models.EntityAttributeDefinition[]>;
370
- rows: _angular_core.Signal<QueryResultItem[]>;
371
- displayValue: _angular_core.Signal<string>;
372
- open(): Promise<void>;
373
- onSearchChange(): void;
374
- applyFilter(): void;
375
- clearSearch(): void;
376
- select(item: QueryResultItem): void;
377
- close(): void;
378
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<SparkReferencePickerComponent, never>;
379
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<SparkReferencePickerComponent, "spark-reference-picker", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "referenceType": { "alias": "referenceType"; "required": false; "isSignal": true; }; "isInvalid": { "alias": "isInvalid"; "required": false; "isSignal": true; }; "inputId": { "alias": "inputId"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
426
+ export declare class SparkReferencePickerComponent {
427
+ private readonly sparkService;
428
+ private readonly lang;
429
+ /** Currently selected referenced id (or null when unset). */
430
+ value: import("@angular/core").InputSignal<string | null>;
431
+ /** Candidate items to pick from (the full query result, pre-loaded by the parent). */
432
+ options: import("@angular/core").InputSignal<QueryResultItem[]>;
433
+ /** Target entity type's CLR type name; used to load the grid's column headers. */
434
+ referenceType: import("@angular/core").InputSignal<string | undefined>;
435
+ /** Renders the field with the Bootstrap is-invalid state. */
436
+ isInvalid: import("@angular/core").InputSignal<boolean>;
437
+ /** Optional id forwarded to the readonly input (for label association). */
438
+ inputId: import("@angular/core").InputSignal<string | undefined>;
439
+ /** Optional resolved label appended to the modal header ("Select {title}"). */
440
+ title: import("@angular/core").InputSignal<string>;
441
+ valueChange: import("@angular/core").OutputEmitterRef<string | null>;
442
+ colors: typeof Color;
443
+ showModal: import("@angular/core").WritableSignal<boolean>;
444
+ entityType: import("@angular/core").WritableSignal<EntityType | null>;
445
+ pagination: import("@angular/core").WritableSignal<PaginationResponse<QueryResultItem> | undefined>;
446
+ settings: import("@angular/core").WritableSignal<DatatableSettings>;
447
+ searchTerm: string;
448
+ visibleAttributes: import("@angular/core").Signal<import("@mintplayer/ng-spark/models").EntityAttributeDefinition[]>;
449
+ rows: import("@angular/core").Signal<QueryResultItem[]>;
450
+ displayValue: import("@angular/core").Signal<string>;
451
+ open(): Promise<void>;
452
+ onSearchChange(): void;
453
+ applyFilter(): void;
454
+ clearSearch(): void;
455
+ select(item: QueryResultItem): void;
456
+ close(): void;
457
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkReferencePickerComponent, never>;
458
+ static ɵcmp: i0.ɵɵComponentDeclaration<SparkReferencePickerComponent, "spark-reference-picker", never, {
459
+ "value": {
460
+ "alias": "value";
461
+ "required": false;
462
+ "isSignal": true;
463
+ };
464
+ "options": {
465
+ "alias": "options";
466
+ "required": false;
467
+ "isSignal": true;
468
+ };
469
+ "referenceType": {
470
+ "alias": "referenceType";
471
+ "required": false;
472
+ "isSignal": true;
473
+ };
474
+ "isInvalid": {
475
+ "alias": "isInvalid";
476
+ "required": false;
477
+ "isSignal": true;
478
+ };
479
+ "inputId": {
480
+ "alias": "inputId";
481
+ "required": false;
482
+ "isSignal": true;
483
+ };
484
+ "title": {
485
+ "alias": "title";
486
+ "required": false;
487
+ "isSignal": true;
488
+ };
489
+ }, {
490
+ "valueChange": "valueChange";
491
+ }, never, never, true, never>;
380
492
  }
381
-
382
493
  /**
383
494
  * Reusable LookupReference value picker: a readonly textbox showing the current selection's
384
495
  * translated label plus a "…" button that opens a searchable modal list over the active
385
496
  * `options`. Per-instance state, so it serves both top-level lookup attributes (display type
386
497
  * Modal) and individual inline AsDetail lookup cells. Emits the picked key via `valueChange`.
387
498
  */
388
- declare class SparkLookupPickerComponent {
389
- /** Currently selected lookup key (or null when unset). */
390
- value: _angular_core.InputSignal<string | null>;
391
- /** Active lookup values to pick from. */
392
- options: _angular_core.InputSignal<LookupReferenceValue[]>;
393
- /** Renders the field with the Bootstrap is-invalid state. */
394
- isInvalid: _angular_core.InputSignal<boolean>;
395
- /** Optional id forwarded to the readonly input (for label association). */
396
- inputId: _angular_core.InputSignal<string | undefined>;
397
- /** Optional resolved label appended to the modal header ("Select {title}"). */
398
- title: _angular_core.InputSignal<string>;
399
- valueChange: _angular_core.OutputEmitterRef<string | null>;
400
- colors: typeof Color;
401
- showModal: _angular_core.WritableSignal<boolean>;
402
- searchTerm: _angular_core.WritableSignal<string>;
403
- displayValue: _angular_core.Signal<string>;
404
- filteredItems: _angular_core.Signal<LookupReferenceValue[]>;
405
- open(): void;
406
- select(item: LookupReferenceValue): void;
407
- close(): void;
408
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<SparkLookupPickerComponent, never>;
409
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<SparkLookupPickerComponent, "spark-lookup-picker", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "isInvalid": { "alias": "isInvalid"; "required": false; "isSignal": true; }; "inputId": { "alias": "inputId"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
410
- }
411
-
412
- export { SparkLookupPickerComponent, SparkPoFormComponent, SparkReferencePickerComponent };
413
- export type { NestedTriggerRequest };
499
+ export declare class SparkLookupPickerComponent {
500
+ /** Currently selected lookup key (or null when unset). */
501
+ value: import("@angular/core").InputSignal<string | null>;
502
+ /** Active lookup values to pick from. */
503
+ options: import("@angular/core").InputSignal<LookupReferenceValue[]>;
504
+ /** Renders the field with the Bootstrap is-invalid state. */
505
+ isInvalid: import("@angular/core").InputSignal<boolean>;
506
+ /** Optional id forwarded to the readonly input (for label association). */
507
+ inputId: import("@angular/core").InputSignal<string | undefined>;
508
+ /** Optional resolved label appended to the modal header ("Select {title}"). */
509
+ title: import("@angular/core").InputSignal<string>;
510
+ valueChange: import("@angular/core").OutputEmitterRef<string | null>;
511
+ colors: typeof Color;
512
+ showModal: import("@angular/core").WritableSignal<boolean>;
513
+ searchTerm: import("@angular/core").WritableSignal<string>;
514
+ displayValue: import("@angular/core").Signal<string>;
515
+ filteredItems: import("@angular/core").Signal<LookupReferenceValue[]>;
516
+ open(): void;
517
+ select(item: LookupReferenceValue): void;
518
+ close(): void;
519
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkLookupPickerComponent, never>;
520
+ static ɵcmp: i0.ɵɵComponentDeclaration<SparkLookupPickerComponent, "spark-lookup-picker", never, {
521
+ "value": {
522
+ "alias": "value";
523
+ "required": false;
524
+ "isSignal": true;
525
+ };
526
+ "options": {
527
+ "alias": "options";
528
+ "required": false;
529
+ "isSignal": true;
530
+ };
531
+ "isInvalid": {
532
+ "alias": "isInvalid";
533
+ "required": false;
534
+ "isSignal": true;
535
+ };
536
+ "inputId": {
537
+ "alias": "inputId";
538
+ "required": false;
539
+ "isSignal": true;
540
+ };
541
+ "title": {
542
+ "alias": "title";
543
+ "required": false;
544
+ "isSignal": true;
545
+ };
546
+ }, {
547
+ "valueChange": "valueChange";
548
+ }, never, never, true, never>;
549
+ }