@object-ui/plugin-dashboard 17.3.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +1445 -0
  2. package/README.md +199 -33
  3. package/dist/DashboardConfigPanel.d.ts +3 -0
  4. package/dist/DashboardConfigPanel.d.ts.map +1 -1
  5. package/dist/DashboardFilterBar.d.ts.map +1 -1
  6. package/dist/DashboardGridLayout.d.ts +27 -0
  7. package/dist/DashboardGridLayout.d.ts.map +1 -1
  8. package/dist/DashboardRenderer.d.ts +46 -4
  9. package/dist/DashboardRenderer.d.ts.map +1 -1
  10. package/dist/DashboardWithConfig.d.ts.map +1 -1
  11. package/dist/DatasetWidget.d.ts +70 -6
  12. package/dist/DatasetWidget.d.ts.map +1 -1
  13. package/dist/MetricCard.d.ts +29 -10
  14. package/dist/MetricCard.d.ts.map +1 -1
  15. package/dist/MetricWidget.d.ts +82 -17
  16. package/dist/MetricWidget.d.ts.map +1 -1
  17. package/dist/ObjectDataTable.d.ts +68 -3
  18. package/dist/ObjectDataTable.d.ts.map +1 -1
  19. package/dist/ObjectMetricWidget.d.ts +41 -27
  20. package/dist/ObjectMetricWidget.d.ts.map +1 -1
  21. package/dist/ObjectPivotTable.d.ts.map +1 -1
  22. package/dist/PivotTable.d.ts.map +1 -1
  23. package/dist/RecordDetailDrawer.d.ts.map +1 -1
  24. package/dist/WidgetConfigPanel.d.ts +28 -0
  25. package/dist/WidgetConfigPanel.d.ts.map +1 -1
  26. package/dist/colorVariants.d.ts +56 -0
  27. package/dist/colorVariants.d.ts.map +1 -0
  28. package/dist/domPassthroughPins.d.ts +9 -0
  29. package/dist/domPassthroughPins.d.ts.map +1 -0
  30. package/dist/index.d.ts +16 -11
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +2087 -1564
  33. package/dist/index.umd.cjs +2 -2
  34. package/dist/legacyRetiredWidget.d.ts +41 -0
  35. package/dist/legacyRetiredWidget.d.ts.map +1 -0
  36. package/dist/recordFields.d.ts +41 -2
  37. package/dist/recordFields.d.ts.map +1 -1
  38. package/dist/schemaHostProps.d.ts +80 -0
  39. package/dist/schemaHostProps.d.ts.map +1 -0
  40. package/dist/useConfigPanelTranslation.d.ts +35 -0
  41. package/dist/useConfigPanelTranslation.d.ts.map +1 -0
  42. package/dist/utils.d.ts +34 -0
  43. package/dist/utils.d.ts.map +1 -1
  44. package/package.json +14 -12
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
@@ -219,21 +287,36 @@ into each bound widget's inline query (`AND`-combined with the widget's own
219
287
  "field": "region", // default binding target
220
288
  "label": "Region",
221
289
  "type": "select", // text | select | date | number | lookup
222
- "options": ["EMEA", "APAC", "AMER"]
290
+ // Canonical @objectstack/spec pair form — the only form the platform
291
+ // accepts at publish. The bare-string shorthand (["EMEA", …]) is
292
+ // deprecated: still lifted at runtime, now warns (objectui#4356).
293
+ "options": [
294
+ { "value": "EMEA", "label": "EMEA" },
295
+ { "value": "APAC", "label": "APAC" },
296
+ { "value": "AMER", "label": "AMER" }
297
+ ]
223
298
  // or dynamic: "optionsFrom": { "object": "accounts", "valueField": "region" }
224
299
  }
225
300
  ],
226
301
  "widgets": [
302
+ // Widgets bind a semantic-layer dataset (ADR-0021) and select its
303
+ // dimensions/measures by name. The pre-ADR-0021 top-level `object` +
304
+ // `categoryField`/`valueField`/`aggregate` shape was REMOVED — a widget
305
+ // still carrying it renders "This widget uses a retired data format.
306
+ // Edit it to bind a dataset." instead of a chart. A renderer-internal
307
+ // query lives under `options.data` as `{ provider: 'object', object,
308
+ // aggregate }`; an `options.data` array is fixed demo data.
309
+ //
227
310
  // Default binding: the filter's own `field` (dateRange → created_at).
228
- { "id": "w1", "type": "bar", "object": "invoices", "aggregate": "count" },
311
+ { "id": "w1", "type": "bar", "dataset": "invoices", "dimensions": ["status"], "values": ["count"] },
229
312
  // Explicit binding: map each filter to THIS widget's own field.
230
313
  {
231
- "id": "w2", "type": "line", "object": "accounts", "aggregate": "count",
314
+ "id": "w2", "type": "line", "dataset": "accounts", "dimensions": ["signed_month"], "values": ["count"],
232
315
  "filterBindings": { "dateRange": "signed_at", "region": "sales_region" }
233
316
  },
234
317
  // Opt out of a filter with `false`.
235
318
  {
236
- "id": "w3", "type": "metric", "object": "invoices", "aggregate": "count",
319
+ "id": "w3", "type": "metric", "dataset": "invoices", "values": ["count"],
237
320
  "filterBindings": { "region": false }
238
321
  }
239
322
  ]
@@ -267,26 +350,106 @@ Notes:
267
350
  warning instead of emitting a query that matches nothing. Explicit
268
351
  `filterBindings` strings are always honoured as written.
269
352
 
270
- ## TypeScript Support
353
+ ## Widget accent colour (`colorVariant`)
354
+
355
+ A KPI widget can declare a semantic accent. The vocabulary is
356
+ `@objectstack/spec`'s `WidgetColorVariantSchema` enum — `default`, `blue`,
357
+ `teal`, `orange`, `purple`, `success`, `warning`, `danger` — the same eight
358
+ tokens the designer's swatch picker offers:
271
359
 
272
360
  ```typescript
273
- import type { DashboardSchema, MetricCardSchema } from '@object-ui/plugin-dashboard';
361
+ {
362
+ id: 'kpi_at_risk',
363
+ type: 'metric',
364
+ title: 'At-Risk Projects',
365
+ dataset: 'project_health',
366
+ values: ['project_count'],
367
+ filter: { health: 'red' },
368
+ colorVariant: 'danger', // tints the value; card chrome stays neutral
369
+ }
370
+ ```
274
371
 
275
- const metricCard: MetricCardSchema = {
276
- type: 'metric-card',
372
+ Where the accent lands depends on the layout, not on the token:
373
+
374
+ | Layout | Accent |
375
+ | --- | --- |
376
+ | Card chrome (`MetricWidget`, inline `object-metric`) | the icon chip's background + foreground |
377
+ | Chrome-less (`MetricWidget variant: 'bare'`, and every dataset-bound `metric`) | the big number's text colour |
378
+
379
+ Both read one shared table (`src/colorVariants.ts`), so the same declaration
380
+ reads the same on either surface. `default` — and omitting the key — means "no
381
+ accent"; the widget renders in the ambient foreground colour. A token outside
382
+ the enum gets no accent and is not aliased to a nearby colour: it is invalid
383
+ metadata, rejected where it is authored and published rather than reinterpreted
384
+ here.
385
+
386
+ ## TypeScript Support
387
+
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`:
392
+
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',
277
409
  title: 'Revenue',
278
- value: '$123,456',
279
- trend: 'up',
280
- 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 },
281
435
  };
282
436
 
283
- const dashboard: DashboardSchema = {
437
+ const dashboard: DashboardComponentSchema = {
284
438
  type: 'dashboard',
285
439
  columns: 3,
286
- widgets: [metricCard]
440
+ gap: 4,
441
+ widgets: [revenue, users, custom],
287
442
  };
288
443
  ```
289
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
+
290
453
  ## Customization
291
454
 
292
455
  All components support Tailwind CSS classes:
@@ -342,9 +505,7 @@ auto-detection.
342
505
  }
343
506
  ```
344
507
 
345
- ## DashboardGridLayout — persisting drag / resize edits
346
-
347
- ### DashboardRenderer — design-mode widget reorder
508
+ ## DashboardRenderer — design-mode widget reorder
348
509
 
349
510
  When `DashboardRenderer` is used in design mode (`designMode={true}` plus an
350
511
  `onWidgetsReorder` callback), widgets become sortable via
@@ -369,10 +530,26 @@ through the `onSchemaChange` callback.
369
530
  <DashboardGridLayout
370
531
  schema={dashboard}
371
532
  // ✅ Preferred — write the updated schema through your data adapter.
372
- 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
+ }}
373
539
  />
374
540
  ```
375
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
+
376
553
  If `onSchemaChange` is **not** provided, layout edits stay in component
377
554
  state and are lost on refresh — a `console.warn` is emitted in development
378
555
  to flag the missing wiring. The component never writes to `localStorage`
@@ -386,17 +563,6 @@ file system, …) per the protocol-agnostic architecture rule.
386
563
  > dashboards. If you still want a browser-local cache for a demo, do it
387
564
  > in the parent inside `onSchemaChange`.
388
565
 
389
- <!-- release-metadata:v3.3.0 -->
390
-
391
- ## Compatibility
392
-
393
- - **React:** 18.x or 19.x
394
- - **Node.js:** ≥ 18
395
- - **TypeScript:** ≥ 5.0 (strict mode)
396
- - **`@objectstack/spec`:** ^3.3.0
397
- - **`@objectstack/client`:** ^3.3.0
398
- - **Tailwind CSS:** ≥ 3.4 (for packages with UI)
399
-
400
566
  ## Links
401
567
 
402
568
  - 📚 [Documentation](https://www.objectui.org/docs/plugins/plugin-dashboard)
@@ -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;AAOzB,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;AA2ND,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"}
@@ -4,6 +4,33 @@ import * as React from 'react';
4
4
  export interface DashboardGridLayoutProps {
5
5
  schema: DashboardComponentSchema;
6
6
  className?: string;
7
+ /**
8
+ * Data-source adapter for the widgets this grid renders, handed to
9
+ * `DatasetWidget` for ADR-0021 dataset-bound widgets (objectui#4614).
10
+ *
11
+ * Typed `unknown`, not `any`. The sibling declares `dataSource?: any`
12
+ * (`DashboardRenderer.tsx:198`) for a reason that is explicitly historical —
13
+ * "that is precisely what it resolved to before", via the index signature that
14
+ * used to answer for it — and this is a NEW declaration with no prior
15
+ * resolution to preserve. `unknown` is what the consumer itself declares
16
+ * (`DatasetWidget.tsx:655`, `dataSource: unknown`), so the value is forwarded
17
+ * to exactly the type that receives it, and no call site is held to anything
18
+ * new: every value is assignable to `unknown`. Narrowing it further to a real
19
+ * adapter type is a separate change with its own consumer sweep, on both
20
+ * surfaces at once.
21
+ *
22
+ * Optional, and the omitted case is a SUPPORTED one rather than an oversight:
23
+ * `dashboard-grid`'s SDUI registration declares only `title` / `className`
24
+ * inputs, so schema-driven hosts render this component with no adapter at all.
25
+ * A dataset-bound widget arriving that way renders `DatasetWidget`'s own
26
+ * no-capability diagnostic — a visible state, never a blank tile.
27
+ *
28
+ * `SchemaRenderer` forwards this as a React prop (its `...props` spread, last:
29
+ * `SchemaRenderer.tsx:632`). It cannot be shadowed by the spec's per-element
30
+ * `dataSource` BINDING, which is stripped from the schema before that spread
31
+ * for exactly this reason (`SchemaRenderer.tsx:564-575`, objectstack#5576).
32
+ */
33
+ dataSource?: unknown;
7
34
  /**
8
35
  * Fires on every drag/resize tick with the raw react-grid-layout payload.
9
36
  * Useful for live previews; NOT a persistence hook.
@@ -1 +1 @@
1
- {"version":3,"file":"DashboardGridLayout.d.ts","sourceRoot":"","sources":["../src/DashboardGridLayout.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAA2C,KAAK,UAAU,IAAI,SAAS,EAAuC,MAAM,mBAAmB,CAAC;AAC/I,OAAO,kCAAkC,CAAC;AAI1C,OAAO,KAAK,EAAE,wBAAwB,EAAyB,MAAM,kBAAkB,CAAC;AA4BxF,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,wBAAwB,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;IAC/C;;;;;;;;;OASG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,wBAAwB,KAAK,IAAI,CAAC;IAC5D,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,iFAAiF;AACjF,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,wBAAwB,EAChC,MAAM,EAAE,SAAS,EAAE,GAClB,wBAAwB,CAa1B;AAcD,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CA6UlE,CAAC"}
1
+ {"version":3,"file":"DashboardGridLayout.d.ts","sourceRoot":"","sources":["../src/DashboardGridLayout.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAA2C,KAAK,UAAU,IAAI,SAAS,EAAuC,MAAM,mBAAmB,CAAC;AAC/I,OAAO,kCAAkC,CAAC;AAK1C,OAAO,KAAK,EAAc,wBAAwB,EAAyB,MAAM,kBAAkB,CAAC;AA8BpG,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,wBAAwB,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;IAC/C;;;;;;;;;OASG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,wBAAwB,KAAK,IAAI,CAAC;IAC5D,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,iFAAiF;AACjF,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,wBAAwB,EAChC,MAAM,EAAE,SAAS,EAAE,GAClB,wBAAwB,CAa1B;AAcD,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CA+blE,CAAC"}
@@ -1,8 +1,51 @@
1
1
  import { DashboardComponentSchema, DashboardWidgetSchema } from '@object-ui/types';
2
- import { ActionDef, ActionResult, ActionContext, ModalHandler } from '@object-ui/core';
3
- export interface DashboardRendererProps {
2
+ import { ActionDef, ActionResult, ActionContext, ModalHandler, SduiDomPassThroughKey } from '@object-ui/core';
3
+ import { HTMLAttributes } from 'react';
4
+ /**
5
+ * The dashboard renderer's props.
6
+ *
7
+ * ## Why there is no `[key: string]: any` here (objectui#4528)
8
+ *
9
+ * There used to be one, and it erased this entire interface. A string index
10
+ * signature puts `string` into `keyof Props`, so `'ref' extends keyof Props` is
11
+ * always true and React's `PropsWithoutRef` takes its `Omit` branch — and
12
+ * `Omit` over a type carrying a string index signature keeps ONLY the index
13
+ * signature. Every declared property above was dropped from the resolved type:
14
+ * `keyof React.ComponentProps< typeof DashboardRenderer >` measured as
15
+ * `string | number`, and `onWidgetClick` measured as `any` at every JSX call
16
+ * site, while this interface went on declaring
17
+ * `(widgetId: string | null) => void`. The declaration was right and no
18
+ * consumer was held to it — a prop typo or a wrong-arity handler type-checked.
19
+ *
20
+ * The same trap, in `packages/components`, is objectui#4422 / PR #4438; this is
21
+ * the sweep of the two packages that issue left unswept.
22
+ *
23
+ * ## How the DOM pass-through survives without it
24
+ *
25
+ * `SchemaRenderer` hands this component the authored node's own keys, so the
26
+ * render function still collects an open rest object — but what may reach the
27
+ * element is decided by `toDomProps`' WHITELIST (objectui#4432), not by this
28
+ * type. The keys that whitelist forwards are therefore declared here BY NAME,
29
+ * derived from the whitelist constant itself so the two cannot drift, which is
30
+ * exactly what `@object-ui/core`'s `dom-props` doctrine asks for: "Deliberate
31
+ * DOM pass-through beyond this set stays available the objectui#4435 way —
32
+ * DECLARE it and forward it by name. Do not reopen the spread."
33
+ */
34
+ export interface DashboardRendererProps extends Pick<HTMLAttributes<HTMLDivElement>, SduiDomPassThroughKey> {
4
35
  schema: DashboardComponentSchema;
5
36
  className?: string;
37
+ /**
38
+ * Data-source adapter for the widgets this dashboard renders.
39
+ *
40
+ * Destructured by the render function and handed to `DatasetWidget` /
41
+ * `SchemaRenderer`, and passed by both in-repo hosts (`DashboardView`,
42
+ * `DashboardPreview`) — but never declared until objectui#4528, because the
43
+ * index signature above was answering for it. Typed `any` deliberately: that
44
+ * is precisely what it resolved to before, so declaring it changes what is
45
+ * DECLARED without changing what any call site is held to. Narrowing it to a
46
+ * real adapter type is a separate change with its own consumer sweep.
47
+ */
48
+ dataSource?: any;
6
49
  /** Callback invoked when dashboard refresh is triggered (manual or auto) */
7
50
  onRefresh?: () => void;
8
51
  /** Total record count to display */
@@ -37,7 +80,6 @@ export interface DashboardRendererProps {
37
80
  * title/subtitle so we don't display them twice.
38
81
  */
39
82
  hideHeaderText?: boolean;
40
- [key: string]: any;
41
83
  }
42
84
  /**
43
85
  * DashboardRenderer — the public dashboard renderer.
@@ -54,5 +96,5 @@ export interface DashboardRendererProps {
54
96
  * stay readable inside widget subtrees, and only a same-named filter shadows
55
97
  * the outer variable.
56
98
  */
57
- export declare const DashboardRenderer: import('react').ForwardRefExoticComponent<Omit<DashboardRendererProps, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
99
+ export declare const DashboardRenderer: import('react').ForwardRefExoticComponent<DashboardRendererProps & import('react').RefAttributes<HTMLDivElement>>;
58
100
  //# sourceMappingURL=DashboardRenderer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DashboardRenderer.d.ts","sourceRoot":"","sources":["../src/DashboardRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAGxF,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAsJ5F,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,wBAAwB,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,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;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAyuBD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,gIAiB7B,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 +1 @@
1
- {"version":3,"file":"DashboardWithConfig.d.ts","sourceRoot":"","sources":["../src/DashboardWithConfig.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,KAAK,EAAE,wBAAwB,EAAyB,MAAM,kBAAkB,CAAC;AAKxF,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAMnE,MAAM,WAAW,wBAAwB;IACvC,qCAAqC;IACrC,MAAM,EAAE,wBAAwB,CAAC;IACjC,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,6DAA6D;IAC7D,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;IACpD,iEAAiE;IACjE,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;IACvE,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,yBAAyB,EAAE,CAAC;IACvC,oDAAoD;IACpD,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,MAAM,EACN,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,WAAW,EACX,iBAAyB,EACzB,SAAS,EACT,QAAQ,EACR,eAAe,GAChB,EAAE,wBAAwB,qBAyJ1B"}
1
+ {"version":3,"file":"DashboardWithConfig.d.ts","sourceRoot":"","sources":["../src/DashboardWithConfig.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,KAAK,EAAE,wBAAwB,EAAyB,MAAM,kBAAkB,CAAC;AAKxF,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAMnE,MAAM,WAAW,wBAAwB;IACvC,qCAAqC;IACrC,MAAM,EAAE,wBAAwB,CAAC;IACjC,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,6DAA6D;IAC7D,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;IACpD,iEAAiE;IACjE,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;IACvE,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,yBAAyB,EAAE,CAAC;IACvC,oDAAoD;IACpD,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,MAAM,EACN,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,WAAW,EACX,iBAAyB,EACzB,SAAS,EACT,QAAQ,EACR,eAAe,GAChB,EAAE,wBAAwB,qBAuK1B"}
@@ -1,4 +1,4 @@
1
- import { buildDatasetDrillFilter, pivotBucketId as pivotRowId, pivotCellKey } 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`)
@@ -10,12 +10,18 @@ export declare const buildDrillFilter: typeof buildDatasetDrillFilter;
10
10
  * live in `@object-ui/core` (`pivotBucketId` / `pivotCellKey`) so this widget
11
11
  * and the report renderer's cross-tab key their buckets identically. See that
12
12
  * module for why both are `JSON.stringify` rather than a delimiter character,
13
- * and for the null-placeholder residual tracked in objectstack#5666.
13
+ * and why an empty value encodes as JSON `null` rather than a placeholder
14
+ * string (objectui#4056).
14
15
  *
15
- * Every consumer of a row id — the cell index below AND the row-total lookup in
16
- * the cross-tab renderer — must build its key with these; a second, hand-rolled
17
- * encoding of the same id is what made the old bug invisible.
16
+ * Every consumer of a bucket id — the cell index below, the row-total lookup
17
+ * AND the column-total lookup in the cross-tab renderer — must build its key
18
+ * with these, over values normalized by `pivotDimensionValue`; a second,
19
+ * hand-rolled encoding of the same id is what made the old bug invisible.
20
+ *
21
+ * `pivotRowId` is the historical name of the axis-neutral encoder, kept as an
22
+ * alias so this package's published surface does not change.
18
23
  */
24
+ declare const pivotRowId: (dimensionValues: Array<string | null>) => string;
19
25
  export { pivotRowId, pivotCellKey };
20
26
  /**
21
27
  * Pivot flat dataset rows into a cross-tab: `rowDims` go DOWN, `colDim` spreads
@@ -24,8 +30,15 @@ export { pivotRowId, pivotCellKey };
24
30
  * holding that combination's measure values. No re-aggregation — the dataset
25
31
  * already grouped by every dimension, so each cell maps to exactly one row (the
26
32
  * index is also what drill-through uses to read `drillRawRows`).
33
+ *
34
+ * `locale` is the display-locale tag the header LABELS are formatted in
35
+ * (objectui#4566) — this is a plain exported function, not a component, so it
36
+ * cannot read `useDisplayLocale()` itself. It affects `rowHeaders`/`colHeaders`
37
+ * only; the `id`s are opaque keys built by `pivotBucketId` from the RAW values
38
+ * and are deliberately untouched by it, so a locale change can never re-key a
39
+ * cell (which would break the `cellIndex` lookup and drill-through with it).
27
40
  */
28
- export declare function buildPivot(rows: Array<Record<string, unknown>>, rowDims: string[], colDim: string): {
41
+ export declare function buildPivot(rows: Array<Record<string, unknown>>, rowDims: string[], colDim: string, locale?: string): {
29
42
  rowHeaders: Array<{
30
43
  id: string;
31
44
  labels: string[];
@@ -38,6 +51,57 @@ export declare function buildPivot(rows: Array<Record<string, unknown>>, rowDims
38
51
  };
39
52
  /** Serialize a 2D array (first row = headers) to CSV text. */
40
53
  export declare function toCsv(rows: Array<Array<string | number | null | undefined>>): string;
54
+ /** A `DatasetSelection.timeDimensions` entry stating a bounded window. */
55
+ export interface DatasetTimeWindow {
56
+ dimension: string;
57
+ dateRange: [string, string];
58
+ }
59
+ /**
60
+ * Split a RESOLVED runtime filter into the bounded date windows it states and
61
+ * the rest of the filter (objectui#3337 point 5).
62
+ *
63
+ * The executor shifts exactly one thing for a `compareTo`: a `timeDimensions`
64
+ * entry carrying a `dateRange`. A widget states its window in its own `filter`
65
+ * instead (a date macro, or the dashboard's date-range filter merged in by
66
+ * `DashboardRenderer`), which is why forwarding a structured `compareTo` alone
67
+ * still came back "compareTo needs a dated window to shift".
68
+ *
69
+ * Windows are **moved, not copied**: the comparison pass re-runs with the
70
+ * shifted `timeDimensions` but the SAME `runtimeFilter`, so a copy left behind
71
+ * would intersect the shifted window with the current one and every
72
+ * `<measure>__compare` column would come back empty.
73
+ *
74
+ * Only CONJUNCTIVE positions are walked — the top level and `$and` members. A
75
+ * window inside `$or` / `$not` is not a window the whole query runs in, so it
76
+ * stays in the filter untouched.
77
+ *
78
+ * **Which dimension gets shifted is not decided here.** Every window found is
79
+ * lowered under the name the author wrote. Zero of them, or two, is the
80
+ * executor's error to raise — it names the candidates (`resolveCompareDimension`).
81
+ * Guessing one renderer-side would trade a loud error for a quietly wrong
82
+ * window, which is the failure class objectstack#5011 set out to end.
83
+ */
84
+ export declare function extractDateWindows(filter: unknown): {
85
+ windows: DatasetTimeWindow[];
86
+ rest: Record<string, unknown> | undefined;
87
+ };
88
+ /**
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.
103
+ */
104
+ export { chartConfigPresentation, mergeAuthoredPresentation, type AuthoredSeriesPresentation, type MergedChartSeries, } from '@object-ui/core';
41
105
  export declare function DatasetWidget({ widget, dataSource }: {
42
106
  widget: any;
43
107
  dataSource: unknown;
@@ -1 +1 @@
1
- {"version":3,"file":"DatasetWidget.d.ts","sourceRoot":"","sources":["../src/DatasetWidget.tsx"],"names":[],"mappings":"AA8BA,OAAO,EAUL,uBAAuB,EAQvB,aAAa,IAAI,UAAU,EAC3B,YAAY,EAGb,MAAM,iBAAiB,CAAC;AAezB;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,gCAA0B,CAAC;AAExD;;;;;;;;;;GAUG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC;AAEpC;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACpC,OAAO,EAAE,MAAM,EAAE,EACjB,MAAM,EAAE,MAAM,GACb;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,CAoBA;AASD,8DAA8D;AAC9D,wBAAgB,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC,GAAG,MAAM,CAEpF;AAmDD,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE;IAAE,MAAM,EAAE,GAAG,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,+BAgezF"}
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"}
@@ -1,17 +1,36 @@
1
1
  import { default as React } from 'react';
2
- export interface MetricCardProps {
3
- title?: string | {
4
- key?: string;
5
- defaultValue?: string;
6
- };
2
+ import { I18nLabel } from '@object-ui/types';
3
+ import { SchemaHostProps } from './schemaHostProps';
4
+ /**
5
+ * DOM PASS-THROUGH (objectui#4426) — see `MetricWidget.tsx`'s interface header
6
+ * for the full argument; this is the same widening on the same spread, onto the
7
+ * same Shadcn `Card` (`div`).
8
+ *
9
+ * `title` is the one key `Omit`-ed, and the omission is the accurate contract
10
+ * rather than a workaround. HTML's `title` is a tooltip string; this card's
11
+ * `title` is its HEADING, in the `I18nLabel` vocabulary — an incompatible type,
12
+ * and one the component destructures out and renders into `CardTitle`, so no
13
+ * `title` attribute has ever reached this element. Declaring the inherited DOM
14
+ * `title` here would be the "declared but not delivered" failure this repo
15
+ * treats as first-class (objectui#3290, objectui#3222): it would type-check,
16
+ * read as a supported tooltip, and silently do nothing. `MetricWidget` has no
17
+ * such collision — its heading is `label` — so it extends the DOM attributes
18
+ * whole. The repo's spelling for this carve-out is `ComboboxProps`
19
+ * (`extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "value" | "onChange">`),
20
+ * omitted there for the same reason: the component's own contract owns the name.
21
+ */
22
+ export interface MetricCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {
23
+ /**
24
+ * Card heading, in @objectstack/spec's `I18nLabel` vocabulary — a plain
25
+ * string or an inline per-locale map. See `MetricWidget.label` for why the
26
+ * retired `{ key, defaultValue }` form is no longer accepted (objectui#4032).
27
+ */
28
+ title?: string | I18nLabel;
7
29
  value: string | number;
8
30
  icon?: string;
9
31
  trend?: 'up' | 'down' | 'neutral';
10
32
  trendValue?: string;
11
- description?: string | {
12
- key?: string;
13
- defaultValue?: string;
14
- };
33
+ description?: string | I18nLabel;
15
34
  className?: string;
16
35
  /** When true, the card is in a loading state (fetching data from server). */
17
36
  loading?: boolean;
@@ -22,5 +41,5 @@ export interface MetricCardProps {
22
41
  * MetricCard - Standalone metric card component for dashboard KPIs
23
42
  * Displays a metric value with optional icon, trend indicator, and description
24
43
  */
25
- export declare const MetricCard: React.FC<MetricCardProps>;
44
+ export declare const MetricCard: React.FC<MetricCardProps & SchemaHostProps>;
26
45
  //# sourceMappingURL=MetricCard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MetricCard.d.ts","sourceRoot":"","sources":["../src/MetricCard.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAY1B,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzD,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,uFAAuF;IACvF,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA+DhD,CAAC"}
1
+ {"version":3,"file":"MetricCard.d.ts","sourceRoot":"","sources":["../src/MetricCard.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAC1F;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,uFAAuF;IACvF,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,GAAG,eAAe,CA6ElE,CAAC"}