-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathobjectql.ts
More file actions
1863 lines (1618 loc) · 53.7 KB
/
Copy pathobjectql.ts
File metadata and controls
1863 lines (1618 loc) · 53.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/**
* ObjectUI
* Copyright (c) 2024-present ObjectStack Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @object-ui/types - ObjectQL Component Schemas
*
* Type definitions for ObjectQL-specific components.
* These schemas enable building ObjectQL-aware interfaces directly from object metadata.
*
* Now aligned with @objectstack/spec view.zod schema for better interoperability.
*
* @module objectql
* @packageDocumentation
*/
import type { BaseSchema } from './base';
import type { FormField } from './form';
// ListView type is now derived from the zod schema (issue #2231) — see ListViewSchema below.
import type { ListViewInferred } from './zod/objectql.zod.js';
// ============================================================================
// Spec-Canonical Types — imported from @objectstack/spec/ui
// Rule: "Never Redefine Types. ALWAYS import them."
// ============================================================================
/**
* HTTP Method for API requests
* Canonical definition from @objectstack/spec/ui.
*/
export type { HttpMethod } from '@objectstack/spec/ui';
/**
* HTTP Request Configuration for API Provider
* Canonical definition from @objectstack/spec/ui.
*/
export type { HttpRequest } from '@objectstack/spec/ui';
/**
* View Data Source Configuration
* Canonical definition from @objectstack/spec/ui.
*
* Supports three modes:
* 1. 'object': Standard Protocol - Auto-connects to ObjectStack Metadata and Data APIs
* 2. 'api': Custom API - Explicitly provided API URLs
* 3. 'value': Static Data - Hardcoded data array
*/
export type { ViewData } from '@objectstack/spec/ui';
/**
* List Column Configuration
* Canonical definition from @objectstack/spec/ui.
*/
export type { ListColumn } from '@objectstack/spec/ui';
/**
* Selection Configuration
* Canonical definition from @objectstack/spec/ui.
*/
export type { SelectionConfig } from '@objectstack/spec/ui';
/**
* Pagination Configuration
* Canonical definition from @objectstack/spec/ui.
*/
export type { PaginationConfig } from '@objectstack/spec/ui';
// Import spec types for local use in interfaces below
import type {
ViewData,
ListColumn,
SelectionConfig,
PaginationConfig,
GroupingConfig,
RowColorConfig,
GalleryConfig,
TimelineConfig,
} from '@objectstack/spec/ui';
/**
* Gallery configuration extended with legacy fields for backward compatibility.
* Spec fields from GalleryConfigSchema take priority; legacy fields serve as fallbacks.
*/
export type ListViewGalleryConfig = GalleryConfig & {
/** Legacy: image field (deprecated, use coverField) */
imageField?: string;
[key: string]: any;
};
/**
* Timeline configuration extended with legacy fields for backward compatibility.
* Spec fields from TimelineConfigSchema take priority; legacy fields serve as fallbacks.
*/
export type ListViewTimelineConfig = TimelineConfig & {
/** Legacy: date field (deprecated, use startDateField) */
dateField?: string;
[key: string]: any;
};
/**
* Kanban Configuration
* Canonical definition from @objectstack/spec/ui (KanbanConfigSchema).
*/
export type KanbanConfig = {
/** Field to group columns by (usually status/select) */
groupByField: string;
/** Field to sum at top of column (e.g. amount) */
summarizeField?: string;
/** Fields to show on cards */
columns: string[];
};
/**
* Calendar Configuration
* Canonical definition from @objectstack/spec/ui (CalendarConfigSchema).
*/
export type CalendarConfig = {
/** Start date field */
startDateField: string;
/** End date field */
endDateField?: string;
/** Title field */
titleField: string;
/** Color field */
colorField?: string;
};
/**
* Gantt Configuration
* Canonical definition from @objectstack/spec/ui (GanttConfigSchema).
*/
export type GanttConfig = {
/** Start date field */
startDateField: string;
/** End date field */
endDateField: string;
/** Title field */
titleField: string;
/** Progress field (0-100) */
progressField?: string;
/** Dependencies field */
dependenciesField?: string;
/** Color field */
colorField?: string;
/**
* Fields to surface in the hover tooltip (悬浮详情), in display order.
* ObjectUI display extension — not part of the upstream GanttConfigSchema.
* Each entry is either a field name (string) or `{ field, label? }` to
* override the label; values are formatted by field type. When omitted the
* tooltip falls back to the built-in start → end · duration · progress line.
*/
tooltipFields?: Array<string | { field: string; label?: string }>;
/**
* Shift segmentation (班次/排班分段). ObjectUI display extension — not part of the
* upstream GanttConfigSchema. When set, the day-mode timeline splits each
* 排班日 (shift-day starting at `dayStart`, default '00:00') into the configured
* time bands (白班 | 夜班…): a two-tier header (date over band), per-band tints,
* and drag/resize snapping to band boundaries. No shift concept is hardcoded —
* bands are pure config. Off by default. Example:
* `{ dayStart: '08:00', bands: [
* { key: 'day', label: '白班', start: '08:00', end: '20:00' },
* { key: 'night', label: '夜班', start: '20:00', end: '08:00' } ] }`.
*/
timeSegments?: {
/** Clock time the shift-day begins, 'HH:mm' (24h). Defaults to '00:00'. */
dayStart?: string;
/** Ordered bands covering the 24h shift-day, beginning at `dayStart`. */
bands: Array<{
/** Stable id (e.g. 'day'/'night'); defaults to `band{index}`. */
key?: string;
/** Display label (白班 / 夜班). */
label: string;
/** Band start, 'HH:mm'. */
start: string;
/** Band end, 'HH:mm'; when `end <= start` the band crosses midnight. */
end: string;
/** Optional accent color (any CSS color) for the column tint. */
color?: string;
}>;
/**
* Draw the dashed calendar-midnight (日历午夜 0:00) cue inside cross-midnight
* bands. Defaults to `true`; set `false` to hide it.
*/
showMidnight?: boolean;
};
};
/**
* Sort Configuration
*/
export interface SortConfig {
/** Field to sort by */
field: string;
/** Sort order */
order: 'asc' | 'desc';
}
// ============================================================================
// QuickFilter Types — Dual-format support
// ============================================================================
// ============================================================================
// ConditionalFormatting Types — Dual-format support
// ============================================================================
/**
* ObjectUI-native ConditionalFormatting rule.
* Uses field/operator/value for declarative comparisons.
*/
export interface ObjectUIConditionalFormattingRule {
/** Field name to evaluate */
field: string;
/** Comparison operator */
operator: 'equals' | 'not_equals' | 'contains' | 'greater_than' | 'less_than' | 'in';
/** Value to compare against */
value: unknown;
/** CSS-compatible background color */
backgroundColor?: string;
/** CSS-compatible text color */
textColor?: string;
/** CSS-compatible border color */
borderColor?: string;
/** Template expression override (e.g., '${data.amount > 1000}') */
expression?: string;
}
/**
* Spec-format ConditionalFormatting rule (from @objectstack/spec).
* Uses a plain expression string with a style map.
* Automatically evaluated at runtime via ExpressionEvaluator.
*/
export interface SpecConditionalFormattingRule {
/** Plain condition expression (e.g., "status == 'overdue'") or template expression (e.g., "${data.amount > 1000}") */
condition: string;
/** Style map to apply when condition matches (e.g., { backgroundColor: '#fee2e2', color: '#991b1b' }) */
style: Record<string, string>;
}
/**
* Union type for ConditionalFormatting rules — accepts both ObjectUI and Spec formats.
* Rules are evaluated in order; first matching rule wins.
*/
export type ConditionalFormattingRule = ObjectUIConditionalFormattingRule | SpecConditionalFormattingRule;
/**
* Parameter declaration for a bulk action. Rendered as a single field in the
* BulkActionDialog params step. Mirrors a minimal FormField shape so existing
* field widgets (text/number/select/lookup/boolean/date) can render it.
*/
export interface BulkActionParam {
/** Parameter name — passed to the runtime handler as params[name]. */
name: string;
/** Human-readable label (i18n-resolved upstream). */
label?: string;
/** Optional help text shown beneath the field. */
help?: string;
/**
* Field widget type — one of the standard FieldWidget names.
* Common values: 'text' | 'number' | 'select' | 'lookup' | 'boolean' | 'date' | 'datetime' | 'textarea'.
*/
type: string;
/** Whether the param is required to enable the Confirm button. */
required?: boolean;
/** Default value applied when the dialog opens. */
default?: unknown;
/** Static options for select-style fields. */
options?: Array<{ label: string; value: string | number | boolean }>;
/** For lookup widgets — the related object name (e.g. 'user'). */
object?: string;
/**
* For `select` / `lookup` widgets — allow picking multiple values. The param
* value becomes a string array and is written to the patch as-is (matching a
* multi-value backend field, e.g. a multi-user `executors`). Defaults to
* single-select.
*/
multiple?: boolean;
/**
* For `lookup` widgets — the related-object field used as the option label
* (defaults to name/full_name/email/id in that order).
*/
labelField?: string;
/** Placeholder text. */
placeholder?: string;
/**
* Catch-all for extra widget-specific configuration (min/max/step/format/...).
* Forwarded to the underlying field renderer as-is.
*/
[key: string]: unknown;
}
/**
* Bulk action operation kind. Determines which `dataSource` method the executor
* calls per batch. `custom` defers entirely to `onComplete` event handlers and
* is intended for callouts (notify/export/...) that don't mutate records.
*/
export type BulkActionOperation = 'update' | 'delete' | 'custom';
/**
* Rich, schema-driven definition of a bulk action.
*
* The grid renders one button per def in the BulkActionBar. Clicking it opens
* the BulkActionDialog: params form → confirm → progress → result. The executor
* batches selected records via `dataSource.bulk(resource, op, items)`.
*
* Pair with the legacy `bulkActions: string[]` field — `bulkActionDefs` takes
* precedence when both are set, but legacy IDs still render alongside as
* fallback buttons.
*/
export interface BulkActionDef {
/** Stable identifier — also used as the action key in audit logs. */
name: string;
/** Human-readable label shown on the button + dialog header. */
label?: string;
/** Lucide icon name (e.g. 'user-check', 'trash-2'); falls back to a generic icon. */
icon?: string;
/** Visual treatment of the action button. */
variant?: 'primary' | 'secondary' | 'danger' | 'ghost' | 'outline';
/** Operation kind — drives how the executor mutates records. */
operation: BulkActionOperation;
/**
* For `operation: 'update'`, a static patch applied to every selected record
* (merged AFTER user-supplied params). Allows declaring fixed-value mass
* updates without exposing them in the params form.
*/
patch?: Record<string, unknown>;
/**
* Parameters collected from the user before execution. Empty/undefined →
* dialog skips the params step and jumps straight to confirm.
*/
params?: BulkActionParam[];
/** Confirmation text shown above the affected-record summary. */
confirmText?: string;
/** Custom Confirm button label (default: "Run"). */
confirmLabel?: string;
/** Permission / feature gate expression — hides the button when it evaluates falsy. */
visible?: string;
/** Max records the action will operate on; selection above this is blocked. */
maxRecords?: number;
/** Batch size for the executor loop (default: 200). */
batchSize?: number;
}
/**
* ObjectGrid Schema
* A specialized grid component that automatically fetches and displays data from ObjectQL objects.
* Implements the grid view type from @objectstack/spec view.zod ListView schema.
*
* Features:
* - Traditional table/grid with CRUD operations
* - Search, filters, pagination
* - Column resizing, sorting
* - Row selection
* - Inline editing support
*/
export interface ObjectGridSchema extends BaseSchema {
type: 'object-grid';
/**
* Internal name for the view
*/
name?: string;
/**
* Display label override
*/
label?: string;
/**
* ObjectQL object name (e.g., 'users', 'accounts', 'contacts')
* Used when data provider is 'object' or not specified
*/
objectName: string;
/**
* Data Source Configuration
* Aligned with @objectstack/spec ViewDataSchema
* If not provided, defaults to { provider: 'object', object: objectName }
*/
data?: ViewData;
/**
* Columns Configuration
* Can be either:
* - Array of field names (simple): ['name', 'email', 'status']
* - Array of ListColumn objects (enhanced): [{ field: 'name', label: 'Full Name', width: 200 }]
*/
columns?: string[] | ListColumn[];
/**
* Filter criteria (JSON Rules format)
* Array-based filter configuration
*/
filter?: any[];
/**
* Sort Configuration
* Can be either:
* - Legacy string format: "name desc"
* - Array of sort configs: [{ field: 'name', order: 'desc' }]
*/
sort?: string | SortConfig[];
/**
* Fields enabled for search
* Defines which fields are searchable when using the search box
*/
searchableFields?: string[];
/**
* Enable column resizing
* Allows users to drag column borders to resize
*/
resizable?: boolean;
/**
* Enable column reordering
* Allows users to drag columns to reorder
*/
reorderableColumns?: boolean;
/**
* Striped row styling
* Alternating row background colors
*/
striped?: boolean;
/**
* Show borders
* Display borders around cells
*/
bordered?: boolean;
/**
* Show column type icons (T / Tag / Calendar / Hash) in column headers.
* Off by default — type is usually obvious from cell content; the icons
* add visual noise that competes with column labels.
* @default false
*/
showColumnTypeIcons?: boolean;
/**
* Row Selection Configuration
* Aligned with @objectstack/spec SelectionConfigSchema
*/
selection?: SelectionConfig;
/**
* Pagination Configuration
* Aligned with @objectstack/spec PaginationConfigSchema
*/
pagination?: PaginationConfig;
/**
* Custom CSS class
*/
className?: string;
// ===== LEGACY FIELDS (for backward compatibility) =====
// These fields are deprecated but maintained for backward compatibility
// They will be mapped to the new structure internally
/**
* @deprecated Use columns instead
* Legacy field names to display
*/
fields?: string[];
/**
* @deprecated Use data with provider: 'value' instead
* Legacy inline data support
*/
staticData?: any[];
/**
* @deprecated Use selection.type instead
* Legacy selection mode
*/
selectable?: boolean | 'single' | 'multiple';
/**
* @deprecated Use pagination.pageSize instead
* Legacy page size
*/
pageSize?: number;
/**
* @deprecated Use searchableFields instead
* Legacy search toggle
*/
showSearch?: boolean;
/**
* @deprecated Use filter property instead
* Legacy filters toggle
*/
showFilters?: boolean;
/**
* @deprecated Use pagination config instead
* Legacy pagination toggle
*/
showPagination?: boolean;
/**
* @deprecated Use sort instead
* Legacy sort configuration
*/
defaultSort?: {
field: string;
order: 'asc' | 'desc';
};
/**
* @deprecated Use filter instead
* Legacy default filters
*/
defaultFilters?: Record<string, any>;
/**
* @deprecated Moved to top-level resizable
* Legacy resizable columns flag
*/
resizableColumns?: boolean;
/**
* @deprecated Use label instead
* Legacy title field
*/
title?: string;
/**
* @deprecated No direct replacement (consider using label with additional context)
* Legacy description field
*/
description?: string;
/**
* Enable/disable built-in operations
* NOTE: This is ObjectUI-specific and not part of @objectstack/spec
*/
operations?: {
/**
* Enable create operation
* @default true
*/
create?: boolean;
/**
* Enable read/view operation
* @default true
*/
read?: boolean;
/**
* Enable update operation
* @default true
*/
update?: boolean;
/**
* Enable delete operation
* @default true
*/
delete?: boolean;
/**
* Enable export operation
* @default false
*/
export?: boolean;
/**
* Enable import operation
* @default false
*/
import?: boolean;
};
/**
* Custom row actions
* NOTE: This is ObjectUI-specific and not part of @objectstack/spec
*/
rowActions?: string[];
/**
* Custom batch actions
* NOTE: This is ObjectUI-specific and not part of @objectstack/spec.
* Legacy alias of `bulkActions` — prefer `bulkActions`. When both are
* set, `batchActions` wins (preserved for backward compatibility).
*/
batchActions?: string[];
/**
* Bulk action identifiers (action names from ActionSchema).
* Aligned with @objectstack/spec ListViewSchema.bulkActions — the
* canonical key; `batchActions` is the legacy ObjectUI alias.
*/
bulkActions?: string[];
/**
* Enable inline cell editing (Grid mode)
* When true, cells become editable on double-click or Enter key
* NOTE: This is ObjectUI-specific and not part of @objectstack/spec
* @default false
*/
editable?: boolean;
/**
* Enable single-click editing mode
* When true with editable, clicking a cell enters edit mode (instead of double-click)
* @default false
*/
singleClickEdit?: boolean;
/**
* Grouping Configuration (Airtable-style)
* Groups rows by specified fields with collapsible sections.
* Aligned with @objectstack/spec GroupingConfigSchema.
*/
grouping?: GroupingConfig;
/**
* Per-group aggregations to display in group headers (e.g. SUM(amount) per region).
* ObjectUI-specific (not in @objectstack/spec for ObjectGrid; sourced from the
* Report protocol when ObjectGrid is rendered as a Summary report body).
* @example [{ field: 'amount', type: 'sum' }, { field: 'id', type: 'count_distinct' }]
*/
aggregations?: Array<{
field: string;
type: 'sum' | 'count' | 'avg' | 'min' | 'max' | 'count_distinct';
}>;
/**
* Row Color Configuration (Airtable-style)
* Colors rows based on field values.
* Aligned with @objectstack/spec RowColorConfigSchema.
*/
rowColor?: RowColorConfig;
/**
* Enable keyboard navigation (Grid mode)
* Arrow keys, Tab, Enter for cell navigation
* NOTE: This is ObjectUI-specific and not part of @objectstack/spec
* @default true when editable is true
*/
keyboardNavigation?: boolean;
/**
* Number of columns to freeze (left-pin)
* Useful for keeping certain columns visible while scrolling
* NOTE: This is ObjectUI-specific and not part of @objectstack/spec
* @default 0
*/
frozenColumns?: number;
/**
* Row height preset for the grid.
* Controls the density of grid rows.
* Aligned with @objectstack/spec RowHeight enum.
* @default 'compact'
*/
rowHeight?: 'compact' | 'short' | 'medium' | 'tall' | 'extra_tall';
/**
* Export options configuration for exporting grid data.
* Supports csv, xlsx, json, and pdf formats.
* Aligned with @objectstack/spec ListViewSchema.exportOptions.
*/
exportOptions?: {
/** Formats available for export */
formats?: Array<'csv' | 'xlsx' | 'json' | 'pdf'>;
/** Maximum number of records to export (0 = unlimited) */
maxRecords?: number;
/** Include column headers in export */
includeHeaders?: boolean;
/** Custom file name prefix */
fileNamePrefix?: string;
};
/**
* Navigation configuration for row click behavior.
* Controls how record detail is displayed when a row is clicked.
* Aligned with @objectstack/spec ListView.navigation.
*/
navigation?: ViewNavigationConfig;
/**
* Callback for page-level navigation (used by 'page' mode).
* Called with recordId and action ('view' | 'edit').
*/
onNavigate?: (recordId: string | number, action?: string) => void;
/**
* Conditional formatting rules for row/cell styling.
* Aligned with @objectstack/spec ListViewSchema.conditionalFormatting.
* Supports both ObjectUI field/operator/value rules and Spec expression-based { condition, style } rules.
*/
conditionalFormatting?: ConditionalFormattingRule[];
/**
* Enable virtual scrolling for large datasets.
* Aligned with @objectstack/spec ListViewSchema.virtualScroll.
* @default false
*/
virtualScroll?: boolean;
/**
* Row action identifiers (action names from ActionSchema).
* Aligned with @objectstack/spec ListViewSchema.rowActions.
*/
rowSpecActions?: string[];
/**
* Bulk action identifiers (action names from ActionSchema).
* Aligned with @objectstack/spec ListViewSchema.bulkActions.
*/
bulkSpecActions?: string[];
/**
* Rich bulk action definitions. When provided, takes precedence over
* `bulkActions` / `bulkSpecActions` (string-id lists) by opening a
* BulkActionDialog that collects params, confirms, and executes via
* dataSource.bulk(...) with progress + result reporting.
*/
bulkActionDefs?: BulkActionDef[];
/**
* Empty state configuration shown when no data is available.
* Aligned with @objectstack/spec ListViewSchema.emptyState.
*/
emptyState?: {
/** Title text for the empty state */
title?: string;
/** Message/description for the empty state */
message?: string;
/** Icon name (Lucide icon identifier) */
icon?: string;
};
}
/**
* Form Section Configuration
* Aligns with @objectstack/spec FormSection
*/
export interface ObjectFormSection {
/**
* Section identifier
*/
name?: string;
/**
* Section label
*/
label?: string;
/**
* Section description
*/
description?: string;
/**
* Whether the section can be collapsed
* @default false
*/
collapsible?: boolean;
/**
* Whether the section is initially collapsed
* @default false
*/
collapsed?: boolean;
/**
* Number of columns for field layout
* @default 1
*/
columns?: 1 | 2 | 3 | 4;
/**
* Field names or inline field configurations for this section
*/
fields: (string | FormField)[];
/**
* Custom CSS class for the section's wrapper (Card, when the form variant
* renders sections as cards; the divider header, for the flat/simple path).
*/
className?: string;
/**
* Custom CSS class for the section's field grid. Only used by form variants
* that render sections as Card chrome (Modal/Split/Tabbed/Wizard).
*/
gridClassName?: string;
}
/**
* ObjectForm Schema
* A smart form component that generates forms from ObjectQL object schemas.
* It automatically creates form fields based on object metadata.
*
* Supports multiple form variants aligned with @objectstack/spec FormView:
* - `simple` – Flat field list (default)
* - `tabbed` – Fields organized in tabs
* - `wizard` – Multi-step form with navigation
* - `split` – Side-by-side panels (reserved)
* - `drawer` – Slide-out form panel (reserved)
* - `modal` – Dialog-based form (reserved)
*/
/**
* Declarative post-submit behavior — aligned with `@objectstack/spec`'s
* `FormView.submitBehavior`. Lets metadata-only forms (which can't pass an
* `onSuccess` function) declare what happens after a successful create/update.
*/
export type SubmitBehavior =
| { kind: 'thank-you'; title?: string; message?: string }
| { kind: 'redirect'; url: string; delayMs?: number }
| { kind: 'continue' }
| { kind: 'next-record' };
/**
* Key taxonomy (#2545 — spec `FormViewSchema` alignment):
*
* - **[spec-aligned]** — same name & semantics as `@objectstack/spec`
* `FormViewSchema` (`title`, `description`, `layout`, `columns`, `sections`,
* `defaultTab`, `tabPosition`, `allowSkip`, `showStepIndicator`,
* `splitDirection`/`splitSize`/`splitResizable`, `drawerSide`/`drawerWidth`,
* `modalSize`, `subforms`, `submitBehavior`; `formType` ↔ spec `type`).
* - **[ObjectUI extension]** — serializable renderer extras with no spec
* backing yet (button visibility/labels, `className`, `initialValues`,
* `fields`/`customFields`, …). Candidates for upstreaming are tracked in
* #2545; until then they are sanctioned, documented extensions.
* - **[runtime-only]** — non-serializable runtime concerns that never belong
* in view metadata (`mode`, `recordId`, `open`, callbacks, …).
*/
export interface ObjectFormSchema extends BaseSchema {
type: 'object-form';
/**
* Form variant type.
* Aligns with @objectstack/spec FormView.type
*
* - `simple` – Standard flat form (default)
* - `tabbed` – Sections as tabs
* - `wizard` – Multi-step wizard with progress indicator
* - `split` – Side-by-side panel layout (reserved)
* - `drawer` – Slide-out form (reserved)
* - `modal` – Dialog form (reserved)
*
* @default 'simple'
*/
formType?: 'simple' | 'tabbed' | 'wizard' | 'split' | 'drawer' | 'modal';
/**
* ObjectQL object name (e.g., 'users', 'accounts', 'contacts')
*/
objectName: string;
/**
* Form mode
*/
mode: 'create' | 'edit' | 'view';
/**
* Record ID (required for edit/view modes)
*/
recordId?: string | number;
/**
* Optional title for the form
*/
title?: string;
/**
* Optional description
*/
description?: string;
/**
* Field names to include in the form
* If not specified, uses all editable fields from object schema
*/
fields?: string[];
/**
* Custom field configurations
* Overrides auto-generated fields for specific fields.
* When used with inline field definitions (without dataSource), this becomes the primary field source.
*/
customFields?: FormField[];
/**
* Inline initial data for demo/static forms
* When provided along with customFields (or inline field definitions), the form can work without a data source.
* Useful for documentation examples and prototyping.
*/
initialData?: Record<string, any>;
/**
* Form sections for organized layout.
* Used by tabbed/wizard/simple forms to group fields.
* Aligns with @objectstack/spec FormView.sections
*/
sections?: ObjectFormSection[];
/**
* Field groups for organized layout.
*
* @deprecated Legacy alias of {@link sections} — `@objectstack/spec`
* FormViewSchema defines `groups` as "Legacy support → alias to sections",
* and the form renderer only consumes `sections`. Consumers (spec-bridge,
* ObjectForm) normalize `groups` into `sections` when `sections` is absent;
* new metadata should declare `sections` directly. Note the legacy shape
* differs from {@link ObjectFormSection}: `title`→`label`,
* `defaultCollapsed`→`collapsed`.
*/
groups?: Array<{
title?: string;
description?: string;
fields: string[];
collapsible?: boolean;
defaultCollapsed?: boolean;
}>;
/**
* Form layout.
*
* Supported layouts:
* - `vertical` – label above field (default)
* - `horizontal` – label and field in a row
* - `inline` – compact inline layout, typically used in toolbars
* - `grid` – **experimental** grid layout
*
* @default 'vertical'
*/
layout?: 'vertical' | 'horizontal' | 'inline' | 'grid';
/**
* Grid columns (for grid layout).
* @default 2
*/
columns?: number;
/**
* Default active tab (section name). Only used when formType is 'tabbed'.
*/
defaultTab?: string;
/**
* Tab position. Only used when formType is 'tabbed'.
* @default 'top'
*/
tabPosition?: 'top' | 'bottom' | 'left' | 'right';
/**
* Allow skipping steps. Only used when formType is 'wizard'.
* @default false
*/
allowSkip?: boolean;
/**
* Show step indicator. Only used when formType is 'wizard'.
* @default true
*/
showStepIndicator?: boolean;
/**
* Text for Next button. Only used when formType is 'wizard'.
* @default 'Next'
*/
nextText?: string;
/**
* Text for Previous button. Only used when formType is 'wizard'.
* @default 'Back'
*/
prevText?: string;
/**
* Called when wizard step changes. Only used when formType is 'wizard'.
*/
onStepChange?: (step: number) => void;
/**
* Show submit button
* @default true
*/
showSubmit?: boolean;
/**
* Submit button text
*/
submitText?: string;