@object-ui/react 16.1.0 → 17.1.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 (38) hide show
  1. package/CHANGELOG.md +639 -1
  2. package/README.md +41 -0
  3. package/dist/SchemaRenderer.js +12 -2
  4. package/dist/context/InlineEditContext.d.ts +21 -0
  5. package/dist/context/InlineEditContext.js +7 -2
  6. package/dist/context/NotificationContext.d.ts +245 -17
  7. package/dist/context/NotificationContext.js +222 -20
  8. package/dist/context/ThemeContext.js +4 -8
  9. package/dist/hooks/index.d.ts +2 -1
  10. package/dist/hooks/index.js +3 -1
  11. package/dist/hooks/useAnimation.d.ts +40 -4
  12. package/dist/hooks/useAnimation.js +41 -10
  13. package/dist/hooks/useCapabilityGate.d.ts +16 -0
  14. package/dist/hooks/useCapabilityGate.js +60 -0
  15. package/dist/hooks/useClientNotifications.d.ts +0 -6
  16. package/dist/hooks/useClientNotifications.js +7 -53
  17. package/dist/hooks/useFilterScope.d.ts +30 -0
  18. package/dist/hooks/useFilterScope.js +55 -0
  19. package/dist/hooks/useNavigationOverlay.d.ts +11 -0
  20. package/dist/hooks/useNavigationOverlay.js +35 -1
  21. package/dist/hooks/usePageVariables.js +23 -11
  22. package/dist/hooks/useRecordSearch.js +98 -4
  23. package/dist/index.d.ts +2 -1
  24. package/dist/index.js +1 -1
  25. package/dist/spec-bridge/SpecBridge.d.ts +0 -4
  26. package/dist/spec-bridge/SpecBridge.js +0 -12
  27. package/dist/spec-bridge/bridges/list-view.js +5 -11
  28. package/dist/spec-bridge/index.d.ts +0 -2
  29. package/dist/spec-bridge/index.js +0 -2
  30. package/dist/utils/error-message.d.ts +31 -0
  31. package/dist/utils/error-message.js +49 -0
  32. package/package.json +7 -7
  33. package/dist/hooks/useColumnSummary.d.ts +0 -38
  34. package/dist/hooks/useColumnSummary.js +0 -54
  35. package/dist/spec-bridge/bridges/dashboard.d.ts +0 -81
  36. package/dist/spec-bridge/bridges/dashboard.js +0 -121
  37. package/dist/spec-bridge/bridges/page.d.ts +0 -58
  38. package/dist/spec-bridge/bridges/page.js +0 -101
@@ -1,38 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
- /** Summary function types aligned with ColumnSummarySchema */
9
- export type SummaryFunction = 'sum' | 'avg' | 'count' | 'min' | 'max' | 'distinct';
10
- export interface ColumnSummaryConfig {
11
- /** The field/column to aggregate */
12
- field: string;
13
- /** The aggregation function */
14
- function: SummaryFunction;
15
- /** Optional label for the summary */
16
- label?: string;
17
- /** Number format options */
18
- format?: Intl.NumberFormatOptions;
19
- }
20
- export interface ColumnSummaryResult {
21
- /** The computed value */
22
- value: number;
23
- /** Formatted display string */
24
- formatted: string;
25
- /** The label */
26
- label: string;
27
- }
28
- /**
29
- * Hook for computing column-level summaries (SUM, AVG, COUNT, MIN, MAX, DISTINCT).
30
- * Implements ColumnSummarySchema from @objectstack/spec v2.0.7.
31
- *
32
- * @example
33
- * ```tsx
34
- * const summary = useColumnSummary(data, { field: 'amount', function: 'sum', label: 'Total' });
35
- * // summary.formatted => "$12,345.67"
36
- * ```
37
- */
38
- export declare function useColumnSummary(data: Record<string, unknown>[], config: ColumnSummaryConfig, locale?: string): ColumnSummaryResult;
@@ -1,54 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
- import { useMemo } from 'react';
9
- /**
10
- * Hook for computing column-level summaries (SUM, AVG, COUNT, MIN, MAX, DISTINCT).
11
- * Implements ColumnSummarySchema from @objectstack/spec v2.0.7.
12
- *
13
- * @example
14
- * ```tsx
15
- * const summary = useColumnSummary(data, { field: 'amount', function: 'sum', label: 'Total' });
16
- * // summary.formatted => "$12,345.67"
17
- * ```
18
- */
19
- export function useColumnSummary(data, config, locale) {
20
- return useMemo(() => {
21
- const values = data
22
- .map((row) => {
23
- const val = row[config.field];
24
- return typeof val === 'number' ? val : Number(val);
25
- })
26
- .filter((v) => !isNaN(v));
27
- let value;
28
- switch (config.function) {
29
- case 'sum':
30
- value = values.reduce((acc, v) => acc + v, 0);
31
- break;
32
- case 'avg':
33
- value = values.length > 0 ? values.reduce((acc, v) => acc + v, 0) / values.length : 0;
34
- break;
35
- case 'count':
36
- value = data.length;
37
- break;
38
- case 'min':
39
- value = values.length > 0 ? Math.min(...values) : 0;
40
- break;
41
- case 'max':
42
- value = values.length > 0 ? Math.max(...values) : 0;
43
- break;
44
- case 'distinct':
45
- value = new Set(data.map((row) => row[config.field])).size;
46
- break;
47
- default:
48
- value = 0;
49
- }
50
- const formatted = new Intl.NumberFormat(locale, config.format).format(value);
51
- const label = config.label ?? config.function.toUpperCase();
52
- return { value, formatted, label };
53
- }, [data, config.field, config.function, config.label, config.format, locale]);
54
- }
@@ -1,81 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
- import type { BridgeFn } from '../types';
9
- interface DashboardWidget {
10
- title?: string;
11
- description?: string;
12
- type?: string;
13
- chartConfig?: any;
14
- colorVariant?: string;
15
- actionUrl?: string;
16
- actionType?: string;
17
- actionIcon?: string;
18
- object?: string;
19
- filter?: any;
20
- categoryField?: string;
21
- valueField?: string;
22
- aggregate?: string;
23
- measures?: any[];
24
- layout?: any;
25
- options?: any;
26
- responsive?: any;
27
- aria?: {
28
- ariaLabel?: string;
29
- ariaDescribedBy?: string;
30
- role?: string;
31
- };
32
- }
33
- interface DashboardHeader {
34
- showTitle?: boolean;
35
- showDescription?: boolean;
36
- actions?: Array<{
37
- label: string;
38
- actionUrl?: string;
39
- actionType?: string;
40
- icon?: string;
41
- }>;
42
- [key: string]: any;
43
- }
44
- interface GlobalFilter {
45
- field: string;
46
- label?: string;
47
- type?: string;
48
- options?: string[];
49
- optionsFrom?: {
50
- object: string;
51
- valueField: string;
52
- labelField?: string;
53
- filter?: any;
54
- };
55
- defaultValue?: any;
56
- scope?: string;
57
- targetWidgets?: string[];
58
- }
59
- interface DashboardSpec {
60
- name?: string;
61
- label?: string;
62
- description?: string;
63
- widgets?: DashboardWidget[];
64
- globalFilters?: GlobalFilter[];
65
- header?: DashboardHeader;
66
- refreshInterval?: number;
67
- dateRange?: {
68
- field?: string;
69
- defaultRange?: string;
70
- allowCustomRange?: boolean;
71
- };
72
- aria?: {
73
- ariaLabel?: string;
74
- ariaDescribedBy?: string;
75
- role?: string;
76
- };
77
- performance?: any;
78
- }
79
- /** Transforms a Dashboard spec into a dashboard layout SchemaNode */
80
- export declare const bridgeDashboard: BridgeFn<DashboardSpec>;
81
- export {};
@@ -1,121 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
- function mapWidget(widget, index) {
9
- const node = {
10
- type: widget.type ?? 'chart',
11
- id: `widget-${index}`,
12
- };
13
- if (widget.title)
14
- node.title = widget.title;
15
- if (widget.description)
16
- node.description = widget.description;
17
- if (widget.chartConfig)
18
- node.chartConfig = widget.chartConfig;
19
- if (widget.colorVariant)
20
- node.colorVariant = widget.colorVariant;
21
- if (widget.actionUrl)
22
- node.actionUrl = widget.actionUrl;
23
- if (widget.actionType)
24
- node.actionType = widget.actionType;
25
- if (widget.actionIcon)
26
- node.actionIcon = widget.actionIcon;
27
- if (widget.object)
28
- node.object = widget.object;
29
- if (widget.filter)
30
- node.filter = widget.filter;
31
- if (widget.categoryField)
32
- node.categoryField = widget.categoryField;
33
- if (widget.valueField)
34
- node.valueField = widget.valueField;
35
- if (widget.aggregate)
36
- node.aggregate = widget.aggregate;
37
- if (widget.measures)
38
- node.measures = widget.measures;
39
- if (widget.layout)
40
- node.layout = widget.layout;
41
- if (widget.options)
42
- node.options = widget.options;
43
- if (widget.responsive)
44
- node.responsive = widget.responsive;
45
- if (widget.aria)
46
- node.aria = widget.aria;
47
- return node;
48
- }
49
- function mapGlobalFilters(filters) {
50
- return {
51
- type: 'filter-bar',
52
- id: 'dashboard-filters',
53
- filters: filters.map((f) => {
54
- const mapped = { field: f.field };
55
- if (f.label)
56
- mapped.label = f.label;
57
- if (f.type)
58
- mapped.type = f.type;
59
- if (f.options)
60
- mapped.options = f.options;
61
- if (f.optionsFrom)
62
- mapped.optionsFrom = f.optionsFrom;
63
- if (f.defaultValue != null)
64
- mapped.defaultValue = f.defaultValue;
65
- if (f.scope)
66
- mapped.scope = f.scope;
67
- if (f.targetWidgets)
68
- mapped.targetWidgets = f.targetWidgets;
69
- return mapped;
70
- }),
71
- };
72
- }
73
- function mapHeader(header) {
74
- const node = {
75
- type: 'dashboard-header',
76
- id: 'dashboard-header',
77
- ...header,
78
- };
79
- return node;
80
- }
81
- /** Transforms a Dashboard spec into a dashboard layout SchemaNode */
82
- export const bridgeDashboard = (spec, _context) => {
83
- const widgetNodes = (spec.widgets ?? []).map(mapWidget);
84
- const bodyChildren = [];
85
- if (spec.header) {
86
- bodyChildren.push(mapHeader(spec.header));
87
- }
88
- if (spec.globalFilters && spec.globalFilters.length > 0) {
89
- bodyChildren.push(mapGlobalFilters(spec.globalFilters));
90
- }
91
- // P1.3 — Date range filter
92
- if (spec.dateRange) {
93
- bodyChildren.push({
94
- type: 'date-range-filter',
95
- id: 'dashboard-date-range',
96
- ...spec.dateRange,
97
- });
98
- }
99
- bodyChildren.push({
100
- type: 'widget-grid',
101
- id: 'dashboard-widgets',
102
- body: widgetNodes,
103
- });
104
- const node = {
105
- type: 'dashboard',
106
- id: spec.name,
107
- body: bodyChildren,
108
- };
109
- if (spec.label)
110
- node.label = spec.label;
111
- if (spec.description)
112
- node.description = spec.description;
113
- if (spec.refreshInterval != null)
114
- node.refreshInterval = spec.refreshInterval;
115
- // P1.6 — i18n & ARIA
116
- if (spec.aria)
117
- node.aria = spec.aria;
118
- if (spec.performance)
119
- node.performance = spec.performance;
120
- return node;
121
- };
@@ -1,58 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
- import type { BridgeFn } from '../types';
9
- interface PageComponent {
10
- type: string;
11
- id?: string;
12
- label?: string;
13
- properties?: Record<string, any>;
14
- events?: Record<string, any>;
15
- style?: Record<string, any>;
16
- responsiveStyles?: Record<string, any>;
17
- className?: string;
18
- /** Canonical conditional-visibility predicate (ADR-0089). */
19
- visibleWhen?: string;
20
- /** @deprecated ADR-0089 → `visibleWhen`. */
21
- visibility?: string;
22
- dataSource?: any;
23
- responsive?: any;
24
- aria?: Record<string, string>;
25
- }
26
- interface PageRegion {
27
- name?: string;
28
- width?: string;
29
- components?: PageComponent[];
30
- }
31
- interface PageVariable {
32
- name: string;
33
- type?: string;
34
- defaultValue?: any;
35
- source?: string;
36
- }
37
- interface PageSpec {
38
- name?: string;
39
- label?: string;
40
- description?: string;
41
- icon?: string;
42
- type?: string;
43
- variables?: PageVariable[];
44
- regions?: PageRegion[];
45
- template?: string;
46
- object?: string;
47
- isDefault?: boolean;
48
- assignedProfiles?: string[];
49
- interfaceConfig?: any;
50
- aria?: {
51
- ariaLabel?: string;
52
- ariaDescribedBy?: string;
53
- role?: string;
54
- };
55
- }
56
- /** Transforms a Page spec into a page layout SchemaNode */
57
- export declare const bridgePage: BridgeFn<PageSpec>;
58
- export {};
@@ -1,101 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
- function mapComponent(component) {
9
- const node = {
10
- type: component.type,
11
- id: component.id,
12
- };
13
- if (component.label)
14
- node.label = component.label;
15
- if (component.className)
16
- node.className = component.className;
17
- if (component.style)
18
- node.style = component.style;
19
- // ADR-0065 scoped per-breakpoint styles — declared on the page-spec
20
- // component (sibling of className/style) but previously dropped here
21
- // before reaching SchemaRenderer, so a layout override like
22
- // `{ large: { display: 'grid', gridTemplateColumns: '...' } }` never
23
- // compiled to CSS and the node fell back to its default layout.
24
- if (component.responsiveStyles)
25
- node.responsiveStyles = component.responsiveStyles;
26
- if (component.properties) {
27
- // Avoid overwriting the component dispatch keys (`type`/`id`) with inner
28
- // renderer-specific props. E.g. PageTabsProps.properties.type is the tab
29
- // visual style ('line'|'card'|'pill'), NOT the component type.
30
- for (const [k, v] of Object.entries(component.properties)) {
31
- if (k === 'type' || k === 'id')
32
- continue;
33
- node[k] = v;
34
- }
35
- // Preserve the original `properties` bag so renderers can still read
36
- // collision-prone keys via `schema.properties.<key>`.
37
- node.properties = component.properties;
38
- }
39
- if (component.events)
40
- node.events = component.events;
41
- // ADR-0089: `visibleWhen` is the canonical conditional-visibility predicate;
42
- // the spec folds the deprecated `visibility` alias into it at parse, so prefer
43
- // it and fall back to `visibility` for raw / un-normalized metadata. SchemaRenderer
44
- // reads `visibleWhen` first (show-when-truthy).
45
- const visiblePredicate = component.visibleWhen ?? component.visibility;
46
- if (visiblePredicate)
47
- node.visibleWhen = visiblePredicate;
48
- if (component.dataSource)
49
- node.dataSource = component.dataSource;
50
- if (component.responsive)
51
- node.responsive = component.responsive;
52
- if (component.aria)
53
- node.aria = component.aria;
54
- return node;
55
- }
56
- function mapRegion(region) {
57
- const children = (region.components ?? []).map(mapComponent);
58
- const node = {
59
- type: 'page-region',
60
- id: region.name,
61
- body: children,
62
- };
63
- if (region.width)
64
- node.width = region.width;
65
- return node;
66
- }
67
- /** Transforms a Page spec into a page layout SchemaNode */
68
- export const bridgePage = (spec, _context) => {
69
- const regions = (spec.regions ?? []).map(mapRegion);
70
- const node = {
71
- type: 'page',
72
- id: spec.name,
73
- body: regions,
74
- };
75
- if (spec.label)
76
- node.label = spec.label;
77
- if (spec.description)
78
- node.description = spec.description;
79
- if (spec.icon)
80
- node.icon = spec.icon;
81
- if (spec.type)
82
- node.pageType = spec.type;
83
- if (spec.variables)
84
- node.variables = spec.variables;
85
- if (spec.template)
86
- node.template = spec.template;
87
- if (spec.object)
88
- node.object = spec.object;
89
- // Additional page properties (blankLayout/recordReview dropped — their page
90
- // types have no renderer and were removed from @objectstack/spec, framework#2265)
91
- if (spec.isDefault != null)
92
- node.isDefault = spec.isDefault;
93
- if (spec.assignedProfiles)
94
- node.assignedProfiles = spec.assignedProfiles;
95
- if (spec.interfaceConfig)
96
- node.interfaceConfig = spec.interfaceConfig;
97
- // P1.6 — i18n & ARIA
98
- if (spec.aria)
99
- node.aria = spec.aria;
100
- return node;
101
- };