@praxisui/list 1.0.0-beta.4 → 1.0.0-beta.40

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,5 +1,12 @@
1
1
  # @praxisui/list — Configurable List/Cards Component
2
2
 
3
+ ## 🔰 Exemplos / Quickstart
4
+
5
+ Para ver esta biblioteca em funcionamento em uma aplicação completa, utilize o projeto de exemplo (Quickstart):
6
+
7
+ - Repositório: https://github.com/codexrodrigues/praxis-ui-quickstart
8
+ - O Quickstart demonstra a integração das bibliotecas `@praxisui/*` em um app Angular, incluindo instalação, configuração e uso em telas reais.
9
+
3
10
  Angular list/cards component for enterprise apps. Supports local or remote data, multiple layout variants, templating slots, actions, grouping and selection.
4
11
 
5
12
  ## Install
@@ -13,6 +20,7 @@ Peers (install in your app):
13
20
  - `rxjs` (>=7 <9)
14
21
  - `@praxisui/core` (icons, config storage, CRUD service)
15
22
  - Optional: `@praxisui/settings-panel` (to open the in-app list configuration editor)
23
+ - Optional: `@praxisui/dynamic-fields` (color picker used by the in-app editor)
16
24
 
17
25
  ## Quick Start
18
26
 
@@ -26,6 +34,7 @@ import { PraxisList } from '@praxisui/list';
26
34
  imports: [PraxisList],
27
35
  template: `
28
36
  <praxis-list
37
+ listId="products-list"
29
38
  [config]="config"
30
39
  (itemClick)="onItem($event)"
31
40
  (actionClick)="onAction($event)"
@@ -64,12 +73,85 @@ export class ListDemoComponent {
64
73
  }
65
74
  ```
66
75
 
76
+ ## Runtime Contract (Data Mode and Precedence)
77
+
78
+ Effective data mode resolution follows `ListDataService.stream()`:
79
+
80
+ 1. if `dataSource.data` exists, local mode is used;
81
+ 2. else if `dataSource.resourcePath` exists and `GenericCrudService` is available, remote mode is used;
82
+ 3. otherwise, empty mode is used.
83
+
84
+ Critical rule:
85
+ - local data has precedence over remote when both `dataSource.data` and `dataSource.resourcePath` are present.
86
+
87
+ Decision matrix (runtime today):
88
+
89
+ | `dataSource.data` | `dataSource.resourcePath` | Resolved mode | Data pipeline | Main surface |
90
+ | --- | --- | --- | --- | --- |
91
+ | array | any value | local | local array only | list/cards/tiles |
92
+ | missing/null | filled | remote | `/filter` with fallback `getAll()` on failure | list/cards/tiles + remote controls |
93
+ | missing/null | missing/empty | empty | none | empty state |
94
+
95
+ Important behavior:
96
+ - pagination/search/sort controls from `ui.*` are rendered only when `dataSource.resourcePath` is defined.
97
+ - remote mode uses `GenericCrudService.filter(query, pageable)` and falls back to `getAll()` when `/filter` fails.
98
+
99
+ ## Runtime Status Matrix (High-Impact Paths)
100
+
101
+ | JSON path | Runtime status | Notes |
102
+ | --- | --- | --- |
103
+ | `dataSource.data` | Active | Local mode source. |
104
+ | `dataSource.resourcePath` | Active | Remote mode source. |
105
+ | `layout.virtualScroll` | Declared-only | Accepted in config/editor but no runtime binding yet. |
106
+ | `layout.stickySectionHeader` | Declared-only | Accepted in config/editor but no runtime sticky behavior yet. |
107
+ | `actions[].emitPayload` | Declared-only | Authoring field only; `actionClick` payload shape is fixed. |
108
+ | `events.*` | Declared-only | Declarative mapping only; no dynamic event router in runtime. |
109
+ | `a11y.highContrast` / `a11y.reduceMotion` | Declared-only | No visual/runtime enforcement yet. |
110
+
111
+ ## Pagina de documentacao viva (showcase completo)
112
+
113
+ Para documentar o componente com exemplos live (layout, templating, selecao, acoes, skins e snippets),
114
+ use o componente `praxis-list-doc-page`:
115
+
116
+ ```html
117
+ <praxis-list-doc-page></praxis-list-doc-page>
118
+ ```
119
+
120
+ ```ts
121
+ import { Component } from '@angular/core';
122
+ import { PraxisListDocPageComponent } from '@praxisui/list';
123
+
124
+ @Component({
125
+ selector: 'app-list-doc-host',
126
+ standalone: true,
127
+ imports: [PraxisListDocPageComponent],
128
+ template: `<praxis-list-doc-page />`,
129
+ })
130
+ export class ListDocHostComponent {}
131
+ ```
132
+
133
+ Cobertura da pagina:
134
+ - Variantes `list`, `cards`, `tiles`.
135
+ - `density`, `lines`, `model`, `groupBy`, `dividers`.
136
+ - Slots `leading`, `primary`, `secondary`, `meta`, `trailing`, `sectionHeader`, `emptyState`.
137
+ - Tipos de template `text`, `icon`, `image`, `chip`, `rating`, `currency`, `date`, `html`.
138
+ - Selecao (`none`, `single`, `multiple`) com `FormControl` externo.
139
+ - Acoes com `showIf`, estilos `icon/button` e log de eventos.
140
+ - Skins `elevated`, `pill-soft`, `glass`, `gradient-tile`, `custom`.
141
+ - Snippets para host, config JSON e contrato remoto com `resourcePath`.
142
+
143
+ ## Persistência
144
+
145
+ - `listId` é obrigatório para salvar/carregar configurações.
146
+ - A chave usada no storage é `praxis-list-config-<component_id>` (via `ComponentKeyService`).
147
+ - Use `componentInstanceId` quando houver múltiplas listas com o mesmo `listId` na mesma rota.
148
+
67
149
  ## Remote Data (resourcePath)
68
150
 
69
151
  Provide `dataSource.resourcePath` to fetch data and (optionally) infer templating from backend schema.
70
152
 
71
153
  ```html
72
- <praxis-list [config]="{
154
+ <praxis-list listId="employees" [config]="{
73
155
  id: 'employees',
74
156
  dataSource: { resourcePath: 'employees', sort: ['name,asc'] },
75
157
  layout: { variant: 'list', lines: 2, groupBy: 'department' },
@@ -83,25 +165,51 @@ The component uses `GenericCrudService` from `@praxisui/core` when `resourcePath
83
165
 
84
166
  - `list` (default): Material list with optional selection and dividers.
85
167
  - `cards`: Card grid layout with the same templating slots.
168
+ - `tiles`: Modern grid layout (image + title + meta), ideal for catalogs.
86
169
 
87
170
  Layout options (`config.layout`):
88
171
  - `lines`: 1 | 2 | 3 controls visible text lines.
89
172
  - `dividers`: 'none' | 'between' | 'all'.
90
173
  - `groupBy`: string key to group items; section headers can be templated via `templating.sectionHeader`.
91
- - `pageSize`, `virtualScroll`, `density`, `model` for advanced tuning.
174
+ - `pageSize`, `density`, `model` are runtime-active.
175
+ - `virtualScroll` and `stickySectionHeader` are currently declared-only (no runtime binding yet).
176
+
177
+ ## Config Merging Behavior
178
+ Be aware that `applyConfigFromAdapter` replaces the entire `config` object. It does not perform a deep merge. Any local runtime overrides must be re-applied or managed carefully.
92
179
 
93
180
  ## Templating Slots
94
181
 
95
182
  Every slot accepts a `TemplateDef` with `type`, `expr`, optional `class` and `style`.
96
- - `leading`: 'icon' | 'image' with optional `badge`.
97
- - `primary`: 'text' | 'html' | 'date' | 'currency' | 'rating' | 'chip'.
183
+ - `leading`: 'icon' | 'image' | 'text' | 'chip' | 'rating' | 'html' with optional `badge`.
184
+ - `primary`: 'text' | 'html' | 'date' | 'currency'.
98
185
  - `secondary`: same as primary; shown when `lines > 1`.
99
- - `meta`: small text or chip/rating rendered inline or on the side (`metaPlacement`).
100
- - `trailing`: optional trailing text/chip.
186
+ - `meta`: small text or chip/rating/icon/image rendered inline or on the side (`metaPlacement`).
187
+ - `trailing`: optional trailing text/chip/icon/image.
101
188
  - `features`: array of `{ icon?, expr }` rendered below primary/secondary; control with `featuresVisible` and `featuresMode` ('icons+labels' | 'icons-only' | 'labels-only').
102
189
 
103
190
  Expressions use `${...}` to read from `item` (e.g., `${item.name}`). For `currency`, you may pass code/locale as `|:USD` or `|:USD:en-US`.
104
191
 
192
+ ### Rating props
193
+
194
+ ```json
195
+ {
196
+ "templating": {
197
+ "meta": {
198
+ "type": "rating",
199
+ "expr": "${item.rating}",
200
+ "props": { "rating": { "max": 5, "size": 16, "color": "primary" } }
201
+ }
202
+ }
203
+ }
204
+ ```
205
+
206
+ ### Colors
207
+
208
+ `color` accepts:
209
+ - theme colors (`primary`, `accent`, `warn`)
210
+ - M3 tokens (`var(--md-sys-color-*)`)
211
+ - custom colors (hex/rgb). The in-app editor offers a color picker.
212
+
105
213
  ## Actions
106
214
 
107
215
  Configure contextual item actions via `config.actions`:
@@ -115,8 +223,44 @@ actions: [
115
223
  ```
116
224
 
117
225
  - `kind`: 'icon' (default) or 'button'.
118
- - `showIf`: simple equality check is supported (left side must be an `${...}` expression).
119
- - `emitPayload`: choose what the action emits ('item' | 'id' | 'value').
226
+ - `showIf`: simple equality check is supported. Syntax: `"${item.field} == 'value'"`. Left side must be an interpolation expression.
227
+ - `emitPayload`: authoring field in the config/editor; current runtime `actionClick` emission does not change shape based on this field.
228
+
229
+ ### Global actions (command)
230
+
231
+ ```ts
232
+ actions: [
233
+ {
234
+ id: 'favorite',
235
+ icon: 'favorite',
236
+ label: 'Favorite',
237
+ command: 'global:api.post',
238
+ globalPayload: { url: '/api/favorite', body: { id: '${item.id}' } }
239
+ }
240
+ ]
241
+ ```
242
+
243
+ When `command` is set, `actionClick` is **not emitted** by default. Use `emitLocal: true` to emit both.
244
+
245
+ ### Confirmation and loading
246
+
247
+ ```ts
248
+ actions: [
249
+ {
250
+ id: 'delete',
251
+ icon: 'delete',
252
+ label: 'Delete',
253
+ command: 'global:api.patch',
254
+ showLoading: true,
255
+ confirmation: {
256
+ title: 'Confirm deletion',
257
+ message: 'Are you sure you want to delete this item?',
258
+ type: 'danger',
259
+ },
260
+ globalPayload: { url: '/api/items/${item.id}', body: { active: false } },
261
+ }
262
+ ]
263
+ ```
120
264
 
121
265
  ## Selection and Events
122
266
 
@@ -131,6 +275,25 @@ Outputs:
131
275
  - `(actionClick)`: `{ actionId, item, index }`
132
276
  - `(selectionChange)`: `{ mode, value, items, ids? }`
133
277
 
278
+ ## Known limitations and mismatches
279
+
280
+ 1. `layout.virtualScroll` and `layout.stickySectionHeader` exist in the contract/editor, but have no runtime implementation.
281
+ 2. `actions[].emitPayload` is accepted in config/editor, but does not change current `actionClick` payload format.
282
+ 3. `events.*` is declarative-only (no runtime dynamic routing).
283
+ 4. `a11y.highContrast` and `a11y.reduceMotion` are declarative-only at this stage.
284
+ 5. In remote mode, `/filter -> getAll()` fallback can increase network cost on large datasets.
285
+
286
+ ## Source of truth
287
+
288
+ - Canonical contract: `projects/praxis-list/src/lib/praxis-list.json-api.md`
289
+ - Runtime implementation:
290
+ - `projects/praxis-list/src/lib/components/praxis-list.component.ts`
291
+ - `projects/praxis-list/src/lib/components/praxis-list.component.html`
292
+ - `projects/praxis-list/src/lib/services/list-data.service.ts`
293
+ - Runtime specs:
294
+ - `projects/praxis-list/src/lib/components/praxis-list.component.spec.ts`
295
+ - `projects/praxis-list/src/lib/services/list-data.service.spec.ts`
296
+
134
297
  ## License
135
298
 
136
299
  Apache-2.0 — see `LICENSE` in this package or the repository root.