@object-ui/plugin-dashboard 17.5.0 → 17.6.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
@@ -16,6 +16,30 @@ Dashboard plugin for Object UI - Create beautiful dashboards with metrics, chart
16
16
  pnpm add @object-ui/plugin-dashboard
17
17
  ```
18
18
 
19
+ ## Requires a bundler — plain Node cannot import this package
20
+
21
+ `DashboardGridLayout` imports `react-grid-layout`'s stylesheet at module scope
22
+ (`import 'react-grid-layout/css/styles.css'`), and Node has no loader for `.css` at all.
23
+ Importing the published entry from plain Node ESM — no bundler, no loader hooks — therefore
24
+ resolves and then fails during evaluation:
25
+
26
+ ```text
27
+ TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".css"
28
+ for .../react-grid-layout/css/styles.css
29
+ ```
30
+
31
+ **This is a supported-configuration statement, not a bug to report.** Unbundled Node
32
+ consumption is not supported for style-carrying plugin packages. It was ruled that way on
33
+ [objectui#5384](https://github.com/objectstack-ai/objectui/issues/5384) — deliberately, over
34
+ the alternative of moving the stylesheet out of module scope — because the grid's layout rules
35
+ are not optional and no unbundled-Node consumer exists to serve.
36
+
37
+ Consume it through a host that handles CSS imports, which every supported host does: Vite,
38
+ webpack, or Next with the package listed in `transpilePackages`. If you have a real need to
39
+ import it under plain Node — SSR with no bundler, a Node-side script — please open an issue.
40
+ That reopens the question as a design decision rather than a defect, and the shape of your
41
+ consumer is the missing input.
42
+
19
43
  ## Usage
20
44
 
21
45
  ### Automatic Registration (Side-Effect Import)
@@ -39,18 +63,62 @@ const schema = {
39
63
  };
40
64
  ```
41
65
 
42
- ### Manual Registration
66
+ ### What the side-effect import registers
67
+
68
+ That single import is the whole of registration — there is no components map to
69
+ iterate over. Importing the entry runs the eight `ComponentRegistry.register(...)`
70
+ calls in `src/index.tsx`, which claim exactly these schema types. The keys below
71
+ are read off those calls:
72
+
73
+ | Namespaced key | Bare-name fallback | Renderer behind it |
74
+ | --- | --- | --- |
75
+ | `view:dashboard` | `dashboard` | `DashboardRenderer` — the widget container |
76
+ | `plugin-dashboard:metric` | `metric` | `MetricWidget` — one KPI value |
77
+ | `plugin-dashboard:metric-card` | `metric-card` | `MetricCard` — KPI with trend and icon |
78
+ | `plugin-dashboard:object-metric` | `object-metric` | internal wrapper around `ObjectMetricWidget` — aggregates over an object |
79
+ | `plugin-dashboard:pivot` | `pivot` | `PivotTable` — pivot over rows you pass in |
80
+ | `plugin-dashboard:object-pivot` | `object-pivot` | internal wrapper around `ObjectPivotTable` — pivot queried from an object |
81
+ | `plugin-dashboard:dashboard-grid` | `dashboard-grid` | `DashboardGridLayout` — the drag/resize editable grid |
82
+ | `plugin-dashboard:object-data-table` | `object-data-table` | `ObjectDataTable` — table queried from an object |
83
+
84
+ `ComponentRegistry.register` publishes `namespace:type`, and — unless the call
85
+ passes `skipFallback: true` — the bare `type` as a back-compat fallback
86
+ (`packages/core/src/registry/Registry.ts:194`, fallback branch at `:226`). No
87
+ call in this package passes `skipFallback`, so each type above resolves under
88
+ both spellings. The two `object-*` types are served by internal wrappers that
89
+ first resolve the spec's per-element `dataSource` binding (through
90
+ `ElementDataSourceGate` from `@object-ui/react`) and then render the exported
91
+ component, which is why those rows name a wrapper rather than an export.
92
+
93
+ ### Registering a component under your own key
94
+
95
+ To serve one of this package's components under a key of your own, register the
96
+ exported component — that is what a manual registration is here:
43
97
 
44
98
  ```typescript
45
- import { dashboardComponents } from '@object-ui/plugin-dashboard';
46
99
  import { ComponentRegistry } from '@object-ui/core';
100
+ import { MetricCard } from '@object-ui/plugin-dashboard';
47
101
 
48
- // Register dashboard components
49
- Object.entries(dashboardComponents).forEach(([type, component]) => {
50
- ComponentRegistry.register(type, component);
102
+ ComponentRegistry.register('my-metric', MetricCard, {
103
+ namespace: 'my-app',
104
+ label: 'My Metric',
105
+ category: 'Dashboard',
51
106
  });
52
107
  ```
53
108
 
109
+ There is also a `dashboardComponents` export: the manual-integration map, keyed
110
+ by the **same eight schema types** as the table above (objectui#5064 re-keyed it
111
+ from component class names). Each key maps to the exact component the import
112
+ registers for that type — for the two `object-*` types that is the internal
113
+ data-source-gate wrapper, not the exported widget. Iterating it with
114
+ `ComponentRegistry.register(type, component)` therefore re-registers the eight
115
+ types the import has already claimed, which is still not the manual registration
116
+ above: each such call passes no `meta`, so it trips the no-namespace deprecation
117
+ warning in `register` (`packages/core/src/registry/Registry.ts:198`) and
118
+ rewrites each bare-name registry entry without its `label`/`category` metadata
119
+ (the `namespace:type` entries are untouched). The side-effect import remains the
120
+ whole of registration.
121
+
54
122
  ## Schema API
55
123
 
56
124
  ### Dashboard
@@ -317,24 +385,71 @@ here.
317
385
 
318
386
  ## TypeScript Support
319
387
 
320
- ```typescript
321
- import type { DashboardSchema, MetricCardSchema } from '@object-ui/plugin-dashboard';
388
+ This package ships **components, not schema types** — its whole type export
389
+ surface is `WidgetConfigPanelProps`, `ConfigPanelTranslate` and the three
390
+ `WidgetDataset*` catalog types, none of which describe an authored dashboard.
391
+ The authored shape is typed by `@object-ui/types`:
322
392
 
323
- const metricCard: MetricCardSchema = {
324
- type: 'metric-card',
393
+ | Import from `@object-ui/types` | What it types |
394
+ | --- | --- |
395
+ | `DashboardComponentSchema` | the whole `type: 'dashboard'` node — `columns`, `gap`, `widgets`, `header`, `globalFilters`, `dateRange`, `refreshInterval`, … |
396
+ | `DashboardWidgetSchema` | one entry of `widgets[]` — the spec's `DashboardWidget` keys, plus objectui's own (`component`, `layout`, `options`, …) |
397
+ | `DashboardWidgetLayout` | a widget's `{ x, y, w, h }` grid box |
398
+
399
+ ```typescript
400
+ import type {
401
+ DashboardComponentSchema,
402
+ DashboardWidgetSchema,
403
+ } from '@object-ui/types';
404
+
405
+ // Dataset-bound KPI — the widget vocabulary (see "Dashboard-level filters").
406
+ const revenue: DashboardWidgetSchema = {
407
+ id: 'kpi_revenue',
408
+ type: 'metric',
325
409
  title: 'Revenue',
326
- value: '$123,456',
327
- trend: 'up',
328
- trendValue: '+12%'
410
+ dataset: 'invoices',
411
+ values: ['count'],
412
+ colorVariant: 'success',
413
+ };
414
+
415
+ // Single-value widget with no query: the number lives under `options`.
416
+ const users: DashboardWidgetSchema = {
417
+ id: 'kpi_users',
418
+ type: 'metric',
419
+ title: 'Total Users',
420
+ options: { value: '1,234' },
421
+ };
422
+
423
+ // Component format: a registered component node in the widget's `component`
424
+ // slot. Its keys are that COMPONENT's props, not widget keys.
425
+ const custom: DashboardWidgetSchema = {
426
+ id: 'kpi_custom',
427
+ component: {
428
+ type: 'metric-card',
429
+ title: 'Revenue',
430
+ value: '$123,456',
431
+ trend: 'up',
432
+ trendValue: '+12%',
433
+ },
434
+ layout: { x: 0, y: 0, w: 3, h: 2 },
329
435
  };
330
436
 
331
- const dashboard: DashboardSchema = {
437
+ const dashboard: DashboardComponentSchema = {
332
438
  type: 'dashboard',
333
439
  columns: 3,
334
- widgets: [metricCard]
440
+ gap: 4,
441
+ widgets: [revenue, users, custom],
335
442
  };
336
443
  ```
337
444
 
445
+ There is **no per-widget-family schema type**: one `DashboardWidgetSchema`
446
+ covers every `type` (`metric`, `bar`, `table`, …) and the family-specific
447
+ settings live under `options`. `MetricCard`'s own props — `value`, `trend`,
448
+ `trendValue` — are the component's, not the widget's: `DashboardWidgetSchema`
449
+ declares none of them, and the component's props interface is not on this
450
+ package's export surface either. So a `metric-card` node is typed only where it
451
+ appears as a component (the `component` slot above), not as a widget family.
452
+
338
453
  ## Customization
339
454
 
340
455
  All components support Tailwind CSS classes:
@@ -390,9 +505,7 @@ auto-detection.
390
505
  }
391
506
  ```
392
507
 
393
- ## DashboardGridLayout — persisting drag / resize edits
394
-
395
- ### DashboardRenderer — design-mode widget reorder
508
+ ## DashboardRenderer — design-mode widget reorder
396
509
 
397
510
  When `DashboardRenderer` is used in design mode (`designMode={true}` plus an
398
511
  `onWidgetsReorder` callback), widgets become sortable via
@@ -417,10 +530,26 @@ through the `onSchemaChange` callback.
417
530
  <DashboardGridLayout
418
531
  schema={dashboard}
419
532
  // ✅ Preferred — write the updated schema through your data adapter.
420
- onSchemaChange={(next) => client.meta.saveItem('dashboard', next.name, next)}
533
+ onSchemaChange={(next) => {
534
+ // `name` is optional on the schema, and `saveItem` requires it — decide
535
+ // what an unnamed dashboard means to your host instead of writing through.
536
+ if (!next.name) return;
537
+ client.meta.saveItem('dashboard', next.name, next);
538
+ }}
421
539
  />
422
540
  ```
423
541
 
542
+ The guard is not defensive noise: the callback receives a
543
+ `DashboardComponentSchema`, whose `name` is optional (`BaseSchema.name` in
544
+ `@object-ui/types`), while `client.meta.saveItem(type, name, item)` declares
545
+ `name: string`. Passing `next.name` straight through is `TS2345` under `strict`
546
+ (`Argument of type 'string | undefined' is not assignable to parameter of type
547
+ 'string'`), so a copied snippet does not compile — and what the server does with
548
+ an absent name has **not** been measured here, which is the other reason this
549
+ example declines to send one rather than guessing. A host that already knows
550
+ which metadata item the grid is editing should pass that name from its own state
551
+ instead of reading it off the node.
552
+
424
553
  If `onSchemaChange` is **not** provided, layout edits stay in component
425
554
  state and are lost on refresh — a `console.warn` is emitted in development
426
555
  to flag the missing wiring. The component never writes to `localStorage`
@@ -1,3 +1,5 @@
1
+ import { ConfigPanelSchema } from '@object-ui/components';
2
+ import { ConfigPanelTranslate } from './useConfigPanelTranslation';
1
3
  /**
2
4
  * ObjectUI
3
5
  * Copyright (c) 2024-present ObjectStack Inc.
@@ -6,6 +8,7 @@
6
8
  * LICENSE file in the root directory of this source tree.
7
9
  */
8
10
  import * as React from 'react';
11
+ export declare function buildDashboardSchema(t: ConfigPanelTranslate): ConfigPanelSchema;
9
12
  export interface DashboardConfigPanelProps {
10
13
  /** Whether the panel is open */
11
14
  open: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"DashboardConfigPanel.d.ts","sourceRoot":"","sources":["../src/DashboardConfigPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAkH/B,MAAM,WAAW,yBAAyB;IACxC,gCAAgC;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,oBAAoB;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,kDAAkD;IAClD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,iCAAiC;IACjC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;IAC9C,oCAAoC;IACpC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;CACrD;AAMD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,IAAI,EACJ,OAAO,EACP,MAAM,EACN,MAAM,EACN,aAAa,GACd,EAAE,yBAAyB,qBAiB3B"}
1
+ {"version":3,"file":"DashboardConfigPanel.d.ts","sourceRoot":"","sources":["../src/DashboardConfigPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,6BAA6B,CAAC;AA2CrC,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,oBAAoB,GAAG,iBAAiB,CA0F/E;AAMD,MAAM,WAAW,yBAAyB;IACxC,gCAAgC;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,oBAAoB;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,kDAAkD;IAClD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,iCAAiC;IACjC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;IAC9C,oCAAoC;IACpC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;CACrD;AAMD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,IAAI,EACJ,OAAO,EACP,MAAM,EACN,MAAM,EACN,aAAa,GACd,EAAE,yBAAyB,qBAoB3B"}
@@ -1 +1 @@
1
- {"version":3,"file":"DashboardFilterBar.d.ts","sourceRoot":"","sources":["../src/DashboardFilterBar.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;GAQG;AAEH,OAAO,KAAuC,MAAM,OAAO,CAAC;AAiB5D,OAAO,EAEL,KAAK,kBAAkB,EAExB,MAAM,iBAAiB,CAAC;AAoCzB,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,kBAAkB,EAAE,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC7C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAkSD,wBAAgB,kBAAkB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,uBAAuB,4BAyCrH"}
1
+ {"version":3,"file":"DashboardFilterBar.d.ts","sourceRoot":"","sources":["../src/DashboardFilterBar.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;GAQG;AAEH,OAAO,KAAuC,MAAM,OAAO,CAAC;AAiB5D,OAAO,EAEL,KAAK,kBAAkB,EAExB,MAAM,iBAAiB,CAAC;AAoCzB,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,kBAAkB,EAAE,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC7C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAgTD,wBAAgB,kBAAkB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,uBAAuB,4BAyCrH"}
@@ -1 +1 @@
1
- {"version":3,"file":"DashboardRenderer.d.ts","sourceRoot":"","sources":["../src/DashboardRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAc,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAGpG,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAUnH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAmI5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,WAAW,sBACf,SAAQ,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,qBAAqB,CAAC;IACnE,MAAM,EAAE,wBAAwB,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;OAUG;IACH,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iCAAiC;IACjC,WAAW,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACrE,kEAAkE;IAClE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gDAAgD;IAChD,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,uDAAuD;IACvD,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAClD;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,qBAAqB,EAAE,KAAK,IAAI,CAAC;IAC9D,mGAAmG;IACnG,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,wGAAwG;IACxG,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAAC,CAAC;IACrH;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAg3BD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,mHAiB7B,CAAC"}
1
+ {"version":3,"file":"DashboardRenderer.d.ts","sourceRoot":"","sources":["../src/DashboardRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAc,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAGpG,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAUnH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAmI5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,WAAW,sBACf,SAAQ,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,qBAAqB,CAAC;IACnE,MAAM,EAAE,wBAAwB,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;OAUG;IACH,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iCAAiC;IACjC,WAAW,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACrE,kEAAkE;IAClE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gDAAgD;IAChD,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,uDAAuD;IACvD,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAClD;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,qBAAqB,EAAE,KAAK,IAAI,CAAC;IAC9D,mGAAmG;IACnG,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,wGAAwG;IACxG,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAAC,CAAC;IACrH;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAq8BD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,mHAiB7B,CAAC"}
@@ -1,4 +1,4 @@
1
- import { buildDatasetDrillFilter, pivotCellKey, ChartSeriesBinding } from '@object-ui/core';
1
+ import { buildDatasetDrillFilter, pivotCellKey } from '@object-ui/core';
2
2
  /**
3
3
  * Build the record-list filter for a drilled row. Re-exported for back-compat;
4
4
  * the implementation now lives in `@object-ui/core` (`buildDatasetDrillFilter`)
@@ -86,126 +86,22 @@ export declare function extractDateWindows(filter: unknown): {
86
86
  rest: Record<string, unknown> | undefined;
87
87
  };
88
88
  /**
89
- * Lower a dashboard widget's declared `chartConfig` (spec `ChartConfigSchema` —
90
- * the same shape a report block and a react `<ObjectChart>` parse) onto the
91
- * chart schema this widget hands to the renderer.
92
- *
93
- * ## Why this is a whitelist and not a spread
94
- *
95
- * Until #3135 NONE of `chartConfig` reached the renderer: this widget read
96
- * `options` and nothing else, so an author who wrote `showLegend: false` still
97
- * got a legend and one who wrote `true` only got one because "on" is the
98
- * renderer's default. #3135 lowered that single flag and left the rest declared
99
- * and inert. objectstack#7016 lowers the rest of the keys that are actually
100
- * DELIVERED, admitting a key only when both of these hold:
101
- *
102
- * 1. **The chart block draws it end to end on this path.** `{ type: 'chart' }`
103
- * resolves to `ChartRenderer` → `AdvancedChartImpl`, which draws
104
- * `title`/`subtitle` in its ChartFrame, turns `description` into the chart
105
- * container's `role="img"` + `aria-label`, applies `height` as that
106
- * container's inline height, reads `colors` as the positional palette,
107
- * prints `showDataLabels` as a Recharts `LabelList`, draws `annotations` as
108
- * ReferenceLine/ReferenceArea and honours `interaction` as the tooltip
109
- * toggle plus `Brush`. Forwarding a key the renderer ignores would only
110
- * move declared-but-not-delivered one layer down, which is the failure this
111
- * change exists to remove.
112
- * 2. **It does not fight the dataset derivation.** `type` stays out: the
113
- * widget's own `type` already picks the family through `CHART_TYPE_MAP`,
114
- * which is the dataset path's chart-family channel.
115
- *
116
- * ## Where `xAxis` / `yAxis` / `series` go — the ruled split (#4229)
117
- *
118
- * Those three used to be refused here under the same criterion 2, on the
119
- * grounds that they are "DERIVED from the dataset selection". That belief was
120
- * **half right, and the half it got wrong silently dropped authored intent**:
121
- * a widget authoring the spec's own combo shape — `series[].type` plus
122
- * `series[].yAxis: 'left'|'right'` and two `yAxis` entries — rendered as
123
- * grouped bars on one axis, because the per-series mark and the axis binding
124
- * never left this function (#4229, measured in the DOM: 2 bars / 0 lines / 1
125
- * axis where 1 bar + 1 line + 2 axes were authored).
126
- *
127
- * The ruling: **the dataset owns DATA, the author owns PRESENTATION.**
128
- *
129
- * - **Data (derived, never forwarded)** — series MEMBERSHIP (which columns
130
- * become series, which rows, which buckets) and the column each binding
131
- * reads. Concretely: `buildChartSeries`'s `dataKey`s, `xAxisKey`, and the
132
- * spec's two binding keys `series[].name` and `ChartAxis.field`.
133
- * - **Presentation (authored, merged forward)** — everything else on those
134
- * same objects: `series[].type` (the per-series mark), `series[].yAxis`
135
- * (which axis it binds to), `label`/`color`/`stack`/`variant`/`dashArray`/
136
- * `opacity`, and the axis definitions' `title`/`format`/`min`/`max`/
137
- * `stepSize`/`showGridLines`/`position`/`logarithmic`.
138
- *
139
- * This is #2880's S2 rule — dual axes are `yAxis[].position` plus
140
- * `series[].yAxis`, and a combo assigns its axes by EXPLICIT binding first,
141
- * falling back to the per-series-type guess only where the author bound
142
- * nothing — extended from `ObjectChart` (where PR #2883 landed it) to the
143
- * dataset path, which never carried it over. {@link mergeAuthoredPresentation}
144
- * is the ONE place that merge happens; see it for the match rule and for why
145
- * membership is safe.
146
- *
147
- * `aria` is the one declared key with **no reader at all** on this path:
148
- * `AdvancedChartImpl` has no `aria` prop, and `SchemaRenderer`'s ARIA injection
149
- * reads the FLAT `ariaLabel`/`ariaDescribedBy`/`role`, never a nested `aria`
150
- * object. It is therefore left unforwarded on purpose (criterion 1) and
151
- * reported back to objectstack#5175's narrowing half rather than papered over
152
- * with a dashboard-only flattening that would also collide with the accessible
153
- * name `description` already sets.
154
- *
155
- * @param raw the widget's `chartConfig` as authored (anything, incl. absent)
156
- * @param fieldCategoryColors per-category colours resolved from the category
157
- * dimension's own select/lookup option colours, merged UNDER an explicit
158
- * author map (see the `colors` note below)
159
- * @returns only the keys that resolved, so the caller can spread it over the
160
- * derived chart schema and every undeclared key keeps the renderer's default
89
+ * The authored chart CHROME and the series/axis presentation merge, both of
90
+ * which now live in `@object-ui/core`'s `chart-presentation` beside
91
+ * `buildChartSeries` — the derivation they are merged onto (objectui#4877).
92
+ *
93
+ * They were written here (#3135 → objectstack#7016 → #4229) and moved when the
94
+ * report renderer's embedded chart turned out to need the SAME merge over the
95
+ * same spec keys: `ReportChartSchema` and `ChartConfigSchema` declare one
96
+ * vocabulary, and a second copy of the split beside this one is precisely the
97
+ * duplication objectui#4389 filed as a defect. The doctrine — the two
98
+ * admission criteria, the data/presentation ruling, why `aria` stays
99
+ * unforwarded — travelled with the code; see that module's header.
100
+ *
101
+ * Re-exported under their original names so this module's public surface is
102
+ * unchanged.
161
103
  */
162
- export declare function chartConfigPresentation(raw: unknown, fieldCategoryColors?: Record<string, string> | null): Record<string, unknown>;
163
- /** Authored spec `ChartSeries` presentation, in the renderer's internal spelling. */
164
- export interface AuthoredSeriesPresentation {
165
- label?: string;
166
- /** Spec `ChartSeries.type`, narrowed — see {@link seriesPresentation}. */
167
- chartType?: 'bar' | 'line' | 'area';
168
- yAxis?: 'left' | 'right';
169
- color?: string;
170
- stack?: string;
171
- variant?: 'primary' | 'comparison';
172
- dashArray?: string;
173
- opacity?: number;
174
- }
175
- /** A derived series binding with the author's presentation merged onto it. */
176
- export type MergedChartSeries = ChartSeriesBinding & AuthoredSeriesPresentation;
177
- /**
178
- * Merge the authored `chartConfig`'s PRESENTATION onto the series and axes the
179
- * dataset selection derived — the one place that happens (#4229).
180
- *
181
- * The match rule is **by name/key**: an authored `series[].name` is paired with
182
- * the derived binding whose `dataKey` it equals, and the pairing decides
183
- * nothing but presentation:
184
- *
185
- * - an authored entry naming a measure that is NOT in the dataset selection is
186
- * **ignored** — membership belongs to the dataset, so an author cannot add,
187
- * remove or re-point a series from `chartConfig`;
188
- * - a derived series with no authored entry keeps the family default, so every
189
- * dashboard that never wrote `chartConfig.series` renders byte-for-byte as
190
- * before;
191
- * - where both exist the **explicit binding wins** (#2880 S2), which is the
192
- * whole point: `type: 'line'` + `yAxis: 'right'` is how the spec says "this
193
- * measure is a line on the secondary axis".
194
- *
195
- * Matching on `name` only is deliberate: `name` is the spec's authorable key
196
- * for a series (`dataKey` is a declared ALIAS of it, resolved where the
197
- * metadata is parsed), so reading a second spelling here would fossilize a
198
- * dialect this renderer has no business accepting (AGENTS.md #0.1).
199
- *
200
- * @param derived the bindings `buildChartSeries` produced from the selection
201
- * @param raw the widget's `chartConfig` as authored (anything, incl. absent)
202
- * @returns the merged series, plus the presentation-only axes to spread onto
203
- * the chart schema (absent when the author declared none)
204
- */
205
- export declare function mergeAuthoredPresentation(derived: ChartSeriesBinding[], raw: unknown): {
206
- series: MergedChartSeries[];
207
- axes: Record<string, unknown>;
208
- };
104
+ export { chartConfigPresentation, mergeAuthoredPresentation, type AuthoredSeriesPresentation, type MergedChartSeries, } from '@object-ui/core';
209
105
  export declare function DatasetWidget({ widget, dataSource }: {
210
106
  widget: any;
211
107
  dataSource: unknown;
@@ -1 +1 @@
1
- {"version":3,"file":"DatasetWidget.d.ts","sourceRoot":"","sources":["../src/DatasetWidget.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DatasetWidget.d.ts","sourceRoot":"","sources":["../src/DatasetWidget.tsx"],"names":[],"mappings":"AAoCA,OAAO,EAYL,uBAAuB,EAUvB,YAAY,EAkBb,MAAM,iBAAiB,CAAC;AAgBzB;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,gCAA0B,CAAC;AAExD;;;;;;;;;;;;;;;GAeG;AACH,QAAA,MAAM,UAAU,mDAAgB,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC;AAEpC;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACpC,OAAO,EAAE,MAAM,EAAE,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,GACd;IACD,UAAU,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACpD,UAAU,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC,CAsBA;AASD,8DAA8D;AAC9D,wBAAgB,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC,GAAG,MAAM,CAEpF;AA6CD,0EAA0E;AAC1E,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B;AAuBD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG;IACnD,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;CAC3C,CA4DA;AA6CD;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EACL,uBAAuB,EACvB,yBAAyB,EACzB,KAAK,0BAA0B,EAC/B,KAAK,iBAAiB,GACvB,MAAM,iBAAiB,CAAC;AAEzB,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE;IAAE,MAAM,EAAE,GAAG,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,+BAsjCzF"}
@@ -30,7 +30,40 @@ interface NormalizedColumn {
30
30
  *
31
31
  * - `string[]` entries are converted to `{ header, accessorKey }` objects,
32
32
  * handling both snake_case and camelCase for header generation.
33
- * - Object entries are returned as-is.
33
+ * - Object entries have their field identity AND their display text RESOLVED
34
+ * here, at the producer, and stamped onto the data-table adapter's own keys
35
+ * (`accessorKey` / `header`). The adapter reads only those two, and no longer
36
+ * falls back to `name` / `label` (objectui#5120, objectui#5351).
37
+ *
38
+ * Object entries used to be returned raw (objectui#5120). `accessorKey` is the
39
+ * table LIBRARY's column key — `column-identity.ts` names it
40
+ * `TABLE_ADAPTER_COLUMN_KEY` and deliberately holds the metadata-identity fold
41
+ * away from it — so a column authored in the spec-canonical spelling
42
+ * (`{ field: 'stage' }`) reached the adapter carrying no `accessorKey` at all
43
+ * and rendered a header over `row[undefined]`: blank cells, no warning. The
44
+ * `$expand` whitelist in `computeLookupExpand` missed it for the same reason,
45
+ * so a `field`-spelled lookup column also lost its related record.
46
+ *
47
+ * Resolving it HERE is the move objectui#5022 made in `RelatedList` and
48
+ * objectui#5068 generalized in `ObjectGrid`: metadata vocabulary in, adapter
49
+ * vocabulary out, one translation in one place. The adapter stays monolingual;
50
+ * the producer owns the translation.
51
+ *
52
+ * Mirror, don't move — the same three rules `RelatedList` states:
53
+ * - an author-supplied `accessorKey` is NEVER overwritten; a deliberate
54
+ * divergence between the table slot and the metadata key belongs to the
55
+ * author;
56
+ * - the authored spelling is left in place, so a host reading `field` / `name`
57
+ * back off these columns keeps working;
58
+ * - an entry with neither a resolvable identity nor any display text is
59
+ * returned UNTOUCHED — nothing is invented for it. It behaves exactly as it
60
+ * does today: a header over empty cells, silently. Whether that silence
61
+ * deserves a dev-time diagnostic is objectui#5349's question, and is
62
+ * deliberately NOT answered here.
63
+ *
64
+ * Returning the INPUT entry by reference when there is nothing to add is load
65
+ * bearing: data-table re-seeds its column state whenever the list is a new
66
+ * object (objectui#4618), and this widget rebuilds its node on every render.
34
67
  */
35
68
  export declare function normalizeColumns(columns: (string | Record<string, any>)[]): NormalizedColumn[];
36
69
  /**
@@ -52,9 +85,41 @@ export declare function normalizeColumns(columns: (string | Record<string, any>)
52
85
  /**
53
86
  * Compute the list of lookup-typed accessors that should be expanded when
54
87
  * fetching rows. Returns column accessors whose object schema field type is
55
- * a relation (lookup/reference/master_detail/user/owner). Used by the
56
- * dashboard table widget to ask the data adapter to populate referenced
88
+ * a relation. Which types those are is NOT restated here: it is
89
+ * {@link EXPANDABLE_FIELD_TYPES}, the family `@object-ui/core` publishes. Used
90
+ * by the dashboard table widget to ask the data adapter to populate referenced
57
91
  * records (e.g. `account: { id, name }`) so cells don't show raw FK ids.
92
+ *
93
+ * THE GATE (objectui#4914, ruling B) runs ahead of the relation test. Measured
94
+ * before the ruling: a `record_owner: { type: 'owner' }` column was ACTIVELY
95
+ * requested for `$expand` — the retired spelling got the full relational read
96
+ * path while the same field's editor answered with a tombstone. It is refused
97
+ * now, loudly and once, and the cell shows the raw id it was always going to
98
+ * show once the spelling stopped being a relation. That the author is TOLD is
99
+ * the whole difference between this and the mechanical deletion the
100
+ * measurement rejected.
101
+ *
102
+ * ## The relation test is core's object, not a private copy (objectui#5692)
103
+ *
104
+ * It used to be the inline literal
105
+ * `t === 'lookup' || t === 'reference' || t === 'master_detail' || t === 'user'`
106
+ * — one of TWO copies this package held (the other `LOOKUP_TYPES` in
107
+ * `recordFields.tsx`), neither deriving from nor pinned against the family core
108
+ * publishes. objectui#5312's claim to have converted "the LAST private copy"
109
+ * was false by these two; they predate that sweep and were outside its file
110
+ * surface.
111
+ *
112
+ * This is the LIVE half of that convergence — `computeLookupExpand` drives a
113
+ * real `$expand` on every dashboard table fetch — so both membership deltas are
114
+ * observable here, and both were decided by measurement (see `isLookupType` in
115
+ * `recordFields.tsx` for the full record):
116
+ *
117
+ * - a `tree` column now GETS `$expand`-ed, the same treatment the form / grid
118
+ * road already gives it;
119
+ * - a `reference` column no longer does, and that is a no-op on spec-compliant
120
+ * data: the spelling is absent from `@objectstack/spec`'s closed `FieldType`
121
+ * and refused by `FieldSchema.safeParse`, so no object schema can declare a
122
+ * field whose stored type is `reference`.
58
123
  */
59
124
  export declare function computeLookupExpand(schema: {
60
125
  columns?: any[];
@@ -1 +1 @@
1
- {"version":3,"file":"ObjectDataTable.d.ts","sourceRoot":"","sources":["../src/ObjectDataTable.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAgE,MAAM,OAAO,CAAC;AAerF,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,YAAY,CAAC,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACrD,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,GAAG,CAAC;QACb,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;QAChB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC;IACF,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,6EAA6E;AAC7E,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,gBAAgB,EAAE,CAS9F;AAED;;;;;;;;;;;;;;;GAeG;AACH;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,EAChD,YAAY,EAAE,GAAG,GAChB,MAAM,EAAE,CAgCV;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA2T1D,CAAC"}
1
+ {"version":3,"file":"ObjectDataTable.d.ts","sourceRoot":"","sources":["../src/ObjectDataTable.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAgE,MAAM,OAAO,CAAC;AA2BrF,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,YAAY,CAAC,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACrD,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,GAAG,CAAC;QACb,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;QAChB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC;IACF,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,6EAA6E;AAC7E,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAyBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,gBAAgB,EAAE,CAkC9F;AAED;;;;;;;;;;;;;;;GAeG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,EAChD,YAAY,EAAE,GAAG,GAChB,MAAM,EAAE,CA+CV;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA+U1D,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { DrillDownConfig } from '@object-ui/types';
2
+ import { DrillDownConfig, I18nLabel } from '@object-ui/types';
3
3
  import { CompareToConfig } from './utils';
4
4
  /**
5
5
  * ObjectMetricWidget — Data-bound metric widget.
@@ -27,31 +27,40 @@ export interface ObjectMetricWidgetProps {
27
27
  };
28
28
  /** Filter conditions */
29
29
  filter?: any;
30
- /** Static label for the metric */
31
- label: string | {
32
- key?: string;
33
- defaultValue?: string;
34
- };
30
+ /**
31
+ * The KPI's heading, in @objectstack/spec's `I18nLabel` vocabulary — a plain
32
+ * string or an inline per-locale map (`{ en: 'Revenue', 'zh-CN': '收入' }`).
33
+ *
34
+ * Was `string | { key?, defaultValue? }` — the key-reference form
35
+ * objectstack#5055 RETIRED at rc.6. The sibling `MetricWidgetProps` was
36
+ * migrated for this reason in objectui#4358; this interface was missed in
37
+ * that pass, and the omission was not inert (objectui#5264). This component
38
+ * forwards `label` straight to `MetricWidget`, which resolves it with
39
+ * `pickLocalized`. The retired object hits no locale limb, so resolution
40
+ * falls through to the last resort — the FIRST string property in insertion
41
+ * order — and `{ key, defaultValue }` written in that natural order paints
42
+ * the raw dotted translation key onto the card as its visible label.
43
+ *
44
+ * The producer side already says so: `ObjectMetricPropsSchema.label` in
45
+ * `@objectstack/spec/ui` is `I18nLabelSchema`, and its inline-map key regex
46
+ * rejects `key`/`defaultValue` by name. This declaration now agrees with it.
47
+ */
48
+ label: string | I18nLabel;
35
49
  /** Fallback static value (used when no dataSource or in demo mode) */
36
50
  fallbackValue?: string | number;
37
51
  /** Trend info */
38
52
  trend?: {
39
53
  value: number;
40
- label?: string | {
41
- key?: string;
42
- defaultValue?: string;
43
- };
54
+ /** Trend caption, same `I18nLabel` vocabulary as {@link ObjectMetricWidgetProps.label}. */
55
+ label?: string | I18nLabel;
44
56
  direction?: 'up' | 'down' | 'neutral';
45
57
  };
46
58
  /** Icon name or ReactNode */
47
59
  icon?: React.ReactNode | string;
48
60
  /** Additional CSS class */
49
61
  className?: string;
50
- /** Description */
51
- description?: string | {
52
- key?: string;
53
- defaultValue?: string;
54
- };
62
+ /** Sub-caption under the value, same `I18nLabel` vocabulary as {@link ObjectMetricWidgetProps.label}. */
63
+ description?: string | I18nLabel;
55
64
  /** External data source (overrides context) */
56
65
  dataSource?: any;
57
66
  /** Visual color variant for the icon container */
@@ -77,11 +86,13 @@ export interface ObjectMetricWidgetProps {
77
86
  * to this metric, filtered by the same `filter` used for aggregation.
78
87
  */
79
88
  drillDown?: DrillDownConfig;
80
- /** Title for the drill-down panel; defaults to the metric label. */
81
- title?: string | {
82
- key?: string;
83
- defaultValue?: string;
84
- };
89
+ /**
90
+ * Title for the drill-down panel; defaults to the metric label. Same
91
+ * `I18nLabel` vocabulary as {@link ObjectMetricWidgetProps.label}, and
92
+ * resolved through the same `pickLocalized` — see `drawerTitle` below, which
93
+ * used to read the retired form's `defaultValue` limb directly.
94
+ */
95
+ title?: string | I18nLabel;
85
96
  /**
86
97
  * Period-over-period comparison configuration — the executor's own
87
98
  * `{ kind, dimension? }` contract since objectstack#5011. When set, the
@@ -1 +1 @@
1
- {"version":3,"file":"ObjectMetricWidget.d.ts","sourceRoot":"","sources":["../src/ObjectMetricWidget.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAgE,MAAM,OAAO,CAAC;AAIrF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAIxD,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,uBAAuB;IACtC,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,SAAS,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClE,wBAAwB;IACxB,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,kCAAkC;IAClC,KAAK,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD,sEAAsE;IACtE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,iBAAiB;IACjB,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,GAAG;YAAE,GAAG,CAAC,EAAE,MAAM,CAAC;YAAC,YAAY,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACzD,SAAS,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC;KACvC,CAAC;IACF,6BAA6B;IAC7B,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC;IAChC,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB;IAClB,WAAW,CAAC,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/D,+CAA+C;IAC/C,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,kDAAkD;IAClD,YAAY,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACpG,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzD;;;;;;;;;;;;;;OAcG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,iEAAiE;IACjE,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC;IAClD,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC3B;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAuVhE,CAAC"}
1
+ {"version":3,"file":"ObjectMetricWidget.d.ts","sourceRoot":"","sources":["../src/ObjectMetricWidget.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAgE,MAAM,OAAO,CAAC;AAIrF,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAInE,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,uBAAuB;IACtC,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,SAAS,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClE,wBAAwB;IACxB,MAAM,CAAC,EAAE,GAAG,CAAC;IACb;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,sEAAsE;IACtE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,iBAAiB;IACjB,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,2FAA2F;QAC3F,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC3B,SAAS,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC;KACvC,CAAC;IACF,6BAA6B;IAC7B,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC;IAChC,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yGAAyG;IACzG,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,+CAA+C;IAC/C,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,kDAAkD;IAClD,YAAY,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACpG,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B;;;;;;;;;;;;;;OAcG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,iEAAiE;IACjE,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC;IAClD,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC3B;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAmWhE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ObjectPivotTable.d.ts","sourceRoot":"","sources":["../src/ObjectPivotTable.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAkD,MAAM,OAAO,CAAC;AAQvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,gBAAgB,GAAG;QACzB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,YAAY,CAAC,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACrD,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,GAAG,CAAC;KACd,CAAC;IACF,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAoO5D,CAAC"}
1
+ {"version":3,"file":"ObjectPivotTable.d.ts","sourceRoot":"","sources":["../src/ObjectPivotTable.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAA0C,MAAM,OAAO,CAAC;AAQ/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAwBzD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,gBAAgB,GAAG;QACzB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,YAAY,CAAC,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACrD,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,GAAG,CAAC;KACd,CAAC;IACF,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAyO5D,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"PivotTable.d.ts","sourceRoot":"","sources":["../src/PivotTable.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,gBAAgB,EAAoB,MAAM,kBAAkB,CAAC;AAE3E,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAWlE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,gFAAgF;IAChF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CAC3C;AAyDD;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAAkD,CAAC;AAwBtG;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAgRhD,CAAC"}
1
+ {"version":3,"file":"PivotTable.d.ts","sourceRoot":"","sources":["../src/PivotTable.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,gBAAgB,EAAoB,MAAM,kBAAkB,CAAC;AAE3E,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAWlE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,gFAAgF;IAChF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CAC3C;AAiFD;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAAkD,CAAC;AAwBtG;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAoRhD,CAAC"}