@mintplayer/ng-spark 22.6.0 → 22.9.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 (31) hide show
  1. package/fesm2022/mintplayer-ng-spark-attribute-description.mjs +68 -0
  2. package/fesm2022/mintplayer-ng-spark-attribute-description.mjs.map +1 -0
  3. package/fesm2022/mintplayer-ng-spark-grid.mjs +134 -52
  4. package/fesm2022/mintplayer-ng-spark-grid.mjs.map +1 -1
  5. package/fesm2022/mintplayer-ng-spark-models.mjs +77 -7
  6. package/fesm2022/mintplayer-ng-spark-models.mjs.map +1 -1
  7. package/fesm2022/mintplayer-ng-spark-pipes.mjs +87 -4
  8. package/fesm2022/mintplayer-ng-spark-pipes.mjs.map +1 -1
  9. package/fesm2022/mintplayer-ng-spark-po-detail.mjs +4 -3
  10. package/fesm2022/mintplayer-ng-spark-po-detail.mjs.map +1 -1
  11. package/fesm2022/mintplayer-ng-spark-po-form.mjs +15 -16
  12. package/fesm2022/mintplayer-ng-spark-po-form.mjs.map +1 -1
  13. package/fesm2022/mintplayer-ng-spark-query-list.mjs +21 -7
  14. package/fesm2022/mintplayer-ng-spark-query-list.mjs.map +1 -1
  15. package/fesm2022/mintplayer-ng-spark-renderers.mjs +16 -1
  16. package/fesm2022/mintplayer-ng-spark-renderers.mjs.map +1 -1
  17. package/fesm2022/mintplayer-ng-spark-services.mjs +92 -5
  18. package/fesm2022/mintplayer-ng-spark-services.mjs.map +1 -1
  19. package/fesm2022/mintplayer-ng-spark-shell.mjs +41 -4
  20. package/fesm2022/mintplayer-ng-spark-shell.mjs.map +1 -1
  21. package/package.json +5 -1
  22. package/types/mintplayer-ng-spark-attribute-description.d.ts +30 -0
  23. package/types/mintplayer-ng-spark-grid.d.ts +75 -33
  24. package/types/mintplayer-ng-spark-models.d.ts +136 -7
  25. package/types/mintplayer-ng-spark-pipes.d.ts +33 -5
  26. package/types/mintplayer-ng-spark-po-detail.d.ts +2 -2
  27. package/types/mintplayer-ng-spark-po-form.d.ts +7 -7
  28. package/types/mintplayer-ng-spark-query-list.d.ts +11 -4
  29. package/types/mintplayer-ng-spark-renderers.d.ts +31 -11
  30. package/types/mintplayer-ng-spark-services.d.ts +71 -2
  31. package/types/mintplayer-ng-spark-shell.d.ts +32 -2
@@ -1,5 +1,5 @@
1
1
  import { Type, InputSignal, InjectionToken, Provider } from '@angular/core';
2
- import { PersistentObjectAttribute, EntityAttributeDefinition, PersistentObject } from '@mintplayer/ng-spark/models';
2
+ import { QueryResultItemValue, PersistentObjectAttribute, SparkCellColumn, QueryResultItem, EntityAttributeDefinition, PersistentObject } from '@mintplayer/ng-spark/models';
3
3
 
4
4
  /**
5
5
  * Drops entries the component doesn't declare, so every contract member is
@@ -10,8 +10,21 @@ declare function withDeclaredInputs(component: Type<any>, inputs: Record<string,
10
10
  * The renderer-facing value of an attribute: the flat value, or for AsDetail
11
11
  * attributes (whose flat value the server nulls on purpose) the nested
12
12
  * PersistentObject (single) / PersistentObject[] (array).
13
+ *
14
+ * Used by the detail and edit paths, which still work in attributes.
13
15
  */
14
16
  declare function rendererValue(attr: PersistentObjectAttribute | undefined): any;
17
+ /**
18
+ * The renderer-facing value of a query-result cell.
19
+ *
20
+ * A cell is a single channel: whatever a renderer needs is already on `value` — for a single-child
21
+ * AsDetail column that is the nested PersistentObject itself, put there by the server so this
22
+ * matches what {@link rendererValue} falls through to on a detail page. There is nothing to fall
23
+ * back to, which is why this is deliberately not the same function: keeping them separate is what
24
+ * stops a renderer silently receiving `undefined` because it was written against the attribute
25
+ * shape's `object` / `objects` fields, which a row does not carry.
26
+ */
27
+ declare function cellValue(value: QueryResultItemValue | undefined): any;
15
28
 
16
29
  /**
17
30
  * Contract for detail-page renderers (spark-po-detail).
@@ -38,21 +51,28 @@ interface SparkAttributeDetailRenderer {
38
51
  */
39
52
  interface SparkAttributeColumnRenderer {
40
53
  /**
41
- * The current attribute value. For an AsDetail attribute this is the nested
42
- * PersistentObject (single) / PersistentObject[] (array) in query-list and
43
- * sub-query grids, and the flattened value in AsDetail sub-table cells.
54
+ * The cell value. For an AsDetail column this is the nested PersistentObject (single) /
55
+ * PersistentObject[] (array) in an AsDetail sub-table, and the projected value in a query grid.
44
56
  */
45
57
  value?: InputSignal<any>;
46
- /** The attribute definition metadata */
47
- attribute?: InputSignal<EntityAttributeDefinition | undefined>;
58
+ /**
59
+ * The column being rendered.
60
+ *
61
+ * A query grid supplies a {@link SparkCellColumn} from the result own column metadata; an
62
+ * AsDetail sub-table supplies its attribute definition, which satisfies the same shape. This
63
+ * replaced an `attribute` input typed as the definition: a query result no longer carries
64
+ * attribute metadata per row, so naming it `attribute` would promise something the grid cannot
65
+ * deliver.
66
+ */
67
+ column?: InputSignal<SparkCellColumn | undefined>;
48
68
  /** Renderer-specific options from rendererOptions */
49
69
  options?: InputSignal<Record<string, any> | undefined>;
50
70
  /**
51
- * The row this cell belongs to: a PersistentObject in query-list/sub-query
52
- * grids, a plain record (possibly including the reserved '__sparkBreadcrumbs'
53
- * key) in AsDetail sub-tables. Passed only when declared.
71
+ * The row this cell belongs to: a {@link QueryResultItem} in a query grid, a plain record
72
+ * (possibly including the reserved '__sparkBreadcrumbs' key) in AsDetail sub-tables. Passed
73
+ * only when declared.
54
74
  */
55
- item?: InputSignal<PersistentObject | Record<string, any> | undefined>;
75
+ item?: InputSignal<QueryResultItem | Record<string, any> | undefined>;
56
76
  }
57
77
  /**
58
78
  * Contract for edit-form renderers (spark-po-form on create/edit pages).
@@ -94,5 +114,5 @@ declare const SPARK_ATTRIBUTE_RENDERERS: InjectionToken<SparkAttributeRendererRe
94
114
  */
95
115
  declare function provideSparkAttributeRenderers(renderers: SparkAttributeRendererRegistration[]): Provider;
96
116
 
97
- export { SPARK_ATTRIBUTE_RENDERERS, provideSparkAttributeRenderers, rendererValue, withDeclaredInputs };
117
+ export { SPARK_ATTRIBUTE_RENDERERS, cellValue, provideSparkAttributeRenderers, rendererValue, withDeclaredInputs };
98
118
  export type { SparkAttributeColumnRenderer, SparkAttributeDetailRenderer, SparkAttributeEditRenderer, SparkAttributeRendererRegistration };
@@ -83,7 +83,20 @@ declare class SparkService {
83
83
  refresh(type: string, data: Partial<PersistentObject>, triggeredBy: string): Promise<PersistentObject>;
84
84
  delete(type: string, id: string): Promise<void>;
85
85
  getCustomActions(objectTypeId: string): Promise<CustomActionDefinition[]>;
86
- executeCustomAction(objectTypeId: string, actionName: string, parent?: PersistentObject, selectedItems?: PersistentObject[]): Promise<void>;
86
+ /**
87
+ * @param parent The object of THIS type the action is operating on — the detail-page invocation.
88
+ * @param selectedItemIds Row ids from a query. Ids, never row objects: a row is a projection.
89
+ * @param queryParent When invoked from a sub-query, the object whose detail page it was rendered
90
+ * on — a DIFFERENT type (the cars listed on a company's page are Cars, the page is a Company).
91
+ * Sent as id + type, exactly as the query endpoint names it, and resolved server-side under its
92
+ * own type with its own Read gate.
93
+ * @param queryId The query the selection came from, so the server can re-run it narrowed to those
94
+ * ids and hand the action the rows the grid actually had -- index-computed columns included.
95
+ */
96
+ executeCustomAction(objectTypeId: string, actionName: string, parent?: PersistentObject, selectedItemIds?: string[], queryParent?: {
97
+ id: string;
98
+ type: string;
99
+ }, queryId?: string): Promise<void>;
87
100
  getLookupReferences(): Promise<LookupReferenceListItem[]>;
88
101
  getLookupReference(name: string): Promise<LookupReference>;
89
102
  addLookupReferenceValue(name: string, value: LookupReferenceValue): Promise<LookupReferenceValue>;
@@ -133,4 +146,60 @@ declare class SparkIconRegistry {
133
146
  static ɵprov: i0.ɵɵInjectableDeclaration<SparkIconRegistry>;
134
147
  }
135
148
 
136
- export { RetryActionService, SparkIconRegistry, SparkLanguageService, SparkService, SparkStreamingService };
149
+ /**
150
+ * A query's custom actions, reachable **without the grid that usually renders them**.
151
+ *
152
+ * ## Why this exists
153
+ *
154
+ * A query's actions were only ever obtainable by rendering `<spark-query-grid>`, which loads the
155
+ * query, resolves its entity type, fetches the actions and filters them to the ones marked for a
156
+ * query surface — all privately. A page that wanted the same buttons somewhere else (a toolbar
157
+ * above the card, the shell's topbar) had three bad options: duplicate the four-step resolution
158
+ * and let it drift, reach into the grid's internals, or put the button in the wrong place.
159
+ *
160
+ * This exposes the resolution itself. The grid keeps rendering the default placement; a host that
161
+ * wants a different one asks here and renders its own control.
162
+ *
163
+ * ## What it does not do
164
+ *
165
+ * It does not authorize. `/spark/actions/{type}` returns only the actions this caller may see —
166
+ * the server filters against `security.json`, and executing re-checks — so nothing here is a gate,
167
+ * and a host must not treat "the list came back empty" as anything other than a display fact.
168
+ *
169
+ * It also does not cache. Actions depend on the caller, and a memo keyed by type id would survive
170
+ * a sign-out.
171
+ */
172
+ declare class SparkQueryActionsService {
173
+ private readonly sparkService;
174
+ /**
175
+ * The custom actions of the query named by id or alias, already filtered to those that belong on
176
+ * a query surface.
177
+ *
178
+ * Returns an empty list — rather than throwing — when the query resolves to no entity type,
179
+ * because a caller rendering a toolbar wants "no buttons", not a broken page.
180
+ */
181
+ actionsFor(queryIdOrAlias: string): Promise<CustomActionDefinition[]>;
182
+ /**
183
+ * Runs one of those actions. `selectedItemIds` are row ids, exactly as the grid posts them —
184
+ * the server re-materializes each one through the same load path a detail page uses, so an id
185
+ * from anywhere is treated as caller input rather than as a verified row.
186
+ */
187
+ execute(queryIdOrAlias: string, actionName: string, options?: {
188
+ parent?: PersistentObject;
189
+ selectedItemIds?: string[];
190
+ /** For a sub-query: the object whose detail page it was rendered on. See SparkService. */
191
+ queryParent?: {
192
+ id: string;
193
+ type: string;
194
+ };
195
+ }): Promise<void>;
196
+ /**
197
+ * The query and the entity type its rows are mapped against — the two-step resolution both
198
+ * methods need, kept in one place so they cannot disagree about which type an action runs on.
199
+ */
200
+ private contextFor;
201
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkQueryActionsService, never>;
202
+ static ɵprov: i0.ɵɵInjectableDeclaration<SparkQueryActionsService>;
203
+ }
204
+
205
+ export { RetryActionService, SparkIconRegistry, SparkLanguageService, SparkQueryActionsService, SparkService, SparkStreamingService };
@@ -50,6 +50,33 @@ declare class SparkShellTopbarEndDirective {
50
50
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<SparkShellTopbarEndDirective, never>;
51
51
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<SparkShellTopbarEndDirective, "[sparkShellTopbarEnd]", never, {}, {}, never, never, true, never>;
52
52
  }
53
+ /**
54
+ * Topbar, trailing edge, **beside** the default chrome rather than instead of it — rendered before
55
+ * the language selector, which stays.
56
+ *
57
+ * ## Why this is not just `*sparkShellTopbarEnd`
58
+ *
59
+ * That slot REPLACES the region, which is right for an auth bar (a host taking over the trailing
60
+ * edge wholesale) and wrong for a page-level action button. A host that only wanted to add a
61
+ * button had to re-render the language selector itself to keep it — which means importing it,
62
+ * knowing it hides itself in a single-language app, and keeping that copy in step with the shell.
63
+ * Every host that did this got it slightly differently.
64
+ *
65
+ * Pairs with `SparkQueryActionsService`: that service resolves a query's custom actions without the
66
+ * grid, and this is where a page-level one goes.
67
+ *
68
+ * ```html
69
+ * <button *sparkShellTopbarActions class="btn btn-primary" (click)="publish()">Publish</button>
70
+ * ```
71
+ *
72
+ * Supplying both slots is allowed and does what it says: `topbarEnd` replaces the default chrome,
73
+ * and these actions still render ahead of whatever it put there.
74
+ */
75
+ declare class SparkShellTopbarActionsDirective {
76
+ readonly templateRef: TemplateRef<unknown>;
77
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SparkShellTopbarActionsDirective, never>;
78
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<SparkShellTopbarActionsDirective, "[sparkShellTopbarActions]", never, {}, {}, never, never, true, never>;
79
+ }
53
80
  /** Sidebar, above everything. Default: `<h5>{{ title }}</h5>`. */
54
81
  declare class SparkShellSidebarHeaderDirective {
55
82
  readonly templateRef: TemplateRef<unknown>;
@@ -160,18 +187,21 @@ declare class SparkShellComponent {
160
187
  readonly sidebarTabs: _angular_core.InputSignal<readonly SparkSidebarTab[]>;
161
188
  readonly topbarStartTemplate: _angular_core.InputSignal<TemplateRef<unknown> | null>;
162
189
  readonly topbarEndTemplate: _angular_core.InputSignal<TemplateRef<unknown> | null>;
190
+ readonly topbarActionsTemplate: _angular_core.InputSignal<TemplateRef<unknown> | null>;
163
191
  readonly sidebarHeaderTemplate: _angular_core.InputSignal<TemplateRef<unknown> | null>;
164
192
  readonly sidebarTopTemplate: _angular_core.InputSignal<TemplateRef<unknown> | null>;
165
193
  readonly sidebarFooterTemplate: _angular_core.InputSignal<TemplateRef<unknown> | null>;
166
194
  readonly mainHeaderTemplate: _angular_core.InputSignal<TemplateRef<unknown> | null>;
167
195
  private readonly topbarStartSlot;
168
196
  private readonly topbarEndSlot;
197
+ private readonly topbarActionsSlot;
169
198
  private readonly sidebarHeaderSlot;
170
199
  private readonly sidebarTopSlot;
171
200
  private readonly sidebarFooterSlot;
172
201
  private readonly mainHeaderSlot;
173
202
  protected readonly topbarStartTpl: _angular_core.Signal<TemplateRef<unknown> | null>;
174
203
  protected readonly topbarEndTpl: _angular_core.Signal<TemplateRef<unknown> | null>;
204
+ protected readonly topbarActionsTpl: _angular_core.Signal<TemplateRef<unknown> | null>;
175
205
  protected readonly sidebarHeaderTpl: _angular_core.Signal<TemplateRef<unknown> | null>;
176
206
  protected readonly sidebarTopTpl: _angular_core.Signal<TemplateRef<unknown> | null>;
177
207
  protected readonly sidebarFooterTpl: _angular_core.Signal<TemplateRef<unknown> | null>;
@@ -189,7 +219,7 @@ declare class SparkShellComponent {
189
219
  protected toggleSidebar(open: boolean): void;
190
220
  protected onShellToggle(detail: ShellStateChangeEventDetail): void;
191
221
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<SparkShellComponent, never>;
192
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<SparkShellComponent, "spark-shell", never, { "title": { "alias": "title"; "required": false; "isSignal": true; }; "breakpoint": { "alias": "breakpoint"; "required": false; "isSignal": true; }; "sidebarTheme": { "alias": "sidebarTheme"; "required": false; "isSignal": true; }; "reloadToken": { "alias": "reloadToken"; "required": false; "isSignal": true; }; "sidebarTabs": { "alias": "sidebarTabs"; "required": false; "isSignal": true; }; "topbarStartTemplate": { "alias": "topbarStartTemplate"; "required": false; "isSignal": true; }; "topbarEndTemplate": { "alias": "topbarEndTemplate"; "required": false; "isSignal": true; }; "sidebarHeaderTemplate": { "alias": "sidebarHeaderTemplate"; "required": false; "isSignal": true; }; "sidebarTopTemplate": { "alias": "sidebarTopTemplate"; "required": false; "isSignal": true; }; "sidebarFooterTemplate": { "alias": "sidebarFooterTemplate"; "required": false; "isSignal": true; }; "mainHeaderTemplate": { "alias": "mainHeaderTemplate"; "required": false; "isSignal": true; }; }, {}, ["topbarStartSlot", "topbarEndSlot", "sidebarHeaderSlot", "sidebarTopSlot", "sidebarFooterSlot", "mainHeaderSlot", "tabSlots"], ["*"], true, never>;
222
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SparkShellComponent, "spark-shell", never, { "title": { "alias": "title"; "required": false; "isSignal": true; }; "breakpoint": { "alias": "breakpoint"; "required": false; "isSignal": true; }; "sidebarTheme": { "alias": "sidebarTheme"; "required": false; "isSignal": true; }; "reloadToken": { "alias": "reloadToken"; "required": false; "isSignal": true; }; "sidebarTabs": { "alias": "sidebarTabs"; "required": false; "isSignal": true; }; "topbarStartTemplate": { "alias": "topbarStartTemplate"; "required": false; "isSignal": true; }; "topbarEndTemplate": { "alias": "topbarEndTemplate"; "required": false; "isSignal": true; }; "topbarActionsTemplate": { "alias": "topbarActionsTemplate"; "required": false; "isSignal": true; }; "sidebarHeaderTemplate": { "alias": "sidebarHeaderTemplate"; "required": false; "isSignal": true; }; "sidebarTopTemplate": { "alias": "sidebarTopTemplate"; "required": false; "isSignal": true; }; "sidebarFooterTemplate": { "alias": "sidebarFooterTemplate"; "required": false; "isSignal": true; }; "mainHeaderTemplate": { "alias": "mainHeaderTemplate"; "required": false; "isSignal": true; }; }, {}, ["topbarStartSlot", "topbarEndSlot", "topbarActionsSlot", "sidebarHeaderSlot", "sidebarTopSlot", "sidebarFooterSlot", "mainHeaderSlot", "tabSlots"], ["*"], true, never>;
193
223
  }
194
224
 
195
225
  /**
@@ -238,5 +268,5 @@ declare class SparkLanguageSelectorComponent {
238
268
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<SparkLanguageSelectorComponent, "spark-language-selector", never, {}, {}, never, never, true, never>;
239
269
  }
240
270
 
241
- export { SparkLanguageSelectorComponent, SparkProgramUnitsComponent, SparkShellComponent, SparkShellMainHeaderDirective, SparkShellSidebarFooterDirective, SparkShellSidebarHeaderDirective, SparkShellSidebarTopDirective, SparkShellTabDirective, SparkShellTopbarEndDirective, SparkShellTopbarStartDirective };
271
+ export { SparkLanguageSelectorComponent, SparkProgramUnitsComponent, SparkShellComponent, SparkShellMainHeaderDirective, SparkShellSidebarFooterDirective, SparkShellSidebarHeaderDirective, SparkShellSidebarTopDirective, SparkShellTabDirective, SparkShellTopbarActionsDirective, SparkShellTopbarEndDirective, SparkShellTopbarStartDirective };
242
272
  export type { SparkSidebarTab };