@mintplayer/ng-spark 22.22.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.
- package/README.md +181 -0
- package/fesm2022/mintplayer-ng-spark-attribute-description.mjs +100 -47
- package/fesm2022/mintplayer-ng-spark-attribute-description.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-client-operations.mjs +308 -329
- package/fesm2022/mintplayer-ng-spark-client-operations.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-column-filter.mjs +175 -135
- package/fesm2022/mintplayer-ng-spark-column-filter.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-grid.mjs +2259 -1117
- package/fesm2022/mintplayer-ng-spark-grid.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-history.mjs +611 -0
- package/fesm2022/mintplayer-ng-spark-history.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-icon.mjs +64 -27
- package/fesm2022/mintplayer-ng-spark-icon.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-models.mjs +365 -753
- package/fesm2022/mintplayer-ng-spark-models.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-moderation.mjs +1212 -0
- package/fesm2022/mintplayer-ng-spark-moderation.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-panels.mjs +52 -0
- package/fesm2022/mintplayer-ng-spark-panels.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-pipes.mjs +1122 -765
- package/fesm2022/mintplayer-ng-spark-pipes.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-create.mjs +273 -169
- package/fesm2022/mintplayer-ng-spark-po-create.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-detail.mjs +786 -410
- package/fesm2022/mintplayer-ng-spark-po-detail.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-edit.mjs +292 -284
- package/fesm2022/mintplayer-ng-spark-po-edit.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-form.mjs +2187 -1225
- package/fesm2022/mintplayer-ng-spark-po-form.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-query-list.mjs +516 -303
- package/fesm2022/mintplayer-ng-spark-query-list.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-renderers.mjs +17 -55
- package/fesm2022/mintplayer-ng-spark-renderers.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs +216 -177
- package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-routes.mjs +24 -28
- package/fesm2022/mintplayer-ng-spark-routes.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-services.mjs +625 -640
- package/fesm2022/mintplayer-ng-spark-services.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-shell.mjs +1013 -397
- package/fesm2022/mintplayer-ng-spark-shell.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-soft-delete.mjs +294 -0
- package/fesm2022/mintplayer-ng-spark-soft-delete.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark.mjs +13 -50
- package/fesm2022/mintplayer-ng-spark.mjs.map +1 -1
- package/package.json +17 -1
- package/types/mintplayer-ng-spark-attribute-description.d.ts +25 -18
- package/types/mintplayer-ng-spark-client-operations.d.ts +133 -160
- package/types/mintplayer-ng-spark-column-filter.d.ts +73 -55
- package/types/mintplayer-ng-spark-grid.d.ts +885 -448
- package/types/mintplayer-ng-spark-history.d.ts +223 -0
- package/types/mintplayer-ng-spark-icon.d.ts +15 -13
- package/types/mintplayer-ng-spark-models.d.ts +624 -573
- package/types/mintplayer-ng-spark-moderation.d.ts +402 -0
- package/types/mintplayer-ng-spark-panels.d.ts +108 -0
- package/types/mintplayer-ng-spark-pipes.d.ts +120 -149
- package/types/mintplayer-ng-spark-po-create.d.ts +46 -37
- package/types/mintplayer-ng-spark-po-detail.d.ts +177 -117
- package/types/mintplayer-ng-spark-po-edit.d.ts +64 -65
- package/types/mintplayer-ng-spark-po-form.d.ts +507 -371
- package/types/mintplayer-ng-spark-query-list.d.ts +118 -82
- package/types/mintplayer-ng-spark-renderers.d.ts +79 -85
- package/types/mintplayer-ng-spark-retry-action-modal.d.ts +31 -34
- package/types/mintplayer-ng-spark-routes.d.ts +7 -11
- package/types/mintplayer-ng-spark-services.d.ts +377 -261
- package/types/mintplayer-ng-spark-shell.d.ts +209 -128
- package/types/mintplayer-ng-spark-soft-delete.d.ts +90 -0
- package/types/mintplayer-ng-spark.d.ts +7 -12
package/README.md
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# @mintplayer/ng-spark
|
|
2
|
+
|
|
3
|
+
The Angular front end for [MintPlayer.Spark](https://github.com/MintPlayer/MintPlayer.Spark): routed
|
|
4
|
+
persistent-object pages (list, detail, create, edit) driven by the server's model, the query grid,
|
|
5
|
+
attribute renderers, client operations, the program-units shell, and the UI halves of the Spark add-on
|
|
6
|
+
packages (soft delete, history, moderation).
|
|
7
|
+
|
|
8
|
+
Sign-in, registration and the account pages are in the companion package
|
|
9
|
+
[`@mintplayer/ng-spark-auth`](https://github.com/MintPlayer/MintPlayer.Spark/blob/master/libs/node_packages/ng-spark-auth/README.md).
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @mintplayer/ng-spark @mintplayer/ng-bootstrap @mintplayer/pagination
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The major version follows Angular's: `22.x` targets Angular 22. Peer dependencies: `@angular/core`,
|
|
18
|
+
`common`, `router`, `forms`, `cdk` (^22), `@mintplayer/ng-bootstrap` (^22.19), `@mintplayer/pagination`,
|
|
19
|
+
`rxjs` (~7.8).
|
|
20
|
+
|
|
21
|
+
## Minimal setup
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
// app.config.ts
|
|
25
|
+
import { provideRouter } from '@angular/router';
|
|
26
|
+
import { provideHttpClient } from '@angular/common/http';
|
|
27
|
+
import { provideSpark } from '@mintplayer/ng-spark';
|
|
28
|
+
import { withSparkTimezone } from '@mintplayer/ng-spark/services';
|
|
29
|
+
|
|
30
|
+
export const appConfig: ApplicationConfig = {
|
|
31
|
+
providers: [
|
|
32
|
+
provideRouter(routes),
|
|
33
|
+
provideHttpClient(...withSparkTimezone()),
|
|
34
|
+
provideSpark(), // optional: { baseUrl: '/spark' } is the default
|
|
35
|
+
],
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// app.routes.ts
|
|
39
|
+
import { sparkRoutes } from '@mintplayer/ng-spark/routes';
|
|
40
|
+
|
|
41
|
+
export const routes: Routes = [
|
|
42
|
+
{ path: 'home', loadComponent: () => import('./home.component') },
|
|
43
|
+
...sparkRoutes(), // last: po/:type, po/:type/:id, query/:queryId, …
|
|
44
|
+
];
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Routes with a parameterised first segment of your own must come **after** `sparkRoutes()`.
|
|
48
|
+
|
|
49
|
+
## Entry points
|
|
50
|
+
|
|
51
|
+
Import from the entry point, not from the package root; each one is a separate chunk.
|
|
52
|
+
|
|
53
|
+
| Entry point | What it provides |
|
|
54
|
+
|---|---|
|
|
55
|
+
| `@mintplayer/ng-spark` | `provideSpark(config?)`, `SPARK_CONFIG` (`baseUrl`), `SPARK_AUTH_STATE` (the bridge `ng-spark-auth` fills) |
|
|
56
|
+
| `/routes` | `sparkRoutes()` — the routed persistent-object and query pages |
|
|
57
|
+
| `/services` | `SparkService`, `SparkStreamingService`, `SparkLanguageService`, `SparkQueryActionsService`, `RetryActionService`; the timezone feature `withSparkTimezone()` |
|
|
58
|
+
| `/models` | The wire types (persistent objects, attributes, queries, envelopes) |
|
|
59
|
+
| `/shell` | `<spark-shell>` with its slot directives, `<spark-program-units>`, `<spark-language-selector>` ([guide](https://github.com/MintPlayer/MintPlayer.Spark/blob/master/docs/guide-program-units.md)) |
|
|
60
|
+
| `/query-list` | `<spark-query-list>` — the routed query page |
|
|
61
|
+
| `/grid` | `<spark-query-grid>`, `<spark-query-card>`, `<spark-grid-cell>`, `<spark-search-box>` and the caption/icon/actions slot directives; `SPARK_GRID_PAGE_SIZES` |
|
|
62
|
+
| `/column-filter` | `<spark-column-filter-panel>` |
|
|
63
|
+
| `/po-detail`, `/po-create`, `/po-edit` | The routed detail, create and edit pages |
|
|
64
|
+
| `/po-form` | `<spark-po-form>`, `<spark-reference-picker>`, `<spark-lookup-picker>` |
|
|
65
|
+
| `/renderers` | `provideSparkAttributeRenderers([...])`, `SPARK_ATTRIBUTE_RENDERERS`, `withDeclaredInputs` ([guide](https://github.com/MintPlayer/MintPlayer.Spark/blob/master/docs/guide-custom-attribute-renderers.md)) |
|
|
66
|
+
| `/panels` | `provideSparkDetailPanels(...)`, `provideSparkDetailActions(...)`, `provideSparkQueryListActions(...)` — how add-ons put components on the routed pages |
|
|
67
|
+
| `/client-operations` | `provideSparkClientOperations()` — notify, navigate and refresh operations from server-side action code; the toast container |
|
|
68
|
+
| `/retry-action-modal` | The modal that answers a server's retry action ([guide](https://github.com/MintPlayer/MintPlayer.Spark/blob/master/docs/guide-manager-retry-actions.md)) |
|
|
69
|
+
| `/attribute-description` | The [i] tooltip for attribute help text ([guide](https://github.com/MintPlayer/MintPlayer.Spark/blob/master/docs/guide-attribute-descriptions.md)) |
|
|
70
|
+
| `/icon` | `<spark-icon>` |
|
|
71
|
+
| `/pipes` | The pipes the pages use (attribute values, references, lookups, translations, router links) |
|
|
72
|
+
| `/soft-delete` | `provideSparkSoftDelete()` — the Deleted toggle on query lists, the recycle bin, Restore / Purge |
|
|
73
|
+
| `/history` | `provideSparkHistory()` — `<spark-po-history>`: revision list, read-only view, diff, Revert |
|
|
74
|
+
| `/moderation` | `provideSparkModeration()`, `sparkModerationRoutes()`, `sparkModerationRenderers` — vote widget, flag button, review queue, reputation badge, moderator panel |
|
|
75
|
+
|
|
76
|
+
### Timezone (`withSparkTimezone`)
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
provideHttpClient(...withSparkTimezone({ cookieName: 'spark-timezone' }))
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Sends the browser's IANA zone as a header and writes it to a cookie (only when it changed) so a
|
|
83
|
+
server-side render can read it. The header is never sent on the server platform. Use the same cookie
|
|
84
|
+
name as the server's `Spark:TimeZone:CookieName`; `cookieName: false` writes no cookie. See
|
|
85
|
+
[guide-dates-and-sorting.md](https://github.com/MintPlayer/MintPlayer.Spark/blob/master/docs/guide-dates-and-sorting.md).
|
|
86
|
+
|
|
87
|
+
### Panels and actions on the routed pages
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import { provideSparkDetailPanels, provideSparkDetailActions } from '@mintplayer/ng-spark/panels';
|
|
91
|
+
|
|
92
|
+
providers: [
|
|
93
|
+
provideSparkDetailPanels({ id: 'audit', component: AuditPanelComponent, order: 10 }),
|
|
94
|
+
provideSparkDetailActions({ id: 'export', component: ExportButtonComponent }),
|
|
95
|
+
]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Each component declares `context = input.required<SparkDetailContext>()` (query-list actions:
|
|
99
|
+
`SparkQueryListContext`) and does its own permission checks. A second registration with the same `id`
|
|
100
|
+
replaces the first.
|
|
101
|
+
|
|
102
|
+
### Query toolbar, selection and sub-queries
|
|
103
|
+
|
|
104
|
+
The grid (`/grid`) owns one toolbar model, `SparkQueryGridComponent.toolbarActions()`. It holds the
|
|
105
|
+
server's default `New` and `Delete` (`isDefault` entries from `/spark/actions/list`) and the custom
|
|
106
|
+
actions, each enabled from the live selection count. The sub-query card's header renders it on the
|
|
107
|
+
right, with the overflow under the translated "More" label (`common.more`), and the query page's
|
|
108
|
+
action bar renders it too.
|
|
109
|
+
|
|
110
|
+
The grid also renders:
|
|
111
|
+
- an "N selected" chip while rows are selected. There is no select-all: with paged, lazy or
|
|
112
|
+
virtual-scrolled rows it could only tick the rows loaded so far. Deselect-all is the datatable's
|
|
113
|
+
own header checkbox, shown only while a row is selected. Single selection has no checkbox
|
|
114
|
+
column, so there the chip carries a ⊗ that clears the selection;
|
|
115
|
+
- a per-row `⋮` menu of the actions whose rule accepts one row. A menu item runs on that row only and
|
|
116
|
+
leaves the checkbox selection alone. The menu is a CDK connected overlay with ng-bootstrap's
|
|
117
|
+
`<bs-dropdown-menu>` inside, not `@mintplayer/ng-bootstrap/dropdown`, pending
|
|
118
|
+
[ng-bootstrap #419](https://github.com/MintPlayer/mintplayer-ng-bootstrap/issues/419) (the
|
|
119
|
+
dropdown fesm fails to initialise in unlinked JIT test runs).
|
|
120
|
+
|
|
121
|
+
- **Selection** follows `selectionMode` (`'auto' | 'none' | 'single' | 'multiple'`).
|
|
122
|
+
- It is set on the query, or on the parent type's `queries` entry, which `<spark-query-card
|
|
123
|
+
[selectionMode]>` and `<spark-query-grid [selectionModeSetting]>` take.
|
|
124
|
+
- `'auto'` derives it from the custom actions, as before.
|
|
125
|
+
- **Delete** posts the selection to `SparkService.deleteMany()` (`/spark/po/delete-many`). One
|
|
126
|
+
request deletes all the rows or none.
|
|
127
|
+
- **New** on a sub-query navigates to the create page with `parentId`, `parentType` and `queryId`.
|
|
128
|
+
The create page always asks `SparkService.newObject()` (`/spark/po/new`) for its blank object, so
|
|
129
|
+
the server's `OnNewAsync` sets the defaults. For a sub-query, its base fills the reference to the
|
|
130
|
+
parent.
|
|
131
|
+
- Read `EntityType.queries` with `subQueriesOf(type)`. An entry is a bare alias or
|
|
132
|
+
`{ query, selectionMode?, parentReference? }`.
|
|
133
|
+
- **Search.** The card's header has a search box on the right, after the actions, as Vidyano's
|
|
134
|
+
sub-query tabs do. It is `<spark-search-box [(term)]>`, the same component the query page uses: a
|
|
135
|
+
300 ms debounce, a clear button, and Escape to clear. The term goes to the grid's `search`, so the
|
|
136
|
+
server searches the sub-query's rows (with `parentId`/`parentType`), and to the column filters'
|
|
137
|
+
value lists as `querySearch`. **A new term clears the selection.** The card's `search` input is the
|
|
138
|
+
starting term; `[searchable]="false"` hides the box, and a card over bound `data` has none.
|
|
139
|
+
- **Recycle bin.** While the grid lists `deleted: 'only'`, or sits under a deleted parent, its
|
|
140
|
+
toolbar and row menu are empty (no New, no Delete, no custom action): the recycle bin offers only
|
|
141
|
+
Restore and Purge. `<spark-query-card>` takes `[deleted]` (the rows' mode, forwarded to its grid)
|
|
142
|
+
and `[parentDeleted]` (the parent is a deleted row; the detail page sets it for a row opened with
|
|
143
|
+
`?deleted=only`). Under a deleted parent the grid sends `parentDeleted: 'include'` on execute and
|
|
144
|
+
distinct-values, which the server honours only for holders of `ViewDeleted/{ParentType}`.
|
|
145
|
+
|
|
146
|
+
```html
|
|
147
|
+
<spark-search-box [(term)]="term" />
|
|
148
|
+
<spark-query-grid queryId="all-cars" [search]="term()" />
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
See [guide-custom-actions.md](https://github.com/MintPlayer/MintPlayer.Spark/blob/master/docs/guide-custom-actions.md)
|
|
152
|
+
for the server side of this.
|
|
153
|
+
|
|
154
|
+
### Soft delete, history and moderation
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
import { provideSparkSoftDelete } from '@mintplayer/ng-spark/soft-delete';
|
|
158
|
+
import { provideSparkHistory } from '@mintplayer/ng-spark/history';
|
|
159
|
+
import { provideSparkModeration, sparkModerationRenderers, sparkModerationRoutes } from '@mintplayer/ng-spark/moderation';
|
|
160
|
+
import { provideSparkAttributeRenderers } from '@mintplayer/ng-spark/renderers';
|
|
161
|
+
|
|
162
|
+
providers: [
|
|
163
|
+
provideSparkSoftDelete(),
|
|
164
|
+
provideSparkHistory(),
|
|
165
|
+
provideSparkModeration(),
|
|
166
|
+
provideSparkAttributeRenderers([...sparkModerationRenderers]),
|
|
167
|
+
]
|
|
168
|
+
|
|
169
|
+
// routes: ...sparkModerationRoutes() before ...sparkRoutes()
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Each needs its server package: [SoftDelete](https://github.com/MintPlayer/MintPlayer.Spark/blob/master/libs/soft_delete/MintPlayer.Spark.SoftDelete/README.md),
|
|
173
|
+
[History](https://github.com/MintPlayer/MintPlayer.Spark/blob/master/libs/history/MintPlayer.Spark.History/README.md),
|
|
174
|
+
[Moderation](https://github.com/MintPlayer/MintPlayer.Spark/blob/master/libs/moderation/MintPlayer.Spark.Moderation/README.md)
|
|
175
|
+
([guide](https://github.com/MintPlayer/MintPlayer.Spark/blob/master/docs/guide-moderation.md)). `apps/QnA` uses all three.
|
|
176
|
+
|
|
177
|
+
## More
|
|
178
|
+
|
|
179
|
+
- [Repository README](https://github.com/MintPlayer/MintPlayer.Spark/blob/master/README.md) — the developer guides
|
|
180
|
+
- [HTTP API specification](https://github.com/MintPlayer/MintPlayer.Spark/blob/master/docs/Spark-API-Specification.md)
|
|
181
|
+
- [Release notes 11.0.0-preview.91 / ng-spark 22.24.0](https://github.com/MintPlayer/MintPlayer.Spark/blob/master/docs/release-notes-preview-91.md)
|
|
@@ -1,37 +1,48 @@
|
|
|
1
|
-
import * as i0 from
|
|
2
|
-
import {
|
|
3
|
-
import { BsTooltipDirective } from
|
|
4
|
-
import { SparkIconComponent } from
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { ChangeDetectionStrategy, Component, computed, input } from "@angular/core";
|
|
3
|
+
import { BsTooltipDirective } from "@mintplayer/ng-bootstrap/tooltip";
|
|
4
|
+
import { SparkIconComponent } from "@mintplayer/ng-spark/icon";
|
|
5
|
+
import { currentLanguage, resolveTranslation } from "@mintplayer/ng-spark/models";
|
|
6
|
+
var SparkAttributeDescriptionComponent = class SparkAttributeDescriptionComponent {
|
|
7
|
+
description = input(...ngDevMode ? [void 0, { debugName: "description" }] : /* istanbul ignore next */ []);
|
|
8
|
+
position = input("top", ...ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []);
|
|
9
|
+
text = computed(() => resolveTranslation(this.description(), currentLanguage()).trim(), ...ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []);
|
|
10
|
+
onClick(event) {
|
|
11
|
+
event.preventDefault();
|
|
12
|
+
event.stopPropagation();
|
|
13
|
+
}
|
|
14
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
15
|
+
minVersion: "12.0.0",
|
|
16
|
+
version: "22.2.0",
|
|
17
|
+
ngImport: i0,
|
|
18
|
+
type: SparkAttributeDescriptionComponent,
|
|
19
|
+
deps: [],
|
|
20
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
21
|
+
});
|
|
22
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
23
|
+
minVersion: "17.0.0",
|
|
24
|
+
version: "22.2.0",
|
|
25
|
+
type: SparkAttributeDescriptionComponent,
|
|
26
|
+
isStandalone: true,
|
|
27
|
+
selector: "spark-attribute-description",
|
|
28
|
+
inputs: {
|
|
29
|
+
description: {
|
|
30
|
+
classPropertyName: "description",
|
|
31
|
+
publicName: "description",
|
|
32
|
+
isSignal: true,
|
|
33
|
+
isRequired: false,
|
|
34
|
+
transformFunction: null
|
|
35
|
+
},
|
|
36
|
+
position: {
|
|
37
|
+
classPropertyName: "position",
|
|
38
|
+
publicName: "position",
|
|
39
|
+
isSignal: true,
|
|
40
|
+
isRequired: false,
|
|
41
|
+
transformFunction: null
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
ngImport: i0,
|
|
45
|
+
template: `
|
|
35
46
|
@if (text(); as text) {
|
|
36
47
|
<button
|
|
37
48
|
type="button"
|
|
@@ -42,11 +53,36 @@ class SparkAttributeDescriptionComponent {
|
|
|
42
53
|
<span *bsTooltip="position()" class="spark-attribute-description-text">{{ text }}</span>
|
|
43
54
|
</button>
|
|
44
55
|
}
|
|
45
|
-
`,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
56
|
+
`,
|
|
57
|
+
isInline: true,
|
|
58
|
+
styles: [":host{display:inline-block;line-height:1}.spark-attribute-description-trigger{color:inherit;opacity:.6;font-size:.875em;vertical-align:baseline}.spark-attribute-description-trigger:hover,.spark-attribute-description-trigger:focus-visible{opacity:1}.spark-attribute-description-text{display:inline-block;white-space:pre-line;text-align:start;max-width:20rem}\n"],
|
|
59
|
+
dependencies: [{
|
|
60
|
+
kind: "directive",
|
|
61
|
+
type: BsTooltipDirective,
|
|
62
|
+
selector: "*[bsTooltip]",
|
|
63
|
+
inputs: ["bsTooltip"]
|
|
64
|
+
}, {
|
|
65
|
+
kind: "component",
|
|
66
|
+
type: SparkIconComponent,
|
|
67
|
+
selector: "spark-icon",
|
|
68
|
+
inputs: ["name"]
|
|
69
|
+
}],
|
|
70
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
71
|
+
});
|
|
72
|
+
};
|
|
73
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
74
|
+
minVersion: "12.0.0",
|
|
75
|
+
version: "22.2.0",
|
|
76
|
+
ngImport: i0,
|
|
77
|
+
type: SparkAttributeDescriptionComponent,
|
|
78
|
+
decorators: [{
|
|
79
|
+
type: Component,
|
|
80
|
+
args: [{
|
|
81
|
+
selector: "spark-attribute-description",
|
|
82
|
+
standalone: true,
|
|
83
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
84
|
+
imports: [BsTooltipDirective, SparkIconComponent],
|
|
85
|
+
template: `
|
|
50
86
|
@if (text(); as text) {
|
|
51
87
|
<button
|
|
52
88
|
type="button"
|
|
@@ -57,12 +93,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
|
|
|
57
93
|
<span *bsTooltip="position()" class="spark-attribute-description-text">{{ text }}</span>
|
|
58
94
|
</button>
|
|
59
95
|
}
|
|
60
|
-
`,
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
96
|
+
`,
|
|
97
|
+
styles: [":host{display:inline-block;line-height:1}.spark-attribute-description-trigger{color:inherit;opacity:.6;font-size:.875em;vertical-align:baseline}.spark-attribute-description-trigger:hover,.spark-attribute-description-trigger:focus-visible{opacity:1}.spark-attribute-description-text{display:inline-block;white-space:pre-line;text-align:start;max-width:20rem}\n"]
|
|
98
|
+
}]
|
|
99
|
+
}],
|
|
100
|
+
propDecorators: {
|
|
101
|
+
description: [{
|
|
102
|
+
type: i0.Input,
|
|
103
|
+
args: [{
|
|
104
|
+
isSignal: true,
|
|
105
|
+
alias: "description",
|
|
106
|
+
required: false
|
|
107
|
+
}]
|
|
108
|
+
}],
|
|
109
|
+
position: [{
|
|
110
|
+
type: i0.Input,
|
|
111
|
+
args: [{
|
|
112
|
+
isSignal: true,
|
|
113
|
+
alias: "position",
|
|
114
|
+
required: false
|
|
115
|
+
}]
|
|
116
|
+
}]
|
|
117
|
+
}
|
|
118
|
+
});
|
|
67
119
|
export { SparkAttributeDescriptionComponent };
|
|
68
|
-
|
|
120
|
+
|
|
121
|
+
//# sourceMappingURL=mintplayer-ng-spark-attribute-description.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mintplayer-ng-spark-attribute-description.mjs","sources":["../../attribute-description/src/spark-attribute-description.component.ts"
|
|
1
|
+
{"version":3,"file":"mintplayer-ng-spark-attribute-description.mjs","names":[],"sources":["../../attribute-description/src/spark-attribute-description.component.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport { BsTooltipDirective } from '@mintplayer/ng-bootstrap/tooltip';\nimport { SparkIconComponent } from '@mintplayer/ng-spark/icon';\nimport { TranslatedString, currentLanguage, resolveTranslation } from '@mintplayer/ng-spark/models';\n\nexport type SparkAttributeDescriptionPosition = 'top' | 'bottom' | 'start' | 'end';\n\n/**\n * The [i] beside an attribute label: a focusable button whose tooltip shows the attribute's\n * `description` (#348). Renders nothing when the model declares no description, so every label\n * site can include it unconditionally.\n *\n * Accessibility comes from `*bsTooltip`: it opens on hover AND focus, closes on Escape, and sets\n * `aria-describedby` on the button while open. The button's own name is the description text, so\n * a screen reader announces the help on focus without waiting for the tooltip.\n *\n * Clicks are stopped: the [i] lives inside sortable grid headers and `<label for>` elements, and\n * must neither toggle the sort nor move focus into the input.\n */\n@Component({\n selector: 'spark-attribute-description',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [BsTooltipDirective, SparkIconComponent],\n template: `\n @if (text(); as text) {\n <button\n type=\"button\"\n class=\"btn btn-link p-0 ms-1 align-baseline spark-attribute-description-trigger\"\n [attr.aria-label]=\"text\"\n (click)=\"onClick($event)\">\n <spark-icon name=\"info-circle\" />\n <span *bsTooltip=\"position()\" class=\"spark-attribute-description-text\">{{ text }}</span>\n </button>\n }\n `,\n styles: [`\n :host {\n display: inline-block;\n line-height: 1;\n }\n .spark-attribute-description-trigger {\n color: inherit;\n opacity: 0.6;\n font-size: 0.875em;\n vertical-align: baseline;\n }\n .spark-attribute-description-trigger:hover,\n .spark-attribute-description-trigger:focus-visible {\n opacity: 1;\n }\n .spark-attribute-description-text {\n display: inline-block;\n white-space: pre-line;\n text-align: start;\n max-width: 20rem;\n }\n `],\n})\nexport class SparkAttributeDescriptionComponent {\n /** The attribute's `description`; `undefined` (the common case) renders nothing. */\n description = input<TranslatedString | undefined>();\n\n /** Where the tooltip opens relative to the [i]. */\n position = input<SparkAttributeDescriptionPosition>('top');\n\n /** Resolved for the current language; re-evaluates when the user switches language. */\n text = computed(() => resolveTranslation(this.description(), currentLanguage()).trim());\n\n onClick(event: MouseEvent): void {\n event.preventDefault();\n event.stopPropagation();\n }\n}\n"],"mappings":";;;;;AA2DA,IAAa,qCAAb,MAAa,mCAAkC;CAE7C,cAAc,MAAqC,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAGnD,WAAW,MAAyC,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CAG1D,OAAO,eAAe,mBAAmB,KAAK,YAAW,GAAI,gBAAe,CAAE,CAAC,CAAC,KAAI,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAEvF,QAAQ,OAAiB;EACvB,MAAM,eAAc;EACpB,MAAM,gBAAe;CACvB;CAbW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAkC,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAlC,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAkC,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,aAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,UAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,UAAA;EAAA,UAnCnC;;;;;;;;;;;;EAWT,UAAA;EAAA,QAAA,CAAA,yWAAA;EAAA,cAAA,CAAA;GAAA,MAAA;GAAA,MAZS;GAAkB,UAAA;GAAA,QAAA,CAAA,WAAA;EAAA,GAAA;GAAA,MAAA;GAAA,MAAE;GAAkB,UAAA;GAAA,QAAA,CAAA,MAAA;EAAA,CAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AAoCrC,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAkC,YAAA,CAAA;EAxC9C,MAAA;EACW,MAAA,CAAA;GAAA,UAAA;GAA6B,YAC3B;GAAI,iBACC,wBAAwB;GAAM,SACtC,CAAC,oBAAoB,kBAAkB;GAAC,UACvC;;;;;;;;;;;;GAWT,QAAA,CAAA,yWAAA;EAAA,CAAA"}
|