@eherve/angular-material-display-dialog 0.0.0-stage → 22.0.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 CHANGED
@@ -1,3 +1,115 @@
1
- # Temporary Holding Version
1
+ # Angular Material Display Dialog
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Generic record consultation with Angular Material, using `@eherve/angular-material-section-tabs` for declarative content. Requires Angular/Material/CDK 22 and RxJS 7.8.
4
+
5
+ ```sh
6
+ npm install @eherve/angular-material-display-dialog @eherve/angular-material-section-tabs
7
+ ```
8
+
9
+ Import `DisplayDialogModule` in your Angular module (also supported in standalone imports), provide Angular Material animations, and include the distributed overlay stylesheet in global styles:
10
+
11
+ ```css
12
+ @import '@eherve/angular-material-display-dialog/styles.css';
13
+ ```
14
+
15
+ ```ts
16
+ import { DisplayDialogService, DisplayDialogData } from '@eherve/angular-material-display-dialog';
17
+
18
+ const data: DisplayDialogData<{name: string}> = {
19
+ record: {name: 'Example'},
20
+ title: record => record.name,
21
+ displayOptions: {
22
+ section: {
23
+ id: 'main', label: 'Details', cards: [{
24
+ id: 'identity', label: 'Identity',
25
+ fields: [{kind: 'text', label: 'Name', path: 'name'}],
26
+ }],
27
+ },
28
+ },
29
+ actions: [{
30
+ label: 'Refresh', position: 'top',
31
+ handle: async context => context.setRecord(await fetchRecord()),
32
+ }],
33
+ };
34
+ const ref = displayDialogService.open(data);
35
+ ref.afterClosed().subscribe(result => console.log(result));
36
+ ```
37
+
38
+ Supply exactly one of `record` or `loadRecord: () => Promise<T> | Observable<T>`. Only the first Observable value is consumed. Empty loaders use `emptyLabel`; rejected loaders use `errorLabel`. `loadingLabel`, `closeLabel`, `showCloseButton` and `showJsonDataButton` customize the surrounding UI. JSON is opt-in; application permissions belong to the caller. `DisplayDialogIntl` is injectable and supplies default labels.
39
+
40
+ Four root modes are supported: `{section}` (one page), `{sections}` (section navigation), `{tabs: [{label, displayOptions}]}` (root tabs) and `{component, input?, overflow?}`. Keep the hierarchy **section → cards → fields**. `showEmptyFields`, `showEmptyFieldsToggle` and `showEmptyFieldsLabel` work in section modes. Card and field components follow the section-tabs contract. Content components receive declared `record`, `data`, `displayOptions` inputs and any declared custom inputs; inputs may be calculated from the current record. HTML labels use Angular sanitization.
41
+
42
+ Global button actions use `handle(context)`; card actions retain `handler(context)` and `menuHandler(optionId, context)`. Positions are `top`, `bottom` (default), `bottom-end`. Visibility and disabled predicates use the current record. `confirm` accepts a message or `{title?, message, ok?, cancel?}`. Cancellation performs no action. Rejections preserve the record, keep the dialog open, restore interaction and report through Angular `ErrorHandler` plus a generic error message. Handlers own business writes. `setRecord(record)` updates titles, content, actions and connection callbacks; `close(result)` and `closeOnHandle` preserve the exact result object.
43
+
44
+ Component actions use `{component, position?, input?}`. Inputs are filtered to declared Angular inputs and recalculated after record changes. They receive automatic `record` and `data` when declared.
45
+
46
+ Each opening can create application integration state using `connect`:
47
+
48
+ ```ts
49
+ connect: () => {
50
+ const binding = createApplicationBinding();
51
+ return {
52
+ actions: [{component: ApplicationAction, position: 'top', input: ({record}) => ({record, binding})}],
53
+ recordChanged: record => binding.update(record),
54
+ destroy: () => binding.destroy(),
55
+ };
56
+ }
57
+ ```
58
+
59
+ The factory runs once per initialization before loading. Configuration actions precede connection actions, with no mutation of the configuration. Every replaced/destroyed connection is cleaned once, including loader failures. Stale results and callbacks after destruction are ignored. Connection callback failures are reported without interrupting cleanup. URL, permissions and application context integrations belong here; no Router or application service is required by this package.
60
+
61
+ `DISPLAY_DIALOG_HOST` has a working default backed by MatDialog for confirmations and escaped JSON text. Override it only to integrate application UI:
62
+
63
+ ```ts
64
+ {provide: DISPLAY_DIALOG_HOST, useExisting: ApplicationDisplayDialogHost}
65
+ // confirm(options: DisplayDialogConfirmOptions): Promise<boolean>
66
+ // showJson(title: string, sources: readonly DisplayDialogJsonSource[]): void
67
+ // Each source has {label, value}.
68
+ ```
69
+
70
+ The second `open` argument accepts Material configuration and `nested`. Standard dimensions are `90vw` × `90vh` with matching maxima, `autoFocus:false`, `restoreFocus:false` and panel class `display-dialog-panel`. Nested dialogs use parent dimensions minus 64px, minimum 640×480px, constrained by viewport minus 16px on each side. Override these via `{nested:{inset,minWidth,minHeight,viewportMargin}}`, disable with `{nested:null}`, or supply explicit width/height/maxWidth/maxHeight (individually higher priority).
71
+
72
+ For embedded rendering, use `<app-display-dialog [data]="data" />` after importing `DisplayDialogModule`; no MatDialogRef is required.
73
+
74
+ ## Theme variables
75
+
76
+ Set these properties on a common ancestor such as `:root`, on a dialog overlay ancestor, or directly on an embedded `app-display-dialog`. The package uses independent defaults and does not require application CSS variables.
77
+
78
+ | Public property | Default | Purpose |
79
+ | --- | --- | --- |
80
+ | `--ngx-mat-display-dialog-primary` | `#0f334d` | Primary text, icons and default action background |
81
+ | `--ngx-mat-display-dialog-background` | `#f4f6f8` | Content background |
82
+ | `--ngx-mat-display-dialog-text` | `#102f49` | Main text |
83
+ | `--ngx-mat-display-dialog-muted` | `#61718a` | Empty-state and secondary text |
84
+ | `--ngx-mat-display-dialog-border` | `rgba(14, 43, 67, 0.12)` | Header and footer borders |
85
+ | `--ngx-mat-display-dialog-header-background` | `#e9eef2` | Header background |
86
+ | `--ngx-mat-display-dialog-header-text` | `#102f49` | Header text and icons |
87
+
88
+ ## Runtime translations
89
+
90
+ `DisplayDialogIntl` exposes `messages: DisplayDialogMessages` and `readonly changes: Subject<void>`. The dictionary is fully typed without an open index signature. Replace or update messages, then emit `changes.next()` to refresh existing dialogs, including loading, empty, load-error, action-error and close labels. Explicit configuration labels remain unchanged. The default confirmation host also updates its default title/buttons while open, and the JSON view updates its close button. Explicit confirmation labels and caller-provided JSON titles/source labels remain owned by their caller. Subscriptions are released on component destruction.
91
+
92
+ ```ts
93
+ const intl = inject(DisplayDialogIntl);
94
+ intl.messages = {...intl.messages, loadingLabel: 'Loading data', closeLabel: 'Close'};
95
+ intl.changes.next();
96
+ ```
97
+
98
+ All message keys and French defaults:
99
+
100
+ | Key | Default |
101
+ | --- | --- |
102
+ | `loadingLabel` | `Chargement des données` |
103
+ | `closeLabel` | `Fermer` |
104
+ | `emptyLabel` | `Aucune donnée à afficher.` |
105
+ | `errorLabel` | `Impossible de charger les données.` |
106
+ | `actionErrorLabel` | `Impossible d’exécuter cette action.` |
107
+ | `jsonTitle` | `Données JSON` |
108
+ | `jsonButtonLabel` | `Afficher les données JSON` |
109
+ | `recordLabel` | `Record` |
110
+ | `confirmTitle` | `Confirmation` |
111
+ | `confirmOk` | `Oui` |
112
+ | `confirmCancel` | `Non` |
113
+ | `emptyContentLabel` | `Aucun contenu à afficher.` |
114
+
115
+ The host receives the caller's confirmation options with optional labels intact. Its default Material implementation applies the Intl defaults; an application host may supply its own translated defaults.