@object-ui/core 3.0.3 → 3.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 (78) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/actions/ActionEngine.d.ts +98 -0
  3. package/dist/actions/ActionEngine.js +222 -0
  4. package/dist/actions/UndoManager.d.ts +80 -0
  5. package/dist/actions/UndoManager.js +193 -0
  6. package/dist/actions/index.d.ts +2 -0
  7. package/dist/actions/index.js +2 -0
  8. package/dist/adapters/ApiDataSource.d.ts +2 -1
  9. package/dist/adapters/ApiDataSource.js +25 -0
  10. package/dist/adapters/ValueDataSource.d.ts +2 -1
  11. package/dist/adapters/ValueDataSource.js +99 -3
  12. package/dist/data-scope/ViewDataProvider.d.ts +143 -0
  13. package/dist/data-scope/ViewDataProvider.js +153 -0
  14. package/dist/data-scope/index.d.ts +1 -0
  15. package/dist/data-scope/index.js +1 -0
  16. package/dist/evaluator/ExpressionEvaluator.d.ts +7 -0
  17. package/dist/evaluator/ExpressionEvaluator.js +19 -0
  18. package/dist/index.d.ts +5 -0
  19. package/dist/index.js +5 -0
  20. package/dist/protocols/DndProtocol.d.ts +84 -0
  21. package/dist/protocols/DndProtocol.js +113 -0
  22. package/dist/protocols/KeyboardProtocol.d.ts +93 -0
  23. package/dist/protocols/KeyboardProtocol.js +108 -0
  24. package/dist/protocols/NotificationProtocol.d.ts +71 -0
  25. package/dist/protocols/NotificationProtocol.js +99 -0
  26. package/dist/protocols/ResponsiveProtocol.d.ts +73 -0
  27. package/dist/protocols/ResponsiveProtocol.js +158 -0
  28. package/dist/protocols/SharingProtocol.d.ts +71 -0
  29. package/dist/protocols/SharingProtocol.js +124 -0
  30. package/dist/protocols/index.d.ts +12 -0
  31. package/dist/protocols/index.js +12 -0
  32. package/dist/utils/debug-collector.d.ts +59 -0
  33. package/dist/utils/debug-collector.js +73 -0
  34. package/dist/utils/debug.d.ts +37 -2
  35. package/dist/utils/debug.js +62 -3
  36. package/dist/utils/expand-fields.d.ts +40 -0
  37. package/dist/utils/expand-fields.js +68 -0
  38. package/dist/utils/extract-records.d.ts +16 -0
  39. package/dist/utils/extract-records.js +32 -0
  40. package/dist/utils/normalize-quick-filter.d.ts +29 -0
  41. package/dist/utils/normalize-quick-filter.js +66 -0
  42. package/package.json +3 -3
  43. package/src/__tests__/protocols/DndProtocol.test.ts +186 -0
  44. package/src/__tests__/protocols/KeyboardProtocol.test.ts +177 -0
  45. package/src/__tests__/protocols/NotificationProtocol.test.ts +142 -0
  46. package/src/__tests__/protocols/ResponsiveProtocol.test.ts +176 -0
  47. package/src/__tests__/protocols/SharingProtocol.test.ts +188 -0
  48. package/src/actions/ActionEngine.ts +268 -0
  49. package/src/actions/UndoManager.ts +215 -0
  50. package/src/actions/__tests__/ActionEngine.test.ts +206 -0
  51. package/src/actions/__tests__/UndoManager.test.ts +320 -0
  52. package/src/actions/index.ts +2 -0
  53. package/src/adapters/ApiDataSource.ts +27 -0
  54. package/src/adapters/ValueDataSource.ts +109 -3
  55. package/src/adapters/__tests__/ValueDataSource.test.ts +147 -0
  56. package/src/data-scope/ViewDataProvider.ts +282 -0
  57. package/src/data-scope/__tests__/ViewDataProvider.test.ts +270 -0
  58. package/src/data-scope/index.ts +8 -0
  59. package/src/evaluator/ExpressionEvaluator.ts +22 -0
  60. package/src/evaluator/__tests__/ExpressionEvaluator.test.ts +31 -1
  61. package/src/index.ts +5 -0
  62. package/src/protocols/DndProtocol.ts +184 -0
  63. package/src/protocols/KeyboardProtocol.ts +185 -0
  64. package/src/protocols/NotificationProtocol.ts +159 -0
  65. package/src/protocols/ResponsiveProtocol.ts +210 -0
  66. package/src/protocols/SharingProtocol.ts +185 -0
  67. package/src/protocols/index.ts +13 -0
  68. package/src/utils/__tests__/debug-collector.test.ts +102 -0
  69. package/src/utils/__tests__/debug.test.ts +52 -1
  70. package/src/utils/__tests__/expand-fields.test.ts +120 -0
  71. package/src/utils/__tests__/extract-records.test.ts +50 -0
  72. package/src/utils/__tests__/normalize-quick-filter.test.ts +123 -0
  73. package/src/utils/debug-collector.ts +100 -0
  74. package/src/utils/debug.ts +87 -6
  75. package/src/utils/expand-fields.ts +76 -0
  76. package/src/utils/extract-records.ts +33 -0
  77. package/src/utils/normalize-quick-filter.ts +78 -0
  78. package/tsconfig.tsbuildinfo +1 -1
@@ -17,6 +17,64 @@ function getRecordId(record, idField) {
17
17
  return record[idField];
18
18
  return record._id ?? record.id;
19
19
  }
20
+ /**
21
+ * Evaluate an AST-format filter node against a record.
22
+ * Supports conditions like ['field', 'op', value] and logical
23
+ * combinations like ['and', ...conditions] or ['or', ...conditions].
24
+ */
25
+ function matchesASTFilter(record, filterNode) {
26
+ if (!filterNode || filterNode.length === 0)
27
+ return true;
28
+ const head = filterNode[0];
29
+ // Logical operators: ['and', ...conditions] or ['or', ...conditions]
30
+ if (head === 'and') {
31
+ return filterNode.slice(1).every((sub) => matchesASTFilter(record, sub));
32
+ }
33
+ if (head === 'or') {
34
+ return filterNode.slice(1).some((sub) => matchesASTFilter(record, sub));
35
+ }
36
+ // Condition node: [field, operator, value]
37
+ if (filterNode.length === 3 && typeof head === 'string') {
38
+ const [field, operator, target] = filterNode;
39
+ const value = record[field];
40
+ switch (operator) {
41
+ case '=':
42
+ return value === target;
43
+ case '!=':
44
+ return value !== target;
45
+ case '>':
46
+ return value > target;
47
+ case '>=':
48
+ return value >= target;
49
+ case '<':
50
+ return value < target;
51
+ case '<=':
52
+ return value <= target;
53
+ case 'in':
54
+ return Array.isArray(target) && target.includes(value);
55
+ case 'not in':
56
+ case 'notin': // alias used by convertFiltersToAST
57
+ return Array.isArray(target) && !target.includes(value);
58
+ case 'contains': {
59
+ const lv = typeof value === 'string' ? value.toLowerCase() : '';
60
+ return typeof value === 'string' && lv.includes(String(target).toLowerCase());
61
+ }
62
+ case 'notcontains': {
63
+ const lv = typeof value === 'string' ? value.toLowerCase() : '';
64
+ return typeof value === 'string' && !lv.includes(String(target).toLowerCase());
65
+ }
66
+ case 'startswith': {
67
+ const lv = typeof value === 'string' ? value.toLowerCase() : '';
68
+ return typeof value === 'string' && lv.startsWith(String(target).toLowerCase());
69
+ }
70
+ case 'between':
71
+ return Array.isArray(target) && target.length === 2 && value >= target[0] && value <= target[1];
72
+ default:
73
+ return true;
74
+ }
75
+ }
76
+ return true;
77
+ }
20
78
  /**
21
79
  * Simple in-memory filter evaluation.
22
80
  * Supports flat key-value equality and basic operators ($gt, $gte, $lt, $lte, $ne, $in).
@@ -168,9 +226,14 @@ export class ValueDataSource {
168
226
  // -----------------------------------------------------------------------
169
227
  async find(_resource, params) {
170
228
  let result = [...this.items];
171
- // Filter
172
- if (params?.$filter && Object.keys(params.$filter).length > 0) {
173
- result = result.filter((r) => matchesFilter(r, params.$filter));
229
+ // Filter — support both MongoDB-style objects and AST-format arrays
230
+ if (params?.$filter) {
231
+ if (Array.isArray(params.$filter) && params.$filter.length > 0) {
232
+ result = result.filter((r) => matchesASTFilter(r, params.$filter));
233
+ }
234
+ else if (!Array.isArray(params.$filter) && Object.keys(params.$filter).length > 0) {
235
+ result = result.filter((r) => matchesFilter(r, params.$filter));
236
+ }
174
237
  }
175
238
  // Search (simple text search across all string fields)
176
239
  if (params?.$search) {
@@ -273,6 +336,39 @@ export class ValueDataSource {
273
336
  async getApp(_appId) {
274
337
  return null;
275
338
  }
339
+ async aggregate(_resource, params) {
340
+ const { field, function: aggFn, groupBy } = params;
341
+ const groups = {};
342
+ for (const record of this.items) {
343
+ const key = String(record[groupBy] ?? 'Unknown');
344
+ if (!groups[key])
345
+ groups[key] = [];
346
+ groups[key].push(record);
347
+ }
348
+ return Object.entries(groups).map(([key, group]) => {
349
+ const values = group.map(r => Number(r[field]) || 0);
350
+ let result;
351
+ switch (aggFn) {
352
+ case 'count':
353
+ result = group.length;
354
+ break;
355
+ case 'avg':
356
+ result = values.length > 0 ? values.reduce((a, b) => a + b, 0) / values.length : 0;
357
+ break;
358
+ case 'min':
359
+ result = values.length > 0 ? Math.min(...values) : 0;
360
+ break;
361
+ case 'max':
362
+ result = values.length > 0 ? Math.max(...values) : 0;
363
+ break;
364
+ case 'sum':
365
+ default:
366
+ result = values.reduce((a, b) => a + b, 0);
367
+ break;
368
+ }
369
+ return { [groupBy]: key, [field]: result };
370
+ });
371
+ }
276
372
  // -----------------------------------------------------------------------
277
373
  // Extra utilities
278
374
  // -----------------------------------------------------------------------
@@ -0,0 +1,143 @@
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
+ * @object-ui/core - View Data Provider
10
+ *
11
+ * Resolves @objectstack/spec ViewData discriminated union into
12
+ * a unified data access interface. Supports three data modes:
13
+ *
14
+ * 1. 'object' — Metadata-driven via ObjectStack API (object name → fields/records)
15
+ * 2. 'api' — Custom REST API endpoints (read/write URLs)
16
+ * 3. 'value' — Static data (pre-loaded items array)
17
+ *
18
+ * @module data-scope
19
+ * @packageDocumentation
20
+ */
21
+ /** ViewData union — matches @objectstack/spec ViewDataSchema */
22
+ export type ViewDataConfig = {
23
+ provider: 'object';
24
+ object: string;
25
+ } | {
26
+ provider: 'api';
27
+ read: {
28
+ url: string;
29
+ method?: string;
30
+ headers?: Record<string, string>;
31
+ };
32
+ write?: {
33
+ url: string;
34
+ method?: string;
35
+ headers?: Record<string, string>;
36
+ };
37
+ } | {
38
+ provider: 'value';
39
+ items: any[];
40
+ };
41
+ /** Element-level data source — matches @objectstack/spec ElementDataSourceSchema */
42
+ export interface ElementDataSourceConfig {
43
+ object: string;
44
+ view?: string;
45
+ filter?: Record<string, any>;
46
+ sort?: Array<{
47
+ field: string;
48
+ order: 'asc' | 'desc';
49
+ }>;
50
+ limit?: number;
51
+ }
52
+ /** Fetcher interface — consumers provide the actual fetch implementation */
53
+ export interface DataFetcher {
54
+ /** Fetch records for an object */
55
+ fetchRecords(object: string, options?: {
56
+ filter?: Record<string, any>;
57
+ sort?: Array<{
58
+ field: string;
59
+ order: 'asc' | 'desc';
60
+ }>;
61
+ limit?: number;
62
+ offset?: number;
63
+ fields?: string[];
64
+ }): Promise<{
65
+ records: any[];
66
+ total: number;
67
+ }>;
68
+ /** Fetch object metadata (fields, etc.) */
69
+ fetchMetadata?(object: string): Promise<{
70
+ name: string;
71
+ label?: string;
72
+ fields: Array<{
73
+ name: string;
74
+ label?: string;
75
+ type: string;
76
+ required?: boolean;
77
+ }>;
78
+ }>;
79
+ /** Fetch from a custom API URL */
80
+ fetchUrl?(url: string, options?: {
81
+ method?: string;
82
+ headers?: Record<string, string>;
83
+ body?: any;
84
+ }): Promise<any>;
85
+ }
86
+ /** Resolved data result */
87
+ export interface ResolvedData {
88
+ /** Data records */
89
+ records: any[];
90
+ /** Total record count (for pagination) */
91
+ total: number;
92
+ /** Object metadata (if available) */
93
+ metadata?: {
94
+ name: string;
95
+ label?: string;
96
+ fields: Array<{
97
+ name: string;
98
+ label?: string;
99
+ type: string;
100
+ required?: boolean;
101
+ }>;
102
+ };
103
+ /** Provider type */
104
+ provider: 'object' | 'api' | 'value';
105
+ /** Loading state */
106
+ loading: boolean;
107
+ /** Error */
108
+ error?: string;
109
+ }
110
+ /**
111
+ * Resolves ViewData configuration into actual data via a pluggable fetcher.
112
+ *
113
+ * @example
114
+ * ```ts
115
+ * const provider = new ViewDataProvider(myFetcher);
116
+ * const data = await provider.resolve({ provider: 'object', object: 'Account' });
117
+ * ```
118
+ */
119
+ export declare class ViewDataProvider {
120
+ private fetcher;
121
+ constructor(fetcher?: DataFetcher);
122
+ /** Set the data fetcher implementation */
123
+ setFetcher(fetcher: DataFetcher): void;
124
+ /** Resolve ViewData config into actual data */
125
+ resolve(config: ViewDataConfig, options?: {
126
+ filter?: Record<string, any>;
127
+ sort?: Array<{
128
+ field: string;
129
+ order: 'asc' | 'desc';
130
+ }>;
131
+ limit?: number;
132
+ offset?: number;
133
+ fields?: string[];
134
+ }): Promise<ResolvedData>;
135
+ /** Resolve static value data */
136
+ private resolveValue;
137
+ /** Resolve API-based data */
138
+ private resolveApi;
139
+ /** Resolve object-based data (metadata-driven) */
140
+ private resolveObject;
141
+ /** Resolve element-level data source */
142
+ resolveElementDataSource(config: ElementDataSourceConfig): Promise<ResolvedData>;
143
+ }
@@ -0,0 +1,153 @@
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
+ /** Extract records array from various common API response shapes */
9
+ function extractRecords(data) {
10
+ if (Array.isArray(data))
11
+ return data;
12
+ if (Array.isArray(data?.records))
13
+ return data.records;
14
+ if (Array.isArray(data?.data))
15
+ return data.data;
16
+ if (Array.isArray(data?.items))
17
+ return data.items;
18
+ return [];
19
+ }
20
+ /**
21
+ * Resolves ViewData configuration into actual data via a pluggable fetcher.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * const provider = new ViewDataProvider(myFetcher);
26
+ * const data = await provider.resolve({ provider: 'object', object: 'Account' });
27
+ * ```
28
+ */
29
+ export class ViewDataProvider {
30
+ constructor(fetcher) {
31
+ Object.defineProperty(this, "fetcher", {
32
+ enumerable: true,
33
+ configurable: true,
34
+ writable: true,
35
+ value: null
36
+ });
37
+ this.fetcher = fetcher ?? null;
38
+ }
39
+ /** Set the data fetcher implementation */
40
+ setFetcher(fetcher) {
41
+ this.fetcher = fetcher;
42
+ }
43
+ /** Resolve ViewData config into actual data */
44
+ async resolve(config, options) {
45
+ switch (config.provider) {
46
+ case 'value':
47
+ return this.resolveValue(config);
48
+ case 'api':
49
+ return this.resolveApi(config);
50
+ case 'object':
51
+ return this.resolveObject(config, options);
52
+ default:
53
+ return {
54
+ records: [],
55
+ total: 0,
56
+ provider: 'value',
57
+ loading: false,
58
+ error: `Unknown data provider: ${config.provider}`,
59
+ };
60
+ }
61
+ }
62
+ /** Resolve static value data */
63
+ resolveValue(config) {
64
+ const items = Array.isArray(config.items) ? config.items : [];
65
+ return {
66
+ records: items,
67
+ total: items.length,
68
+ provider: 'value',
69
+ loading: false,
70
+ };
71
+ }
72
+ /** Resolve API-based data */
73
+ async resolveApi(config) {
74
+ if (!this.fetcher?.fetchUrl) {
75
+ return {
76
+ records: [],
77
+ total: 0,
78
+ provider: 'api',
79
+ loading: false,
80
+ error: 'No fetchUrl implementation available for API data provider',
81
+ };
82
+ }
83
+ try {
84
+ const data = await this.fetcher.fetchUrl(config.read.url, {
85
+ method: config.read.method,
86
+ headers: config.read.headers,
87
+ });
88
+ // Handle common response shapes
89
+ const records = extractRecords(data);
90
+ const total = data?.total ?? data?.count ?? records.length;
91
+ return {
92
+ records,
93
+ total,
94
+ provider: 'api',
95
+ loading: false,
96
+ };
97
+ }
98
+ catch (error) {
99
+ return {
100
+ records: [],
101
+ total: 0,
102
+ provider: 'api',
103
+ loading: false,
104
+ error: error.message,
105
+ };
106
+ }
107
+ }
108
+ /** Resolve object-based data (metadata-driven) */
109
+ async resolveObject(config, options) {
110
+ if (!this.fetcher) {
111
+ return {
112
+ records: [],
113
+ total: 0,
114
+ provider: 'object',
115
+ loading: false,
116
+ error: 'No data fetcher configured for object data provider',
117
+ };
118
+ }
119
+ try {
120
+ // Fetch metadata if available
121
+ let metadata;
122
+ if (this.fetcher.fetchMetadata) {
123
+ metadata = await this.fetcher.fetchMetadata(config.object);
124
+ }
125
+ // Fetch records
126
+ const result = await this.fetcher.fetchRecords(config.object, options);
127
+ return {
128
+ records: result.records,
129
+ total: result.total,
130
+ metadata,
131
+ provider: 'object',
132
+ loading: false,
133
+ };
134
+ }
135
+ catch (error) {
136
+ return {
137
+ records: [],
138
+ total: 0,
139
+ provider: 'object',
140
+ loading: false,
141
+ error: error.message,
142
+ };
143
+ }
144
+ }
145
+ /** Resolve element-level data source */
146
+ async resolveElementDataSource(config) {
147
+ return this.resolve({ provider: 'object', object: config.object }, {
148
+ filter: config.filter,
149
+ sort: config.sort,
150
+ limit: config.limit,
151
+ });
152
+ }
153
+ }
@@ -8,3 +8,4 @@
8
8
  * @packageDocumentation
9
9
  */
10
10
  export { DataScopeManager, defaultDataScopeManager, type RowLevelFilter, type DataScopeConfig, } from './DataScopeManager.js';
11
+ export { ViewDataProvider, type ViewDataConfig, type ElementDataSourceConfig, type DataFetcher, type ResolvedData, } from './ViewDataProvider.js';
@@ -8,3 +8,4 @@
8
8
  * @packageDocumentation
9
9
  */
10
10
  export { DataScopeManager, defaultDataScopeManager, } from './DataScopeManager.js';
11
+ export { ViewDataProvider, } from './ViewDataProvider.js';
@@ -125,3 +125,10 @@ export declare function evaluateExpression(expression: string | boolean | number
125
125
  * Convenience function to evaluate a condition
126
126
  */
127
127
  export declare function evaluateCondition(condition: string | boolean | undefined, context?: Record<string, any>): boolean;
128
+ /**
129
+ * Convenience function to evaluate a plain condition string against a data record.
130
+ * Supports both template expressions (e.g., '${data.amount > 1000}') and
131
+ * plain expressions (e.g., "status == 'overdue'").
132
+ * Record fields are available both directly (status) and namespaced (data.status).
133
+ */
134
+ export declare function evaluatePlainCondition(condition: string, record: Record<string, any>): boolean;
@@ -242,3 +242,22 @@ export function evaluateCondition(condition, context = {}) {
242
242
  const evaluator = new ExpressionEvaluator(context, globalCache, globalFormulas);
243
243
  return evaluator.evaluateCondition(condition);
244
244
  }
245
+ /**
246
+ * Convenience function to evaluate a plain condition string against a data record.
247
+ * Supports both template expressions (e.g., '${data.amount > 1000}') and
248
+ * plain expressions (e.g., "status == 'overdue'").
249
+ * Record fields are available both directly (status) and namespaced (data.status).
250
+ */
251
+ export function evaluatePlainCondition(condition, record) {
252
+ const evaluator = new ExpressionEvaluator({ ...record, data: record }, globalCache, globalFormulas);
253
+ try {
254
+ const isTemplate = /\$\{/.test(condition);
255
+ const result = isTemplate
256
+ ? evaluator.evaluate(condition, { throwOnError: true })
257
+ : evaluator.evaluateExpression(condition);
258
+ return result === true;
259
+ }
260
+ catch {
261
+ return false;
262
+ }
263
+ }
package/dist/index.d.ts CHANGED
@@ -13,6 +13,9 @@ export * from './registry/WidgetRegistry.js';
13
13
  export * from './validation/index.js';
14
14
  export * from './builder/schema-builder.js';
15
15
  export * from './utils/filter-converter.js';
16
+ export * from './utils/normalize-quick-filter.js';
17
+ export * from './utils/extract-records.js';
18
+ export * from './utils/expand-fields.js';
16
19
  export * from './evaluator/index.js';
17
20
  export * from './actions/index.js';
18
21
  export * from './query/index.js';
@@ -21,3 +24,5 @@ export * from './theme/index.js';
21
24
  export * from './data-scope/index.js';
22
25
  export * from './errors/index.js';
23
26
  export * from './utils/debug.js';
27
+ export * from './utils/debug-collector.js';
28
+ export * from './protocols/index.js';
package/dist/index.js CHANGED
@@ -12,6 +12,9 @@ export * from './registry/WidgetRegistry.js';
12
12
  export * from './validation/index.js';
13
13
  export * from './builder/schema-builder.js';
14
14
  export * from './utils/filter-converter.js';
15
+ export * from './utils/normalize-quick-filter.js';
16
+ export * from './utils/extract-records.js';
17
+ export * from './utils/expand-fields.js';
15
18
  export * from './evaluator/index.js';
16
19
  export * from './actions/index.js';
17
20
  export * from './query/index.js';
@@ -20,3 +23,5 @@ export * from './theme/index.js';
20
23
  export * from './data-scope/index.js';
21
24
  export * from './errors/index.js';
22
25
  export * from './utils/debug.js';
26
+ export * from './utils/debug-collector.js';
27
+ export * from './protocols/index.js';
@@ -0,0 +1,84 @@
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
+ * @object-ui/core - DnD Protocol Bridge
10
+ *
11
+ * Converts spec-aligned DnD configuration schemas into runtime-usable
12
+ * component props and CSS constraint styles for drag-and-drop interactions.
13
+ *
14
+ * @module protocols/DndProtocol
15
+ * @packageDocumentation
16
+ */
17
+ import type { DndConfig, DragItem, DropZone, DragConstraint } from '@object-ui/types';
18
+ /** Fully resolved DnD configuration with all defaults applied. */
19
+ export interface ResolvedDndConfig {
20
+ enabled: boolean;
21
+ sortable: boolean;
22
+ autoScroll: boolean;
23
+ touchDelay: number;
24
+ dragItem?: DragItem;
25
+ dropZone?: DropZone;
26
+ }
27
+ /** Component props for a draggable element. */
28
+ export interface DragItemProps {
29
+ draggable: boolean;
30
+ 'aria-roledescription': string;
31
+ 'aria-label'?: string;
32
+ 'aria-describedby'?: string;
33
+ role: string;
34
+ 'data-drag-type': string;
35
+ 'data-drag-handle': string;
36
+ 'data-drag-disabled': string;
37
+ }
38
+ /** Component props for a droppable area. */
39
+ export interface DropZoneProps {
40
+ 'aria-dropeffect': string;
41
+ 'aria-label'?: string;
42
+ 'aria-describedby'?: string;
43
+ role: string;
44
+ 'data-drop-accept': string;
45
+ 'data-drop-max-items'?: number;
46
+ 'data-drop-highlight': string;
47
+ }
48
+ /** CSS constraint styles for drag movement. */
49
+ export interface DragConstraintStyles {
50
+ position: string;
51
+ touchAction: string;
52
+ [key: string]: string | number | undefined;
53
+ }
54
+ /**
55
+ * Resolve a DnD configuration by applying spec defaults to missing fields.
56
+ *
57
+ * @param config - Partial DnD configuration from the spec
58
+ * @returns Fully resolved DnD configuration
59
+ */
60
+ export declare function resolveDndConfig(config: DndConfig): ResolvedDndConfig;
61
+ /**
62
+ * Convert a spec DragItem to component props suitable for a draggable element.
63
+ * Produces `draggable`, ARIA attributes, and data attributes for DnD libraries.
64
+ *
65
+ * @param item - DragItem configuration from the spec
66
+ * @returns Component props object for a draggable element
67
+ */
68
+ export declare function createDragItemProps(item: DragItem): DragItemProps;
69
+ /**
70
+ * Convert a spec DropZone to component props suitable for a droppable area.
71
+ * Produces ARIA attributes and data attributes for DnD libraries.
72
+ *
73
+ * @param zone - DropZone configuration from the spec
74
+ * @returns Component props object for a droppable area
75
+ */
76
+ export declare function createDropZoneProps(zone: DropZone): DropZoneProps;
77
+ /**
78
+ * Resolve a DragConstraint into CSS style properties that restrict
79
+ * drag movement along an axis or within bounds.
80
+ *
81
+ * @param constraint - DragConstraint configuration from the spec
82
+ * @returns CSS styles object for constraining drag movement
83
+ */
84
+ export declare function resolveDragConstraints(constraint: DragConstraint): DragConstraintStyles;