@object-ui/react 16.1.0 → 17.2.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 (45) hide show
  1. package/CHANGELOG.md +790 -1
  2. package/README.md +41 -0
  3. package/dist/SchemaRenderer.js +12 -2
  4. package/dist/context/AppShellContext.js +51 -23
  5. package/dist/context/InlineEditContext.d.ts +64 -0
  6. package/dist/context/InlineEditContext.js +8 -2
  7. package/dist/context/NotificationContext.d.ts +245 -17
  8. package/dist/context/NotificationContext.js +222 -20
  9. package/dist/context/ThemeContext.js +4 -8
  10. package/dist/hooks/index.d.ts +2 -1
  11. package/dist/hooks/index.js +3 -1
  12. package/dist/hooks/useAnimation.d.ts +40 -4
  13. package/dist/hooks/useAnimation.js +41 -10
  14. package/dist/hooks/useCapabilityGate.d.ts +16 -0
  15. package/dist/hooks/useCapabilityGate.js +60 -0
  16. package/dist/hooks/useClientNotifications.d.ts +0 -6
  17. package/dist/hooks/useClientNotifications.js +7 -53
  18. package/dist/hooks/useFilterScope.d.ts +30 -0
  19. package/dist/hooks/useFilterScope.js +55 -0
  20. package/dist/hooks/useNavigationOverlay.d.ts +34 -10
  21. package/dist/hooks/useNavigationOverlay.js +35 -1
  22. package/dist/hooks/useOffline.d.ts +51 -33
  23. package/dist/hooks/useOffline.js +3 -3
  24. package/dist/hooks/usePageVariables.js +23 -11
  25. package/dist/hooks/usePerformance.d.ts +3 -3
  26. package/dist/hooks/usePerformance.js +2 -2
  27. package/dist/hooks/useRecordSearch.js +98 -4
  28. package/dist/index.d.ts +2 -1
  29. package/dist/index.js +1 -1
  30. package/dist/spec-bridge/SpecBridge.d.ts +0 -4
  31. package/dist/spec-bridge/SpecBridge.js +0 -12
  32. package/dist/spec-bridge/bridges/list-view.js +5 -11
  33. package/dist/spec-bridge/index.d.ts +0 -2
  34. package/dist/spec-bridge/index.js +0 -2
  35. package/dist/spec-input.d.ts +37 -0
  36. package/dist/spec-input.js +8 -0
  37. package/dist/utils/error-message.d.ts +31 -0
  38. package/dist/utils/error-message.js +49 -0
  39. package/package.json +8 -8
  40. package/dist/hooks/useColumnSummary.d.ts +0 -38
  41. package/dist/hooks/useColumnSummary.js +0 -54
  42. package/dist/spec-bridge/bridges/dashboard.d.ts +0 -81
  43. package/dist/spec-bridge/bridges/dashboard.js +0 -121
  44. package/dist/spec-bridge/bridges/page.d.ts +0 -58
  45. package/dist/spec-bridge/bridges/page.js +0 -101
@@ -7,8 +7,6 @@
7
7
  */
8
8
  import { bridgeListView } from './bridges/list-view';
9
9
  import { bridgeFormView } from './bridges/form-view';
10
- import { bridgePage } from './bridges/page';
11
- import { bridgeDashboard } from './bridges/dashboard';
12
10
  export class SpecBridge {
13
11
  constructor(context = {}) {
14
12
  Object.defineProperty(this, "bridges", {
@@ -26,8 +24,6 @@ export class SpecBridge {
26
24
  this.context = context;
27
25
  this.register('list', bridgeListView);
28
26
  this.register('form', bridgeFormView);
29
- this.register('page', bridgePage);
30
- this.register('dashboard', bridgeDashboard);
31
27
  }
32
28
  register(specType, bridge) {
33
29
  this.bridges.set(specType, bridge);
@@ -48,14 +44,6 @@ export class SpecBridge {
48
44
  transformFormView(spec) {
49
45
  return this.transform('form', spec);
50
46
  }
51
- /** Transform a Page spec */
52
- transformPage(spec) {
53
- return this.transform('page', spec);
54
- }
55
- /** Transform a Dashboard spec */
56
- transformDashboard(spec) {
57
- return this.transform('dashboard', spec);
58
- }
59
47
  updateContext(ctx) {
60
48
  this.context = { ...this.context, ...ctx };
61
49
  }
@@ -134,17 +134,11 @@ export const bridgeListView = (spec, _context) => {
134
134
  // P1.6 — i18n & ARIA
135
135
  if (spec.aria)
136
136
  node.aria = spec.aria;
137
- if (spec.sharing) {
138
- // Normalize spec sharing format: map type → visibility, set enabled = true
139
- const sharing = { ...spec.sharing };
140
- if (sharing.type && !sharing.visibility) {
141
- sharing.visibility = sharing.type === 'collaborative' ? 'team' : 'private';
142
- }
143
- if (sharing.type && sharing.enabled == null) {
144
- sharing.enabled = true;
145
- }
146
- node.sharing = sharing;
147
- }
137
+ // `sharing` is already the spec's `ViewSharing` shape on both sides (#2890) —
138
+ // this used to DOWNGRADE it here, inventing a legacy `visibility` audience and
139
+ // an `enabled` flag that the renderer then had to fold back.
140
+ if (spec.sharing)
141
+ node.sharing = spec.sharing;
148
142
  if (spec.hiddenFields)
149
143
  node.hiddenFields = spec.hiddenFields;
150
144
  if (spec.fieldOrder)
@@ -9,5 +9,3 @@ export { SpecBridge } from './SpecBridge';
9
9
  export type { BridgeContext, BridgeFn, ObjectDefLite } from './types';
10
10
  export { bridgeListView } from './bridges/list-view';
11
11
  export { bridgeFormView } from './bridges/form-view';
12
- export { bridgePage } from './bridges/page';
13
- export { bridgeDashboard } from './bridges/dashboard';
@@ -8,5 +8,3 @@
8
8
  export { SpecBridge } from './SpecBridge';
9
9
  export { bridgeListView } from './bridges/list-view';
10
10
  export { bridgeFormView } from './bridges/form-view';
11
- export { bridgePage } from './bridges/page';
12
- export { bridgeDashboard } from './bridges/dashboard';
@@ -0,0 +1,37 @@
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
+ /**
9
+ * The AUTHORING ("input") type of a `@objectstack/spec` zod schema.
10
+ *
11
+ * ## Why not `z.infer`
12
+ *
13
+ * `z.infer` is the OUTPUT type — what `.parse()` returns, with every
14
+ * `.default()` already applied and therefore REQUIRED. The hooks in this
15
+ * package are handed configuration an app author wrote by hand, so the input
16
+ * side is the one that describes what they may legally omit. Deriving a config
17
+ * type from `z.infer` turns every defaulted key into a required one and makes
18
+ * the schema's own defaults unusable — the `_input`/`_output` trap the spec
19
+ * symbol guard's header warns about, and the one that already bit
20
+ * `ObjectFieldGroup` in objectui#3169.
21
+ *
22
+ * Rule of thumb: is this module WRITING the metadata, or READING what has
23
+ * already been parsed? Writing → input. Reading → `z.infer`.
24
+ *
25
+ * ## Why it reads `_zod`, not `z.input`
26
+ *
27
+ * `z.input<typeof S>` needs a `zod` import, and `@object-ui/react` deliberately
28
+ * does not depend on zod — it renders plain objects and never parses. The
29
+ * schema's own type already carries both sides in `_zod`, so the input type is
30
+ * reachable through the spec's binding alone, with no new dependency and no
31
+ * copy of the shape.
32
+ */
33
+ export type SpecAuthoredInput<S extends {
34
+ _zod: {
35
+ input: unknown;
36
+ };
37
+ }> = S['_zod']['input'];
@@ -0,0 +1,8 @@
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
+ export {};
@@ -12,6 +12,37 @@
12
12
  * usable can be extracted, so callers fall back to a generic localized string.
13
13
  */
14
14
  export declare function extractWriteErrorMessage(err: unknown): string | null;
15
+ /** One field the server rejected, normalised for `form.setError`. */
16
+ export interface WriteFieldError {
17
+ /** Field name, matching the form control's `name`. */
18
+ field: string;
19
+ /** Human-readable reason, already localized by the server when it can be. */
20
+ message: string;
21
+ }
22
+ /**
23
+ * Per-field errors from a rejected write, or `null` when the failure was not
24
+ * field-scoped.
25
+ *
26
+ * The server has always sent these. `@objectstack/objectql`'s validators throw
27
+ * `{ code: 'VALIDATION_FAILED', fields: [{ field, code, message }] }`, and both
28
+ * the REST layer and the runtime dispatcher serve that as a 400 with `fields[]`
29
+ * intact. What was missing was the last hop: every form caught the rejection,
30
+ * showed one generic toast, and dropped `fields[]` on the floor — so a user told
31
+ * "Validation failed" had to guess WHICH input was wrong, on a surface that
32
+ * already knows how to mark it.
33
+ *
34
+ * Reads three shapes, because the error can arrive from either side of the
35
+ * adapter boundary:
36
+ * - `validationErrors` — a `ValidationError` from `@object-ui/data-objectstack`;
37
+ * - `details.fields` — the raw `@objectstack/client` error, whose `details`
38
+ * falls back to the whole response body;
39
+ * - `fields` — a hand-rolled error of the same shape (the server duck-types
40
+ * these identically, so we do too).
41
+ *
42
+ * Entries without a usable `field` are dropped rather than guessed at: a wrong
43
+ * mark on an innocent input is worse than the generic toast we already show.
44
+ */
45
+ export declare function extractFieldErrors(err: unknown): WriteFieldError[] | null;
15
46
  /**
16
47
  * True when a failed write was rejected for authorization reasons (HTTP 403 /
17
48
  * `PERMISSION_DENIED` / `FORBIDDEN` / a row-level-security denial). Lets a
@@ -68,6 +68,55 @@ export function extractWriteErrorMessage(err) {
68
68
  .trim();
69
69
  return clean || null;
70
70
  }
71
+ /**
72
+ * Per-field errors from a rejected write, or `null` when the failure was not
73
+ * field-scoped.
74
+ *
75
+ * The server has always sent these. `@objectstack/objectql`'s validators throw
76
+ * `{ code: 'VALIDATION_FAILED', fields: [{ field, code, message }] }`, and both
77
+ * the REST layer and the runtime dispatcher serve that as a 400 with `fields[]`
78
+ * intact. What was missing was the last hop: every form caught the rejection,
79
+ * showed one generic toast, and dropped `fields[]` on the floor — so a user told
80
+ * "Validation failed" had to guess WHICH input was wrong, on a surface that
81
+ * already knows how to mark it.
82
+ *
83
+ * Reads three shapes, because the error can arrive from either side of the
84
+ * adapter boundary:
85
+ * - `validationErrors` — a `ValidationError` from `@object-ui/data-objectstack`;
86
+ * - `details.fields` — the raw `@objectstack/client` error, whose `details`
87
+ * falls back to the whole response body;
88
+ * - `fields` — a hand-rolled error of the same shape (the server duck-types
89
+ * these identically, so we do too).
90
+ *
91
+ * Entries without a usable `field` are dropped rather than guessed at: a wrong
92
+ * mark on an innocent input is worse than the generic toast we already show.
93
+ */
94
+ export function extractFieldErrors(err) {
95
+ const e = err;
96
+ if (!e || typeof e !== 'object')
97
+ return null;
98
+ const raw = (Array.isArray(e.validationErrors) && e.validationErrors) ||
99
+ (Array.isArray(e.details?.fields) && e.details.fields) ||
100
+ (Array.isArray(e.fields) && e.fields) ||
101
+ null;
102
+ if (!raw || !Array.isArray(raw))
103
+ return null;
104
+ const out = [];
105
+ for (const entry of raw) {
106
+ if (!entry || typeof entry !== 'object')
107
+ continue;
108
+ const rec = entry;
109
+ const field = firstString(rec.field, rec.name, rec.path);
110
+ if (!field)
111
+ continue;
112
+ // `code` is the machine enum (`required`, `invalid_option`, …). It is a
113
+ // last resort only: the server builds `message` to be shown verbatim, and
114
+ // an untranslated enum in the UI reads as a bug.
115
+ const message = firstString(rec.message, rec.error, rec.code) ?? '';
116
+ out.push({ field, message });
117
+ }
118
+ return out.length > 0 ? out : null;
119
+ }
71
120
  /**
72
121
  * True when a failed write was rejected for authorization reasons (HTTP 403 /
73
122
  * `PERMISSION_DENIED` / `FORBIDDEN` / a row-level-security denial). Lets a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@object-ui/react",
3
- "version": "16.1.0",
3
+ "version": "17.2.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "React bindings and SchemaRenderer component for Object UI",
@@ -24,12 +24,12 @@
24
24
  }
25
25
  },
26
26
  "dependencies": {
27
- "@objectstack/spec": "^16.0.0-rc.0",
28
- "react-hook-form": "^7.82.0",
29
- "@object-ui/core": "16.1.0",
30
- "@object-ui/data-objectstack": "16.1.0",
31
- "@object-ui/i18n": "16.1.0",
32
- "@object-ui/types": "16.1.0"
27
+ "@objectstack/spec": "^17.0.0-rc.1",
28
+ "react-hook-form": "^7.83.0",
29
+ "@object-ui/core": "17.2.0",
30
+ "@object-ui/data-objectstack": "17.2.0",
31
+ "@object-ui/i18n": "17.2.0",
32
+ "@object-ui/types": "17.2.0"
33
33
  },
34
34
  "peerDependencies": {
35
35
  "react": "^18.0.0 || ^19.0.0",
@@ -65,7 +65,7 @@
65
65
  "scripts": {
66
66
  "build": "tsc",
67
67
  "test": "vitest run",
68
- "type-check": "tsc --noEmit",
68
+ "type-check": "tsc --noEmit && tsc -p tsconfig.typetests.json",
69
69
  "lint": "eslint ."
70
70
  }
71
71
  }
@@ -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 {};