@almadar/std 13.3.0 → 13.4.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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "std-stats",
3
- "version": "1.0.0",
4
- "description": "std-stats — embeddable analytics-card atom. Drop into a dashboard\nmolecule alongside std-browse / std-search / std-filter; wire its\nITEMS_LOADED listener to the upstream collection's success emit, then\nconfigure `metrics` per call-site to declare WHICH aggregations to\nshow.\n\nAggregation runs in the lolo state machine (no custom React component\nbeyond stat-display): the ITEMS_LOADED transition uses array/map over\n@config.metrics with a chained `if` to dispatch each metric to the\nright reducer (array/len | array/sum | array/avg | array/min |\narray/max), and the resulting cards array drops into a data-list\nwhose renderItem maps each card to a stat-display pattern. The atom\nowns its own auxiliary entity (StatsItem) for UI state — explicit-\nbinding rule applies: every @entity.X is set explicitly via\n(set @entity.X ...) on each transition.\n\nEach entry in `metrics` is `{ aggregation, field, label, icon,\nformat, variant, max }` where:\n- aggregation count|sum|avg|min|max (default count)\n- field is the numeric entity field for sum/avg/min/max\n- label is the card title (required)\n- icon, format (number|currency|percent), variant\n (default|primary|success|warning|error|info), max are pass-through\n to the stat-display render.",
3
+ "version": "2.0.0",
4
+ "description": "std-stats — embeddable analytics-card atom. Drop into a dashboard\nmolecule alongside std-browse / std-search / std-filter; wire its\nITEMS_LOADED listener to the upstream collection's success emit, then\nconfigure `metrics` per call-site to declare WHICH aggregations to\nshow.\n\nAggregation runs in the lolo state machine (no custom React component\nbeyond stat-display): the ITEMS_LOADED transition uses array/map over\n@config.metrics, applies the per-metric `filter` predicate to\n@payload.data, then dispatches the chosen aggregation kind. Cards\ndrop into a data-list whose renderItem maps each card to a\nstat-display pattern. The atom owns an auxiliary entity (StatsItem)\nfor UI state — explicit-binding rule applies: every @entity.X is set\nexplicitly via (set @entity.X ...) on each transition.\n\nEach entry in `metrics` (all but `label` optional):\n- label string! card title\n- aggregation count|sum|avg|min|max default count what to compute\n- field string numeric entity field for sum/avg/min/max\n- filter SExpression row predicate (e.g. [\"=\", \"@item.status\", \"active\"])\n Drops rows that don't match BEFORE aggregation.\n Omitted = all rows.\n- format number|currency|percent default number value formatting\n- variant default|primary|success|warning|error|info color\n- icon string lucide icon name\n- prefix string prepended to displayed value (e.g. \"≈ \")\n- suffix string appended (e.g. \" /mo\", \" ms\")\n- max number optional denominator. >0 renders \"value / max\".\n- target number optional progress target. >0 renders a progress bar.\n- trend number signed delta vs previous period. >0 ↑ green, <0 ↓ red.\n\nFor dynamic max/target/trend (computed against @payload.data),\nschema authors today must precompute and pass literal numbers; an\nSExpression-evaluating slot is a future extension.",
5
5
  "orbitals": [
6
6
  {
7
7
  "name": "StatsItemOrbital",
@@ -21,18 +21,35 @@
21
21
  "items": {
22
22
  "type": "object",
23
23
  "properties": {
24
- "max": {
25
- "name": "max",
26
- "type": "number"
27
- },
28
- "label": {
29
- "name": "label",
24
+ "suffix": {
25
+ "name": "suffix",
30
26
  "type": "string"
31
27
  },
32
28
  "value": {
33
29
  "name": "value",
34
30
  "type": "number"
35
31
  },
32
+ "icon": {
33
+ "name": "icon",
34
+ "type": "string"
35
+ },
36
+ "format": {
37
+ "name": "format",
38
+ "type": "string",
39
+ "values": [
40
+ "number",
41
+ "currency",
42
+ "percent"
43
+ ]
44
+ },
45
+ "max": {
46
+ "name": "max",
47
+ "type": "number"
48
+ },
49
+ "target": {
50
+ "name": "target",
51
+ "type": "number"
52
+ },
36
53
  "variant": {
37
54
  "name": "variant",
38
55
  "type": "string",
@@ -45,18 +62,17 @@
45
62
  "info"
46
63
  ]
47
64
  },
48
- "icon": {
49
- "name": "icon",
65
+ "prefix": {
66
+ "name": "prefix",
50
67
  "type": "string"
51
68
  },
52
- "format": {
53
- "name": "format",
54
- "type": "string",
55
- "values": [
56
- "number",
57
- "currency",
58
- "percent"
59
- ]
69
+ "trend": {
70
+ "name": "trend",
71
+ "type": "number"
72
+ },
73
+ "label": {
74
+ "name": "label",
75
+ "type": "string"
60
76
  }
61
77
  }
62
78
  }
@@ -110,19 +126,19 @@
110
126
  "render-ui",
111
127
  "main",
112
128
  {
113
- "type": "data-list",
114
- "fields": [],
115
129
  "entity": "@entity.cards",
130
+ "fields": [],
131
+ "type": "data-list",
116
132
  "renderItem": [
117
133
  "fn",
118
134
  "card",
119
135
  {
120
- "label": "@card.label",
121
- "format": "@card.format",
136
+ "max": "@card.max",
137
+ "value": "@card.value",
122
138
  "type": "stat-display",
139
+ "label": "@card.label",
123
140
  "variant": "@card.variant",
124
- "value": "@card.value",
125
- "max": "@card.max",
141
+ "format": "@card.format",
126
142
  "icon": "@card.icon"
127
143
  }
128
144
  ]
@@ -145,17 +161,29 @@
145
161
  "fn",
146
162
  "metric",
147
163
  {
148
- "icon": [
164
+ "format": [
149
165
  "object/get",
150
166
  "@metric",
151
- "icon",
152
- ""
167
+ "format",
168
+ "number"
153
169
  ],
154
- "variant": [
170
+ "max": [
155
171
  "object/get",
156
172
  "@metric",
157
- "variant",
158
- "default"
173
+ "max",
174
+ 0.0
175
+ ],
176
+ "trend": [
177
+ "object/get",
178
+ "@metric",
179
+ "trend",
180
+ 0.0
181
+ ],
182
+ "suffix": [
183
+ "object/get",
184
+ "@metric",
185
+ "suffix",
186
+ ""
159
187
  ],
160
188
  "value": [
161
189
  "if",
@@ -171,7 +199,16 @@
171
199
  ],
172
200
  [
173
201
  "array/sum",
174
- "@payload.data",
202
+ [
203
+ "array/filter",
204
+ "@payload.data",
205
+ [
206
+ "object/get",
207
+ "@metric",
208
+ "filter",
209
+ true
210
+ ]
211
+ ],
175
212
  [
176
213
  "object/get",
177
214
  "@metric",
@@ -193,7 +230,16 @@
193
230
  ],
194
231
  [
195
232
  "array/avg",
196
- "@payload.data",
233
+ [
234
+ "array/filter",
235
+ "@payload.data",
236
+ [
237
+ "object/get",
238
+ "@metric",
239
+ "filter",
240
+ true
241
+ ]
242
+ ],
197
243
  [
198
244
  "object/get",
199
245
  "@metric",
@@ -215,7 +261,16 @@
215
261
  ],
216
262
  [
217
263
  "array/min",
218
- "@payload.data",
264
+ [
265
+ "array/filter",
266
+ "@payload.data",
267
+ [
268
+ "object/get",
269
+ "@metric",
270
+ "filter",
271
+ true
272
+ ]
273
+ ],
219
274
  [
220
275
  "object/get",
221
276
  "@metric",
@@ -237,7 +292,16 @@
237
292
  ],
238
293
  [
239
294
  "array/max",
240
- "@payload.data",
295
+ [
296
+ "array/filter",
297
+ "@payload.data",
298
+ [
299
+ "object/get",
300
+ "@metric",
301
+ "filter",
302
+ true
303
+ ]
304
+ ],
241
305
  [
242
306
  "object/get",
243
307
  "@metric",
@@ -247,28 +311,49 @@
247
311
  ],
248
312
  [
249
313
  "array/len",
250
- "@payload.data"
314
+ [
315
+ "array/filter",
316
+ "@payload.data",
317
+ [
318
+ "object/get",
319
+ "@metric",
320
+ "filter",
321
+ true
322
+ ]
323
+ ]
251
324
  ]
252
325
  ]
253
326
  ]
254
327
  ]
255
328
  ],
256
- "format": [
329
+ "label": [
257
330
  "object/get",
258
331
  "@metric",
259
- "format",
260
- "number"
332
+ "label"
261
333
  ],
262
- "label": [
334
+ "variant": [
263
335
  "object/get",
264
336
  "@metric",
265
- "label"
337
+ "variant",
338
+ "default"
266
339
  ],
267
- "max": [
340
+ "icon": [
268
341
  "object/get",
269
342
  "@metric",
270
- "max",
343
+ "icon",
344
+ ""
345
+ ],
346
+ "target": [
347
+ "object/get",
348
+ "@metric",
349
+ "target",
271
350
  0.0
351
+ ],
352
+ "prefix": [
353
+ "object/get",
354
+ "@metric",
355
+ "prefix",
356
+ ""
272
357
  ]
273
358
  }
274
359
  ]
@@ -278,22 +363,26 @@
278
363
  "render-ui",
279
364
  "main",
280
365
  {
281
- "type": "data-list",
282
- "entity": "@entity.cards",
283
- "fields": [],
284
366
  "renderItem": [
285
367
  "fn",
286
368
  "card",
287
369
  {
370
+ "type": "stat-display",
288
371
  "icon": "@card.icon",
372
+ "max": "@card.max",
373
+ "suffix": "@card.suffix",
374
+ "format": "@card.format",
375
+ "value": "@card.value",
289
376
  "label": "@card.label",
290
377
  "variant": "@card.variant",
291
- "format": "@card.format",
292
- "max": "@card.max",
293
- "type": "stat-display",
294
- "value": "@card.value"
378
+ "prefix": "@card.prefix",
379
+ "target": "@card.target",
380
+ "trend": "@card.trend"
295
381
  }
296
- ]
382
+ ],
383
+ "type": "data-list",
384
+ "entity": "@entity.cards",
385
+ "fields": []
297
386
  }
298
387
  ]
299
388
  ]
@@ -64,39 +64,50 @@
64
64
  "ref": "Stats.traits.StatsItemStats",
65
65
  "name": "DashboardSummary",
66
66
  "config": {
67
- "title": "Summary",
68
67
  "metrics": [
69
68
  {
70
- "variant": "primary",
69
+ "format": "number",
71
70
  "aggregation": "count",
71
+ "label": "Total Items",
72
72
  "icon": "list",
73
- "format": "number",
74
- "label": "Total Items"
73
+ "variant": "primary"
75
74
  },
76
75
  {
77
- "variant": "success",
76
+ "aggregation": "count",
77
+ "filter": [
78
+ "fn",
79
+ "row",
80
+ [
81
+ "=",
82
+ "@row.status",
83
+ "active"
84
+ ]
85
+ ],
78
86
  "icon": "check-circle",
87
+ "variant": "success",
79
88
  "format": "number",
80
- "aggregation": "count",
81
89
  "label": "Active"
82
90
  },
83
91
  {
84
- "format": "currency",
92
+ "label": "Total Revenue",
85
93
  "variant": "info",
86
94
  "aggregation": "sum",
95
+ "format": "currency",
87
96
  "field": "amount",
88
- "icon": "dollar-sign",
89
- "label": "Total Revenue"
97
+ "target": 10000.0,
98
+ "icon": "dollar-sign"
90
99
  },
91
100
  {
92
- "variant": "default",
93
101
  "icon": "trending-up",
94
- "label": "Avg Units",
95
- "field": "units",
102
+ "aggregation": "avg",
103
+ "variant": "default",
96
104
  "format": "number",
97
- "aggregation": "avg"
105
+ "field": "units",
106
+ "label": "Avg Units",
107
+ "suffix": " units"
98
108
  }
99
- ]
109
+ ],
110
+ "title": "Summary"
100
111
  },
101
112
  "listens": [
102
113
  {
@@ -113,13 +124,13 @@
113
124
  "ref": "Graphs.traits.GraphItemGraph",
114
125
  "name": "DashboardCategoryChart",
115
126
  "config": {
116
- "subtitle": "Count across categories",
117
- "chartType": "bar",
118
- "height": 280.0,
119
- "title": "Items by Category",
120
127
  "categoryField": "category",
121
128
  "aggregation": "count",
122
- "showLegend": false
129
+ "height": 280.0,
130
+ "showLegend": false,
131
+ "subtitle": "Count across categories",
132
+ "title": "Items by Category",
133
+ "chartType": "bar"
123
134
  },
124
135
  "listens": [
125
136
  {
@@ -136,12 +147,12 @@
136
147
  "ref": "Graphs.traits.GraphItemGraph",
137
148
  "name": "DashboardStatusChart",
138
149
  "config": {
139
- "showLegend": true,
140
- "categoryField": "status",
141
- "aggregation": "count",
142
150
  "height": 280.0,
151
+ "categoryField": "status",
143
152
  "title": "Status Mix",
144
- "chartType": "donut"
153
+ "showLegend": true,
154
+ "chartType": "donut",
155
+ "aggregation": "count"
145
156
  },
146
157
  "listens": [
147
158
  {
@@ -159,6 +170,8 @@
159
170
  "name": "DashboardItemBrowse",
160
171
  "linkedEntity": "DashboardItem",
161
172
  "config": {
173
+ "displayPageSize": 5.0,
174
+ "pageSize": 100.0,
162
175
  "fields": [
163
176
  {
164
177
  "name": "name",
@@ -166,23 +179,21 @@
166
179
  "variant": "h4"
167
180
  },
168
181
  {
169
- "label": "Category",
170
182
  "name": "category",
183
+ "label": "Category",
171
184
  "variant": "caption"
172
185
  },
173
186
  {
187
+ "variant": "badge",
174
188
  "name": "status",
175
- "label": "Status",
176
- "variant": "badge"
189
+ "label": "Status"
177
190
  },
178
191
  {
179
- "name": "amount",
180
192
  "variant": "caption",
181
- "label": "Amount"
193
+ "label": "Amount",
194
+ "name": "amount"
182
195
  }
183
- ],
184
- "pageSize": 100.0,
185
- "displayPageSize": 5.0
196
+ ]
186
197
  }
187
198
  },
188
199
  {
@@ -263,8 +274,8 @@
263
274
  "DashboardItem",
264
275
  {
265
276
  "emit": {
266
- "success": "DashboardItemLoaded",
267
- "failure": "DashboardItemLoadFailed"
277
+ "failure": "DashboardItemLoadFailed",
278
+ "success": "DashboardItemLoaded"
268
279
  }
269
280
  }
270
281
  ],
@@ -273,14 +284,13 @@
273
284
  "main",
274
285
  {
275
286
  "type": "stack",
276
- "gap": "lg",
287
+ "className": "max-w-6xl mx-auto w-full p-4",
277
288
  "children": [
278
289
  {
279
- "type": "stack",
280
290
  "children": [
281
291
  {
282
- "type": "icon",
283
- "name": "bar-chart-2"
292
+ "name": "bar-chart-2",
293
+ "type": "icon"
284
294
  },
285
295
  {
286
296
  "type": "typography",
@@ -288,34 +298,35 @@
288
298
  "content": "Dashboard"
289
299
  }
290
300
  ],
291
- "align": "center",
301
+ "direction": "horizontal",
302
+ "type": "stack",
292
303
  "gap": "sm",
293
- "direction": "horizontal"
304
+ "align": "center"
294
305
  },
295
306
  {
296
307
  "type": "divider"
297
308
  },
298
309
  "@trait.DashboardSummary",
299
310
  {
311
+ "type": "simple-grid",
300
312
  "children": [
301
313
  "@trait.DashboardCategoryChart",
302
314
  "@trait.DashboardStatusChart"
303
315
  ],
304
- "gap": "md",
305
316
  "cols": 2.0,
306
- "type": "simple-grid"
317
+ "gap": "md"
307
318
  },
308
319
  {
309
320
  "type": "divider"
310
321
  },
311
322
  {
312
- "content": "Recent Items",
323
+ "variant": "h3",
313
324
  "type": "typography",
314
- "variant": "h3"
325
+ "content": "Recent Items"
315
326
  },
316
327
  "@trait.DashboardItemBrowse"
317
328
  ],
318
- "className": "max-w-6xl mx-auto w-full p-4",
329
+ "gap": "lg",
319
330
  "direction": "vertical"
320
331
  }
321
332
  ]
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "std-stats",
3
- "version": "1.0.0",
4
- "description": "std-stats — embeddable analytics-card atom. Drop into a dashboard\nmolecule alongside std-browse / std-search / std-filter; wire its\nITEMS_LOADED listener to the upstream collection's success emit, then\nconfigure `metrics` per call-site to declare WHICH aggregations to\nshow.\n\nAggregation runs in the lolo state machine (no custom React component\nbeyond stat-display): the ITEMS_LOADED transition uses array/map over\n@config.metrics with a chained `if` to dispatch each metric to the\nright reducer (array/len | array/sum | array/avg | array/min |\narray/max), and the resulting cards array drops into a data-list\nwhose renderItem maps each card to a stat-display pattern. The atom\nowns its own auxiliary entity (StatsItem) for UI state — explicit-\nbinding rule applies: every @entity.X is set explicitly via\n(set @entity.X ...) on each transition.\n\nEach entry in `metrics` is `{ aggregation, field, label, icon,\nformat, variant, max }` where:\n- aggregation count|sum|avg|min|max (default count)\n- field is the numeric entity field for sum/avg/min/max\n- label is the card title (required)\n- icon, format (number|currency|percent), variant\n (default|primary|success|warning|error|info), max are pass-through\n to the stat-display render.",
3
+ "version": "2.0.0",
4
+ "description": "std-stats — embeddable analytics-card atom. Drop into a dashboard\nmolecule alongside std-browse / std-search / std-filter; wire its\nITEMS_LOADED listener to the upstream collection's success emit, then\nconfigure `metrics` per call-site to declare WHICH aggregations to\nshow.\n\nAggregation runs in the lolo state machine (no custom React component\nbeyond stat-display): the ITEMS_LOADED transition uses array/map over\n@config.metrics, applies the per-metric `filter` predicate to\n@payload.data, then dispatches the chosen aggregation kind. Cards\ndrop into a data-list whose renderItem maps each card to a\nstat-display pattern. The atom owns an auxiliary entity (StatsItem)\nfor UI state — explicit-binding rule applies: every @entity.X is set\nexplicitly via (set @entity.X ...) on each transition.\n\nEach entry in `metrics` (all but `label` optional):\n- label string! card title\n- aggregation count|sum|avg|min|max default count what to compute\n- field string numeric entity field for sum/avg/min/max\n- filter SExpression row predicate (e.g. [\"=\", \"@item.status\", \"active\"])\n Drops rows that don't match BEFORE aggregation.\n Omitted = all rows.\n- format number|currency|percent default number value formatting\n- variant default|primary|success|warning|error|info color\n- icon string lucide icon name\n- prefix string prepended to displayed value (e.g. \"≈ \")\n- suffix string appended (e.g. \" /mo\", \" ms\")\n- max number optional denominator. >0 renders \"value / max\".\n- target number optional progress target. >0 renders a progress bar.\n- trend number signed delta vs previous period. >0 ↑ green, <0 ↓ red.\n\nFor dynamic max/target/trend (computed against @payload.data),\nschema authors today must precompute and pass literal numbers; an\nSExpression-evaluating slot is a future extension.",
5
5
  "orbitals": [
6
6
  {
7
7
  "name": "StatsItemOrbital",
@@ -21,18 +21,35 @@
21
21
  "items": {
22
22
  "type": "object",
23
23
  "properties": {
24
- "max": {
25
- "name": "max",
26
- "type": "number"
27
- },
28
- "label": {
29
- "name": "label",
24
+ "suffix": {
25
+ "name": "suffix",
30
26
  "type": "string"
31
27
  },
32
28
  "value": {
33
29
  "name": "value",
34
30
  "type": "number"
35
31
  },
32
+ "icon": {
33
+ "name": "icon",
34
+ "type": "string"
35
+ },
36
+ "format": {
37
+ "name": "format",
38
+ "type": "string",
39
+ "values": [
40
+ "number",
41
+ "currency",
42
+ "percent"
43
+ ]
44
+ },
45
+ "max": {
46
+ "name": "max",
47
+ "type": "number"
48
+ },
49
+ "target": {
50
+ "name": "target",
51
+ "type": "number"
52
+ },
36
53
  "variant": {
37
54
  "name": "variant",
38
55
  "type": "string",
@@ -45,18 +62,17 @@
45
62
  "info"
46
63
  ]
47
64
  },
48
- "icon": {
49
- "name": "icon",
65
+ "prefix": {
66
+ "name": "prefix",
50
67
  "type": "string"
51
68
  },
52
- "format": {
53
- "name": "format",
54
- "type": "string",
55
- "values": [
56
- "number",
57
- "currency",
58
- "percent"
59
- ]
69
+ "trend": {
70
+ "name": "trend",
71
+ "type": "number"
72
+ },
73
+ "label": {
74
+ "name": "label",
75
+ "type": "string"
60
76
  }
61
77
  }
62
78
  }
@@ -110,19 +126,19 @@
110
126
  "render-ui",
111
127
  "main",
112
128
  {
113
- "type": "data-list",
114
- "fields": [],
115
129
  "entity": "@entity.cards",
130
+ "fields": [],
131
+ "type": "data-list",
116
132
  "renderItem": [
117
133
  "fn",
118
134
  "card",
119
135
  {
120
- "label": "@card.label",
121
- "format": "@card.format",
136
+ "max": "@card.max",
137
+ "value": "@card.value",
122
138
  "type": "stat-display",
139
+ "label": "@card.label",
123
140
  "variant": "@card.variant",
124
- "value": "@card.value",
125
- "max": "@card.max",
141
+ "format": "@card.format",
126
142
  "icon": "@card.icon"
127
143
  }
128
144
  ]
@@ -145,17 +161,29 @@
145
161
  "fn",
146
162
  "metric",
147
163
  {
148
- "icon": [
164
+ "format": [
149
165
  "object/get",
150
166
  "@metric",
151
- "icon",
152
- ""
167
+ "format",
168
+ "number"
153
169
  ],
154
- "variant": [
170
+ "max": [
155
171
  "object/get",
156
172
  "@metric",
157
- "variant",
158
- "default"
173
+ "max",
174
+ 0.0
175
+ ],
176
+ "trend": [
177
+ "object/get",
178
+ "@metric",
179
+ "trend",
180
+ 0.0
181
+ ],
182
+ "suffix": [
183
+ "object/get",
184
+ "@metric",
185
+ "suffix",
186
+ ""
159
187
  ],
160
188
  "value": [
161
189
  "if",
@@ -171,7 +199,16 @@
171
199
  ],
172
200
  [
173
201
  "array/sum",
174
- "@payload.data",
202
+ [
203
+ "array/filter",
204
+ "@payload.data",
205
+ [
206
+ "object/get",
207
+ "@metric",
208
+ "filter",
209
+ true
210
+ ]
211
+ ],
175
212
  [
176
213
  "object/get",
177
214
  "@metric",
@@ -193,7 +230,16 @@
193
230
  ],
194
231
  [
195
232
  "array/avg",
196
- "@payload.data",
233
+ [
234
+ "array/filter",
235
+ "@payload.data",
236
+ [
237
+ "object/get",
238
+ "@metric",
239
+ "filter",
240
+ true
241
+ ]
242
+ ],
197
243
  [
198
244
  "object/get",
199
245
  "@metric",
@@ -215,7 +261,16 @@
215
261
  ],
216
262
  [
217
263
  "array/min",
218
- "@payload.data",
264
+ [
265
+ "array/filter",
266
+ "@payload.data",
267
+ [
268
+ "object/get",
269
+ "@metric",
270
+ "filter",
271
+ true
272
+ ]
273
+ ],
219
274
  [
220
275
  "object/get",
221
276
  "@metric",
@@ -237,7 +292,16 @@
237
292
  ],
238
293
  [
239
294
  "array/max",
240
- "@payload.data",
295
+ [
296
+ "array/filter",
297
+ "@payload.data",
298
+ [
299
+ "object/get",
300
+ "@metric",
301
+ "filter",
302
+ true
303
+ ]
304
+ ],
241
305
  [
242
306
  "object/get",
243
307
  "@metric",
@@ -247,28 +311,49 @@
247
311
  ],
248
312
  [
249
313
  "array/len",
250
- "@payload.data"
314
+ [
315
+ "array/filter",
316
+ "@payload.data",
317
+ [
318
+ "object/get",
319
+ "@metric",
320
+ "filter",
321
+ true
322
+ ]
323
+ ]
251
324
  ]
252
325
  ]
253
326
  ]
254
327
  ]
255
328
  ],
256
- "format": [
329
+ "label": [
257
330
  "object/get",
258
331
  "@metric",
259
- "format",
260
- "number"
332
+ "label"
261
333
  ],
262
- "label": [
334
+ "variant": [
263
335
  "object/get",
264
336
  "@metric",
265
- "label"
337
+ "variant",
338
+ "default"
266
339
  ],
267
- "max": [
340
+ "icon": [
268
341
  "object/get",
269
342
  "@metric",
270
- "max",
343
+ "icon",
344
+ ""
345
+ ],
346
+ "target": [
347
+ "object/get",
348
+ "@metric",
349
+ "target",
271
350
  0.0
351
+ ],
352
+ "prefix": [
353
+ "object/get",
354
+ "@metric",
355
+ "prefix",
356
+ ""
272
357
  ]
273
358
  }
274
359
  ]
@@ -278,22 +363,26 @@
278
363
  "render-ui",
279
364
  "main",
280
365
  {
281
- "type": "data-list",
282
- "entity": "@entity.cards",
283
- "fields": [],
284
366
  "renderItem": [
285
367
  "fn",
286
368
  "card",
287
369
  {
370
+ "type": "stat-display",
288
371
  "icon": "@card.icon",
372
+ "max": "@card.max",
373
+ "suffix": "@card.suffix",
374
+ "format": "@card.format",
375
+ "value": "@card.value",
289
376
  "label": "@card.label",
290
377
  "variant": "@card.variant",
291
- "format": "@card.format",
292
- "max": "@card.max",
293
- "type": "stat-display",
294
- "value": "@card.value"
378
+ "prefix": "@card.prefix",
379
+ "target": "@card.target",
380
+ "trend": "@card.trend"
295
381
  }
296
- ]
382
+ ],
383
+ "type": "data-list",
384
+ "entity": "@entity.cards",
385
+ "fields": []
297
386
  }
298
387
  ]
299
388
  ]
@@ -64,39 +64,50 @@
64
64
  "ref": "Stats.traits.StatsItemStats",
65
65
  "name": "DashboardSummary",
66
66
  "config": {
67
- "title": "Summary",
68
67
  "metrics": [
69
68
  {
70
- "variant": "primary",
69
+ "format": "number",
71
70
  "aggregation": "count",
71
+ "label": "Total Items",
72
72
  "icon": "list",
73
- "format": "number",
74
- "label": "Total Items"
73
+ "variant": "primary"
75
74
  },
76
75
  {
77
- "variant": "success",
76
+ "aggregation": "count",
77
+ "filter": [
78
+ "fn",
79
+ "row",
80
+ [
81
+ "=",
82
+ "@row.status",
83
+ "active"
84
+ ]
85
+ ],
78
86
  "icon": "check-circle",
87
+ "variant": "success",
79
88
  "format": "number",
80
- "aggregation": "count",
81
89
  "label": "Active"
82
90
  },
83
91
  {
84
- "format": "currency",
92
+ "label": "Total Revenue",
85
93
  "variant": "info",
86
94
  "aggregation": "sum",
95
+ "format": "currency",
87
96
  "field": "amount",
88
- "icon": "dollar-sign",
89
- "label": "Total Revenue"
97
+ "target": 10000.0,
98
+ "icon": "dollar-sign"
90
99
  },
91
100
  {
92
- "variant": "default",
93
101
  "icon": "trending-up",
94
- "label": "Avg Units",
95
- "field": "units",
102
+ "aggregation": "avg",
103
+ "variant": "default",
96
104
  "format": "number",
97
- "aggregation": "avg"
105
+ "field": "units",
106
+ "label": "Avg Units",
107
+ "suffix": " units"
98
108
  }
99
- ]
109
+ ],
110
+ "title": "Summary"
100
111
  },
101
112
  "listens": [
102
113
  {
@@ -113,13 +124,13 @@
113
124
  "ref": "Graphs.traits.GraphItemGraph",
114
125
  "name": "DashboardCategoryChart",
115
126
  "config": {
116
- "subtitle": "Count across categories",
117
- "chartType": "bar",
118
- "height": 280.0,
119
- "title": "Items by Category",
120
127
  "categoryField": "category",
121
128
  "aggregation": "count",
122
- "showLegend": false
129
+ "height": 280.0,
130
+ "showLegend": false,
131
+ "subtitle": "Count across categories",
132
+ "title": "Items by Category",
133
+ "chartType": "bar"
123
134
  },
124
135
  "listens": [
125
136
  {
@@ -136,12 +147,12 @@
136
147
  "ref": "Graphs.traits.GraphItemGraph",
137
148
  "name": "DashboardStatusChart",
138
149
  "config": {
139
- "showLegend": true,
140
- "categoryField": "status",
141
- "aggregation": "count",
142
150
  "height": 280.0,
151
+ "categoryField": "status",
143
152
  "title": "Status Mix",
144
- "chartType": "donut"
153
+ "showLegend": true,
154
+ "chartType": "donut",
155
+ "aggregation": "count"
145
156
  },
146
157
  "listens": [
147
158
  {
@@ -159,6 +170,8 @@
159
170
  "name": "DashboardItemBrowse",
160
171
  "linkedEntity": "DashboardItem",
161
172
  "config": {
173
+ "displayPageSize": 5.0,
174
+ "pageSize": 100.0,
162
175
  "fields": [
163
176
  {
164
177
  "name": "name",
@@ -166,23 +179,21 @@
166
179
  "variant": "h4"
167
180
  },
168
181
  {
169
- "label": "Category",
170
182
  "name": "category",
183
+ "label": "Category",
171
184
  "variant": "caption"
172
185
  },
173
186
  {
187
+ "variant": "badge",
174
188
  "name": "status",
175
- "label": "Status",
176
- "variant": "badge"
189
+ "label": "Status"
177
190
  },
178
191
  {
179
- "name": "amount",
180
192
  "variant": "caption",
181
- "label": "Amount"
193
+ "label": "Amount",
194
+ "name": "amount"
182
195
  }
183
- ],
184
- "pageSize": 100.0,
185
- "displayPageSize": 5.0
196
+ ]
186
197
  }
187
198
  },
188
199
  {
@@ -263,8 +274,8 @@
263
274
  "DashboardItem",
264
275
  {
265
276
  "emit": {
266
- "success": "DashboardItemLoaded",
267
- "failure": "DashboardItemLoadFailed"
277
+ "failure": "DashboardItemLoadFailed",
278
+ "success": "DashboardItemLoaded"
268
279
  }
269
280
  }
270
281
  ],
@@ -273,14 +284,13 @@
273
284
  "main",
274
285
  {
275
286
  "type": "stack",
276
- "gap": "lg",
287
+ "className": "max-w-6xl mx-auto w-full p-4",
277
288
  "children": [
278
289
  {
279
- "type": "stack",
280
290
  "children": [
281
291
  {
282
- "type": "icon",
283
- "name": "bar-chart-2"
292
+ "name": "bar-chart-2",
293
+ "type": "icon"
284
294
  },
285
295
  {
286
296
  "type": "typography",
@@ -288,34 +298,35 @@
288
298
  "content": "Dashboard"
289
299
  }
290
300
  ],
291
- "align": "center",
301
+ "direction": "horizontal",
302
+ "type": "stack",
292
303
  "gap": "sm",
293
- "direction": "horizontal"
304
+ "align": "center"
294
305
  },
295
306
  {
296
307
  "type": "divider"
297
308
  },
298
309
  "@trait.DashboardSummary",
299
310
  {
311
+ "type": "simple-grid",
300
312
  "children": [
301
313
  "@trait.DashboardCategoryChart",
302
314
  "@trait.DashboardStatusChart"
303
315
  ],
304
- "gap": "md",
305
316
  "cols": 2.0,
306
- "type": "simple-grid"
317
+ "gap": "md"
307
318
  },
308
319
  {
309
320
  "type": "divider"
310
321
  },
311
322
  {
312
- "content": "Recent Items",
323
+ "variant": "h3",
313
324
  "type": "typography",
314
- "variant": "h3"
325
+ "content": "Recent Items"
315
326
  },
316
327
  "@trait.DashboardItemBrowse"
317
328
  ],
318
- "className": "max-w-6xl mx-auto w-full p-4",
329
+ "gap": "lg",
319
330
  "direction": "vertical"
320
331
  }
321
332
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/std",
3
- "version": "13.3.0",
3
+ "version": "13.4.0",
4
4
  "description": "Standard library operators for Almadar (math, string, array, etc.)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",