@nubitio/crud 0.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.
@@ -0,0 +1,1869 @@
1
+ import React, { ReactNode, RefObject } from "react";
2
+ import { CoreHttpClient, DataGridEventNames, DataRecord, DataRecord as DataRecord$1, DialogEventNames, FormEventNames, GridData, GridData as GridData$1, createCrudEvents } from "@nubitio/core";
3
+ import { AppDropdownOption } from "@nubitio/ui";
4
+
5
+ //#region packages/crud/field/FieldType.d.ts
6
+ declare enum FieldType {
7
+ NONE = "none",
8
+ TEXT = "text",
9
+ PASSWORD = "password",
10
+ TEXTAREA = "textarea",
11
+ DATE = "date",
12
+ DATETIME = "datetime",
13
+ NUMBER = "number",
14
+ CURRENCY = "currency",
15
+ SELECT = "select",
16
+ ENUM = "enum",
17
+ ENTITY = "entity",
18
+ RADIO = "radio",
19
+ SWITCH = "switch",
20
+ CHECKBOX = "checkbox",
21
+ FILE = "file",
22
+ TAGS = "tags",
23
+ HTML = "html"
24
+ }
25
+ //#endregion
26
+ //#region packages/crud/field/FilterRule.d.ts
27
+ interface FilterRule {
28
+ field: string;
29
+ operator: string;
30
+ value: string | number | boolean;
31
+ }
32
+ //#endregion
33
+ //#region packages/crud/field/ValidationRule.d.ts
34
+ type RequiredRule = {
35
+ type: 'required';
36
+ options: {
37
+ message?: string;
38
+ };
39
+ };
40
+ type EmailRule = {
41
+ type: 'email';
42
+ options: {
43
+ message?: string;
44
+ };
45
+ };
46
+ type NumericRule = {
47
+ type: 'numeric';
48
+ options: {
49
+ message?: string;
50
+ };
51
+ };
52
+ type PatternRule = {
53
+ type: 'pattern';
54
+ options: {
55
+ pattern: string;
56
+ message?: string;
57
+ };
58
+ };
59
+ type StringLengthRule = {
60
+ type: 'stringLength';
61
+ options: {
62
+ min?: number;
63
+ max?: number;
64
+ message?: string;
65
+ };
66
+ };
67
+ type RangeRule = {
68
+ type: 'range';
69
+ options: {
70
+ min?: number;
71
+ max?: number;
72
+ message?: string;
73
+ };
74
+ };
75
+ type CompareRule = {
76
+ type: 'compare';
77
+ options: {
78
+ comparisonTarget: () => unknown;
79
+ comparisonType?: '==' | '!=' | '>' | '<' | '>=' | '<=';
80
+ message?: string;
81
+ };
82
+ };
83
+ type CustomRule = {
84
+ type: 'custom';
85
+ options: {
86
+ validationCallback: (value: unknown) => boolean;
87
+ message?: string;
88
+ };
89
+ };
90
+ type AsyncRule = {
91
+ type: 'async';
92
+ options: {
93
+ validationCallback: (value: unknown) => Promise<boolean>;
94
+ message?: string;
95
+ };
96
+ };
97
+ type ValidationRule = RequiredRule | EmailRule | NumericRule | PatternRule | StringLengthRule | RangeRule | CompareRule | CustomRule | AsyncRule;
98
+ //#endregion
99
+ //#region packages/crud/field/FieldCallbacks.d.ts
100
+ interface GridCellContext<TData extends DataRecord$1 = DataRecord$1, TValue = unknown> {
101
+ value?: TValue;
102
+ data: TData;
103
+ rowIndex?: number;
104
+ columnIndex?: number;
105
+ [key: string]: unknown;
106
+ }
107
+ /**
108
+ * Callback for grid column cell rendering.
109
+ * Receives the app-owned cell context; UI adapters may provide extra fields.
110
+ *
111
+ * Pass a TData type argument to get typed access to cell.data:
112
+ * FormatterFn<InvoiceRecord>
113
+ * (cell: GridCellContext<InvoiceRecord>) => cell.data.customer?.ruc
114
+ */
115
+ type FormatterFn<TData extends DataRecord$1 = DataRecord$1> = (cell: GridCellContext<TData>) => React.ReactNode;
116
+ /**
117
+ * Callback for grid column `setCellValue` — called when the user edits a cell in an
118
+ * inline grid editor. The active grid adapter passes three arguments:
119
+ * - `newData` – partial row data object to mutate with the new value
120
+ * - `value` – the new cell value
121
+ * - `currentRowData`– the full row data before the edit
122
+ *
123
+ * @example
124
+ * .onChange(function(row, value, currentRow) { row.total = value * currentRow.qty; })
125
+ */
126
+ type GridOnChangeFn = (newData: DataRecord$1, value: unknown, currentRowData: DataRecord$1) => void | Promise<void>;
127
+ /**
128
+ * Callback for form field `onValueChanged` — called when the user changes a form
129
+ * field value. The form infrastructure unwraps adapter events and passes the raw value directly.
130
+ *
131
+ * @example
132
+ * .onChange(value => { selectedWarehouseId = value as number; })
133
+ */
134
+ type FormOnChangeFn = (value: unknown) => void | Promise<void>;
135
+ /** Union accepted by `.onChange()` — covers both grid and form contexts. */
136
+ type OnChangeFn = GridOnChangeFn | FormOnChangeFn;
137
+ /**
138
+ * Callback for `itemRender` in dropdown/select editors — renders a single list item.
139
+ *
140
+ * @example
141
+ * .itemFormatter(item => `${item.code} – ${item.name}`)
142
+ */
143
+ type ItemFormatterFn = (item: unknown) => React.ReactNode;
144
+ //#endregion
145
+ //#region packages/crud/view/drawerSizes.d.ts
146
+ /**
147
+ * Drawer size tokens for CRUD viewMode.
148
+ *
149
+ * Tokens describe spatial capacity (how wide the panel is), not domain meaning.
150
+ * `drawerWidth` always wins when set explicitly.
151
+ */
152
+ type CrudDrawerSize = 'sm' | 'md' | 'lg' | 'xl';
153
+ declare const DRAWER_WIDTHS: Record<CrudDrawerSize, number>;
154
+ declare const DEFAULT_DRAWER_SIZE: CrudDrawerSize;
155
+ declare const DEFAULT_DRAWER_WIDTH: string;
156
+ declare function resolveDrawerWidth(options?: {
157
+ drawerSize?: CrudDrawerSize;
158
+ drawerWidth?: number | string;
159
+ }): number | string;
160
+ declare function parseDrawerWidthPx(drawerWidth?: number | string): number | undefined;
161
+ /**
162
+ * Maps an effective drawer width to a layout bucket used by the form grid resolver.
163
+ * Thresholds align with {@link DRAWER_WIDTHS} token boundaries.
164
+ */
165
+ declare function resolveDrawerLayoutBucket(drawerWidth?: number | string): CrudDrawerSize;
166
+ //#endregion
167
+ //#region packages/crud/form/resolveFieldColSpan.d.ts
168
+ type FormLayoutHint = 'short' | 'medium' | 'long' | 'multiline' | 'fullWidth' | 'identity' | 'money' | 'date' | 'lookup' | 'upload' | 'detail';
169
+ type FormPresentationMode = 'dialog' | 'drawer' | 'page';
170
+ /** @deprecated Use {@link CrudDrawerSize} from drawer size tokens instead. */
171
+ type DrawerSize = CrudDrawerSize;
172
+ type ColSpan = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
173
+ interface FormPresentationContext {
174
+ presentationMode: FormPresentationMode;
175
+ drawerWidth?: number | string;
176
+ dialogWidth?: number;
177
+ viewportWidth?: number;
178
+ containerWidth?: number;
179
+ hasTabs?: boolean;
180
+ hasMasterDetail?: boolean;
181
+ }
182
+ interface FieldColSpanContext extends FormPresentationContext {
183
+ drawerSize?: CrudDrawerSize;
184
+ avoidOrphanFields?: boolean;
185
+ }
186
+ /** Layout bucket derived from the effective drawer width. */
187
+ declare function resolveDrawerSize(drawerWidth?: number | string): CrudDrawerSize;
188
+ /**
189
+ * Structural full-width signal — type, layout hint, or declared max length only.
190
+ * No field-name or label heuristics (library stays domain-agnostic).
191
+ */
192
+ declare function isLongTextField(field: Field): boolean;
193
+ /**
194
+ * Structural compact-field signal — field type and explicit layout hints only.
195
+ */
196
+ declare function isShortField(field: Field): boolean;
197
+ /**
198
+ * Resolves the grid column span for a single field.
199
+ * Explicit `field.col` always wins over heuristics.
200
+ */
201
+ declare function resolveFieldColSpan(field: Field, context: FieldColSpanContext): ColSpan;
202
+ /**
203
+ * Resolves spans for a field list and optionally expands a trailing half-column orphan.
204
+ */
205
+ declare function resolveFieldsColSpans(fields: Field[], context: FieldColSpanContext): Map<string, ColSpan>;
206
+ declare function buildFieldColSpanContext(options: FormPresentationContext & {
207
+ avoidOrphanFields?: boolean;
208
+ }): FieldColSpanContext;
209
+ //#endregion
210
+ //#region packages/crud/field/Field.d.ts
211
+ type LoadOption = Record<string, any>;
212
+ interface FieldButton {
213
+ name?: string;
214
+ location?: string;
215
+ options?: {
216
+ icon?: string;
217
+ stylingMode?: string;
218
+ onClick?: (event: unknown, form: {
219
+ getFieldValue: (name: string) => unknown;
220
+ setFieldValue: (name: string, value: unknown) => void;
221
+ }) => void;
222
+ };
223
+ }
224
+ interface Field {
225
+ isIdentity: boolean;
226
+ type: FieldType;
227
+ col: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | undefined;
228
+ name: string;
229
+ label: string;
230
+ width: string | number | undefined;
231
+ height: number | null;
232
+ minWidth: number | undefined;
233
+ align: 'left' | 'center' | 'right' | undefined;
234
+ sortable: boolean;
235
+ filterable: boolean;
236
+ hideable: boolean;
237
+ validators: ValidationRule[];
238
+ url: string | undefined;
239
+ loadOptions: LoadOption[];
240
+ filters: FilterRule[];
241
+ byKeyUrl: string | null;
242
+ textField: string;
243
+ valueField: string;
244
+ valueType: 'string' | 'number' | 'date' | 'boolean' | 'object' | 'datetime';
245
+ format: string;
246
+ selectedFilterOperation: '<' | '<=' | '<>' | '=' | '>' | '>=' | 'between' | 'contains' | 'endswith' | 'notcontains' | 'startswith' | undefined;
247
+ filterValue: string | number | boolean | Date | null | undefined;
248
+ data: DataRecord$1[];
249
+ formatter: FormatterFn | undefined;
250
+ itemFormatter: ItemFormatterFn | undefined;
251
+ visible: boolean;
252
+ defaultValue: string | number | boolean | Date | null | undefined | (() => unknown);
253
+ autoSelectIfSingle?: boolean;
254
+ onChange: OnChangeFn | undefined;
255
+ onSelect: ((e: unknown) => void) | undefined;
256
+ onClick: ((e: unknown) => void) | undefined;
257
+ readonly: boolean;
258
+ disabled: boolean;
259
+ hidden: boolean;
260
+ required: boolean;
261
+ precision: number;
262
+ accept: string | null | undefined;
263
+ buttons: FieldButton[];
264
+ searchEnabled: boolean;
265
+ searchExpr: string[] | null;
266
+ helpText: string | undefined;
267
+ contentRender: string | ((...args: unknown[]) => React.ReactNode) | null | undefined;
268
+ visibleOnForm: boolean;
269
+ maxLength: number | undefined;
270
+ multiple: boolean;
271
+ sendAsString: boolean;
272
+ /** Column display order hint set via `x-crud.order` from Hydra metadata. */
273
+ order?: number;
274
+ /**
275
+ * Mobile card layout hint:
276
+ * - 'title' → rendered as the card title (bold, no label)
277
+ * - 'primary' → always-visible labelled row
278
+ * - 'secondary' → collapsed behind the card's "show more" toggle
279
+ * - 'hidden' → never shown on the card
280
+ * Without hints the grid uses the first non-date visible column as title
281
+ * and the next four columns as primary rows.
282
+ */
283
+ cardRole?: 'title' | 'primary' | 'secondary' | 'hidden';
284
+ /** Optional visual layout hint for auto column resolution. */
285
+ layoutHint?: FormLayoutHint;
286
+ /** Preferred grid span when auto layout is active. */
287
+ preferredColSpan?: 6 | 12;
288
+ /** Minimum grid span when auto layout is active. */
289
+ minColSpan?: 6 | 12;
290
+ /** Forces full-width layout regardless of heuristics (explicit `col` still wins). */
291
+ forceFullWidth?: boolean;
292
+ /** Returns true when the field should be visible */
293
+ visibleWhen?: (formData: DataRecord$1) => boolean;
294
+ /** Returns true when the field should be disabled (read-only in form) */
295
+ disabledWhen?: (formData: DataRecord$1) => boolean;
296
+ /** Derived value — field is rendered as read-only with this computed value */
297
+ computed?: (formData: DataRecord$1) => unknown;
298
+ /** Default value applied when the current value is empty for the current form data */
299
+ defaultWhen?: (formData: DataRecord$1) => unknown;
300
+ /** Returns true when the field should be required for the current form data */
301
+ requiredWhen?: (formData: DataRecord$1) => boolean;
302
+ /** Clears the field value when `visibleWhen` hides it. */
303
+ clearWhenHidden?: boolean;
304
+ /** When listed fields change, reload this field's options (entityField / enumField) */
305
+ dependsOn?: string[];
306
+ /** UI-only RBAC — field is hidden/readonly based on user roles */
307
+ permissions?: {
308
+ /** Roles that can SEE this field. Omit = visible to all. */visible?: string[]; /** Roles that can EDIT this field. Omit = editable by all who can see it. */
309
+ editable?: string[];
310
+ };
311
+ }
312
+ /**
313
+ * Generic extension of `Field` that narrows `defaultValue` and `onChange`
314
+ * to the value types of a specific resource record type `T`.
315
+ *
316
+ * Use `FieldDef<T>` when you want type-safe field definitions for a known
317
+ * resource shape. Falls back to `DataRecord` when `T` is omitted.
318
+ *
319
+ * `defaultValue` and `onChange` are re-declared with generic-aware types;
320
+ * all other `Field` properties are inherited unchanged.
321
+ */
322
+ type FieldDef<T extends DataRecord$1 = DataRecord$1> = Omit<Field, 'defaultValue' | 'onChange'> & {
323
+ defaultValue?: T[keyof T] | (() => T[keyof T]);
324
+ onChange?: ((value: T[keyof T]) => void | Promise<void>) | GridOnChangeFn;
325
+ };
326
+ //#endregion
327
+ //#region packages/crud/form/FormDataSnapshot.d.ts
328
+ type FormDataRecord = DataRecord$1;
329
+ type FormDataSnapshot = FormDataRecord;
330
+ type FormDataChangedHandler = (formData: FormDataSnapshot) => void;
331
+ //#endregion
332
+ //#region packages/crud/form/FormHandle.d.ts
333
+ interface FormHandle {
334
+ getFormData: () => FormDataRecord | undefined;
335
+ getFieldValue: (name: string) => unknown;
336
+ setFieldValue: (name: string, value: unknown) => void;
337
+ getDetailData: () => FormDataRecord[] | undefined;
338
+ setDetailData: (data: FormDataRecord[]) => void;
339
+ saveDetailData: () => Promise<void> | void;
340
+ reloadDetailData: () => void;
341
+ setValues: (data: FormDataRecord) => void;
342
+ save: () => void;
343
+ deleteRow: (row: FormDataRecord) => void;
344
+ setReadonly: (field: string, value: boolean) => void;
345
+ setDisabled: (field: string, value: boolean) => void;
346
+ enableValidation: (field: string) => void;
347
+ disableValidation: (field: string) => void;
348
+ setError: (field: string, message: string) => void;
349
+ showField: (field: string) => void;
350
+ hideField: (field: string) => void;
351
+ validate: () => boolean;
352
+ setIsEdit: (value: boolean) => void;
353
+ }
354
+ //#endregion
355
+ //#region packages/crud/datagrid/GridHandle.d.ts
356
+ interface GridHandle {
357
+ showLoading: (message?: string) => void;
358
+ hideLoading: () => void;
359
+ refresh: () => void;
360
+ reset: () => void;
361
+ loadData: () => Promise<unknown>;
362
+ getSelectedRowKey: () => string | number | undefined;
363
+ getSelectedRow: () => DataRecord$1 | undefined;
364
+ getSelectedRowKeys: () => unknown[];
365
+ getSelectedRows: () => DataRecord$1[];
366
+ getFilter: () => unknown[];
367
+ filter: (filterRule: FilterRule | null) => void;
368
+ }
369
+ //#endregion
370
+ //#region packages/crud/form/FormLayout.d.ts
371
+ interface FormTab {
372
+ label: string;
373
+ fields: string[];
374
+ icon?: string;
375
+ }
376
+ interface FormSection {
377
+ label: string;
378
+ fields: string[];
379
+ collapsible?: boolean;
380
+ defaultCollapsed?: boolean;
381
+ /** When true (default), trailing half-column orphans expand to full width. */
382
+ avoidOrphanFields?: boolean;
383
+ }
384
+ type FormLayout = {
385
+ type: 'tabs';
386
+ tabs: FormTab[];
387
+ } | {
388
+ type: 'sections';
389
+ sections: FormSection[];
390
+ };
391
+ //#endregion
392
+ //#region packages/crud/crud/BulkAction.d.ts
393
+ interface BulkAction {
394
+ key: string;
395
+ label: string;
396
+ icon?: string;
397
+ confirmMessage?: string;
398
+ onAction: (selectedIds: (string | number)[]) => void | Promise<void>;
399
+ }
400
+ //#endregion
401
+ //#region packages/crud/crud/ColumnPreset.d.ts
402
+ interface ColumnPreset {
403
+ key: string;
404
+ label: string;
405
+ columns: string[];
406
+ }
407
+ //#endregion
408
+ //#region packages/crud/crud/AuditTrail.d.ts
409
+ interface AuditEntry {
410
+ id: string | number;
411
+ timestamp: string;
412
+ user: string;
413
+ action: 'create' | 'update' | 'delete';
414
+ changes: Record<string, {
415
+ before: unknown;
416
+ after: unknown;
417
+ }>;
418
+ }
419
+ interface AuditTrailConfig {
420
+ enabled: boolean;
421
+ apiUrl: string | ((id: string | number) => string);
422
+ renderEntry?: (entry: AuditEntry) => ReactNode;
423
+ }
424
+ //#endregion
425
+ //#region packages/crud/crud/fieldOperationSemantics.d.ts
426
+ type SmartCrudOperation = 'create' | 'edit';
427
+ type SmartCrudFieldOperation = SmartCrudOperation;
428
+ type SmartCrudFieldOperationFlag = boolean | Partial<Record<SmartCrudFieldOperation, boolean>>;
429
+ interface SmartCrudFieldOperationState {
430
+ visible?: boolean;
431
+ required?: boolean;
432
+ readonly?: boolean;
433
+ disabled?: boolean;
434
+ }
435
+ interface SmartCrudFieldOperationBehavior {
436
+ only?: SmartCrudFieldOperation | readonly SmartCrudFieldOperation[];
437
+ visible?: SmartCrudFieldOperationFlag;
438
+ required?: SmartCrudFieldOperationFlag;
439
+ readonly?: SmartCrudFieldOperationFlag;
440
+ disabled?: SmartCrudFieldOperationFlag;
441
+ create?: SmartCrudFieldOperationState;
442
+ edit?: SmartCrudFieldOperationState;
443
+ }
444
+ //#endregion
445
+ //#region packages/crud/crud/fieldValidation.d.ts
446
+ type SmartCrudRecord$1 = object;
447
+ type SmartCrudHydraDirectiveLike<T extends SmartCrudRecord$1> = {
448
+ kind: 'override';
449
+ key: Extract<keyof T, string>;
450
+ patch: SmartCrudFieldPatchLike;
451
+ } | {
452
+ kind: 'remove';
453
+ key: Extract<keyof T, string>;
454
+ } | {
455
+ kind: 'prepend';
456
+ field: SmartCrudManualFieldLike;
457
+ } | {
458
+ kind: 'append';
459
+ field: SmartCrudManualFieldLike;
460
+ };
461
+ type SmartCrudFieldContractLike<T extends SmartCrudRecord$1> = {
462
+ source: 'hydra';
463
+ strategy: 'augment';
464
+ directives: readonly SmartCrudHydraDirectiveLike<T>[];
465
+ } | {
466
+ source: 'manual';
467
+ strategy: 'replace';
468
+ fields: readonly SmartCrudManualFieldLike[];
469
+ };
470
+ declare const FIELD_KEYS: readonly ["isIdentity", "type", "col", "name", "label", "width", "height", "minWidth", "align", "sortable", "filterable", "hideable", "validators", "url", "loadOptions", "filters", "byKeyUrl", "textField", "valueField", "valueType", "format", "selectedFilterOperation", "filterValue", "data", "formatter", "itemFormatter", "visible", "defaultValue", "autoSelectIfSingle", "onChange", "onSelect", "onClick", "readonly", "disabled", "hidden", "required", "precision", "accept", "buttons", "searchEnabled", "searchExpr", "helpText", "contentRender", "visibleOnForm", "maxLength", "multiple", "sendAsString", "order", "layoutHint", "preferredColSpan", "minColSpan", "forceFullWidth", "visibleWhen", "disabledWhen", "computed", "defaultWhen", "requiredWhen", "clearWhenHidden", "dependsOn", "permissions"];
471
+ type SmartCrudFieldShape = Partial<Record<(typeof FIELD_KEYS)[number], unknown>>;
472
+ type SmartCrudFieldPatchLike = SmartCrudFieldShape & {
473
+ operation?: SmartCrudFieldOperationBehavior;
474
+ };
475
+ type SmartCrudManualFieldLike = SmartCrudFieldShape & {
476
+ name: string;
477
+ operation?: SmartCrudFieldOperationBehavior;
478
+ };
479
+ declare function validateFieldContract<T extends SmartCrudRecord$1>(contract: SmartCrudFieldContractLike<T>): SmartCrudFieldContractLike<T>;
480
+ //#endregion
481
+ //#region packages/crud/crud/fieldContract.d.ts
482
+ type SmartCrudRecord = DataRecord$1;
483
+ type SmartCrudModelFieldKey<T extends SmartCrudRecord> = Extract<keyof T, string>;
484
+ type SmartCrudFieldRecord<T extends SmartCrudRecord> = T & DataRecord$1;
485
+ type SmartCrudFieldPatch<T extends SmartCrudRecord> = Partial<Omit<FieldDef<SmartCrudFieldRecord<T>>, 'name' | 'defaultValue' | 'onChange' | 'required' | 'readonly' | 'disabled'>> & {
486
+ defaultValue?: FieldDef<SmartCrudFieldRecord<T>>['defaultValue'];
487
+ onChange?: FieldDef<SmartCrudFieldRecord<T>>['onChange'];
488
+ required?: boolean;
489
+ readonly?: boolean;
490
+ disabled?: boolean;
491
+ operation?: SmartCrudFieldOperationBehavior;
492
+ };
493
+ type SmartCrudManualField<T extends SmartCrudRecord, Name extends string = string> = Omit<FieldDef<SmartCrudFieldRecord<T>>, 'name' | 'defaultValue' | 'onChange' | 'required' | 'readonly' | 'disabled'> & {
494
+ name: Name;
495
+ defaultValue?: FieldDef<SmartCrudFieldRecord<T>>['defaultValue'];
496
+ onChange?: FieldDef<SmartCrudFieldRecord<T>>['onChange'];
497
+ required?: boolean;
498
+ readonly?: boolean;
499
+ disabled?: boolean;
500
+ operation?: SmartCrudFieldOperationBehavior;
501
+ };
502
+ interface SmartCrudOverrideField<T extends SmartCrudRecord, Key extends SmartCrudModelFieldKey<T> = SmartCrudModelFieldKey<T>> {
503
+ kind: 'override';
504
+ key: Key;
505
+ patch: SmartCrudFieldPatch<T>;
506
+ }
507
+ interface SmartCrudRemoveField<T extends SmartCrudRecord, Key extends SmartCrudModelFieldKey<T> = SmartCrudModelFieldKey<T>> {
508
+ kind: 'remove';
509
+ key: Key;
510
+ }
511
+ interface SmartCrudPrependField<T extends SmartCrudRecord, Name extends string = string> {
512
+ kind: 'prepend';
513
+ field: SmartCrudManualField<T, Name>;
514
+ }
515
+ interface SmartCrudAppendField<T extends SmartCrudRecord, Name extends string = string> {
516
+ kind: 'append';
517
+ field: SmartCrudManualField<T, Name>;
518
+ }
519
+ type SmartCrudHydraFieldDirective<T extends SmartCrudRecord> = SmartCrudOverrideField<T> | SmartCrudRemoveField<T> | SmartCrudPrependField<T> | SmartCrudAppendField<T>;
520
+ interface SmartCrudHydraFieldContract<T extends SmartCrudRecord> {
521
+ source: 'hydra';
522
+ strategy: 'augment';
523
+ directives: readonly SmartCrudHydraFieldDirective<T>[];
524
+ }
525
+ interface SmartCrudManualFieldContract<T extends SmartCrudRecord> {
526
+ source: 'manual';
527
+ strategy: 'replace';
528
+ fields: readonly SmartCrudManualField<T>[];
529
+ }
530
+ type SmartCrudFieldContract<T extends SmartCrudRecord> = SmartCrudHydraFieldContract<T> | SmartCrudManualFieldContract<T>;
531
+ declare function defineFields<T extends SmartCrudRecord>(contract: SmartCrudHydraFieldContract<T>): SmartCrudHydraFieldContract<T>;
532
+ declare function defineFields<T extends SmartCrudRecord>(contract: SmartCrudManualFieldContract<T>): SmartCrudManualFieldContract<T>;
533
+ declare const defineFieldContract: typeof defineFields;
534
+ //#endregion
535
+ //#region packages/crud/adapter/BackendAdapter.d.ts
536
+ /**
537
+ * Strategy object that abstracts backend-specific conventions from the CRUD engine.
538
+ *
539
+ * The engine ships with two built-in adapters:
540
+ * - `HydraAdapter` — for API Platform / JSON-LD backends (default)
541
+ * - `RestAdapter` — for plain OpenAPI / REST backends
542
+ *
543
+ * Provide a custom implementation on `ResourceConfig.adapter` to support any other backend.
544
+ */
545
+ interface BackendAdapter {
546
+ /**
547
+ * Extract the unique identifier from a data record.
548
+ * Used by the grid to identify rows for edit/delete actions.
549
+ *
550
+ * @param record - The data record returned by the API.
551
+ * @param idField - The name of the identity field declared in the field list.
552
+ */
553
+ getRowId(record: DataRecord$1, idField: string): string | number;
554
+ /**
555
+ * Build the URL for a single-item operation (PATCH / DELETE).
556
+ *
557
+ * @param baseUrl - The collection URL from ResourceConfig.apiUrl.
558
+ * @param id - The value returned by getRowId().
559
+ */
560
+ buildItemUrl(baseUrl: string, id: string | number): string;
561
+ /**
562
+ * Serialize a single entity field value for API submission (POST / PATCH body).
563
+ *
564
+ * @param field - The ENTITY field definition.
565
+ * @param rawValue - The raw value stored in the form (object, IRI string, or scalar id).
566
+ * @returns The serialized value to place in the request body, or undefined to omit the field.
567
+ */
568
+ serializeEntityRef(field: Field, rawValue: unknown): unknown;
569
+ /**
570
+ * Normalize an entity field value received from the API into the scalar key
571
+ * expected by the form's select editor.
572
+ *
573
+ * @param rawValue - The raw value in the API response (IRI string, nested object, or scalar).
574
+ * @param field - The ENTITY field definition.
575
+ * @returns The normalized scalar key (e.g. id number, IRI string, or the object unchanged for inline display).
576
+ */
577
+ normalizeEntityValue(rawValue: unknown, field: Field): unknown;
578
+ /**
579
+ * Extract the display key from an option record for entity select fields.
580
+ * Used when matching a stored value against a list of loaded options.
581
+ *
582
+ * @param item - An option record from the remote data source.
583
+ * @param field - The ENTITY field definition.
584
+ */
585
+ getEntityOptionKey(item: DataRecord$1, field: Field): unknown;
586
+ /**
587
+ * Parse the collection response body into an items array and total count.
588
+ * Used by the grid data source.
589
+ *
590
+ * @param response - The raw API response body.
591
+ */
592
+ parseListResponse(response: unknown): {
593
+ items: DataRecord$1[];
594
+ total: number;
595
+ };
596
+ /**
597
+ * Synthesize a canonical IRI / key for an entity object that arrived without one.
598
+ * Called during form data normalization when the object lacks the expected identity key.
599
+ * Return undefined if synthesis is not possible.
600
+ *
601
+ * @param field - The ENTITY field definition.
602
+ * @param entityValue - The entity object from the API response.
603
+ */
604
+ synthesizeEntityKey(field: Field, entityValue: FormDataRecord): string | undefined;
605
+ }
606
+ //#endregion
607
+ //#region packages/crud/crud/ResourceConfig.d.ts
608
+ /**
609
+ * URL-based deep-linking and filter sync configuration for SmartCrudPage.
610
+ * All fields are optional — if `routing` is absent, no URL behaviour is applied.
611
+ */
612
+ interface ResourceRouting {
613
+ /**
614
+ * URL param name for deep-linking a specific record.
615
+ * e.g. `routeParam: 'id'` → `/products/42` opens record 42 in the edit dialog
616
+ * → `/products/new` opens the add dialog
617
+ */
618
+ routeParam?: string;
619
+ /**
620
+ * When true, grid filter state is synced to URL query params.
621
+ * e.g. `?name=foo&status=active`
622
+ */
623
+ syncFiltersToUrl?: boolean;
624
+ }
625
+ /** Raw permission spec: each entry may be a static boolean or a zero-arg callable. */
626
+ interface ResourcePermissions {
627
+ canAdd?: boolean | (() => boolean);
628
+ canEdit?: boolean | (() => boolean);
629
+ canView?: boolean | (() => boolean);
630
+ canDelete?: boolean | (() => boolean);
631
+ canExport?: boolean | (() => boolean);
632
+ canBulkDelete?: boolean | (() => boolean);
633
+ }
634
+ type ResourceToolbarActionVariant = string;
635
+ interface ResourceToolbarAction {
636
+ key?: string;
637
+ text: string;
638
+ icon?: string;
639
+ hint?: string;
640
+ type?: ResourceToolbarActionVariant;
641
+ group?: string;
642
+ groupLabel?: string;
643
+ permission?: string;
644
+ visible?: boolean;
645
+ disabled?: boolean;
646
+ onClick?: () => void;
647
+ }
648
+ type ResourceRowActions<T extends DataRecord$1 = DataRecord$1> = ResourceToolbarAction[] | ((row: T) => ResourceToolbarAction[]);
649
+ interface ResourceToolbarItems {
650
+ primary?: ResourceToolbarAction[];
651
+ selection?: ResourceToolbarAction[];
652
+ utility?: ResourceToolbarAction[];
653
+ showRefresh?: boolean;
654
+ }
655
+ interface ResourceToolbarContext<T extends DataRecord$1 = DataRecord$1> {
656
+ resource: ResourceConfig<T>;
657
+ selectedRow: T | undefined;
658
+ selectedRows: T[];
659
+ gridRef: RefObject<GridHandle | null>;
660
+ formRef: RefObject<FormHandle | null>;
661
+ events: FormEventNames;
662
+ emit: <P>(name: string, payload?: P) => void;
663
+ }
664
+ type ResourceToolbar<T extends DataRecord$1 = DataRecord$1> = ResourceToolbarItems | ((context: ResourceToolbarContext<T>) => ResourceToolbarItems);
665
+ interface ResourceGridDetail {
666
+ url: string;
667
+ fields: Field[] | ((parentRow: DataRecord$1) => Field[]);
668
+ }
669
+ interface ResourceFormDetail {
670
+ url?: string;
671
+ fields: Field[];
672
+ propertyName?: string;
673
+ allowAdding?: boolean;
674
+ allowDeleting?: boolean;
675
+ allowUpdating?: boolean;
676
+ required?: boolean;
677
+ }
678
+ /**
679
+ * Where the create/edit form is rendered.
680
+ *
681
+ * - `'dialog'` (default) — modal centred over the grid. Best for short forms.
682
+ * - `'drawer'` — slide-in panel from the right (full-screen sheet on mobile).
683
+ * Grid stays visible — user can reference other rows while editing.
684
+ * - `'page'` — full route. The grid is replaced by the form; Save/Cancel
685
+ * navigate back to the list URL. Requires the route to accept `:id?`.
686
+ * Use the `crudRoute()` helper to wire `/<resource>` and `/<resource>/:id?`
687
+ * in one call.
688
+ */
689
+ type CrudViewMode = 'dialog' | 'drawer' | 'page';
690
+ interface CrudViewModeConfig {
691
+ mode: CrudViewMode;
692
+ /**
693
+ * Drawer size token — maps to a library width preset (`sm` 480, `md` 640,
694
+ * `lg` 880, `xl` 1120). Ignored when `drawerWidth` is set.
695
+ */
696
+ drawerSize?: CrudDrawerSize;
697
+ /** Explicit drawer width override. Takes priority over `drawerSize`. */
698
+ drawerWidth?: number | string;
699
+ /** Side the drawer slides in from. Default: `'right'`. */
700
+ drawerSide?: 'right' | 'left';
701
+ }
702
+ /** Contextual empty state shown when the grid has no rows. */
703
+ interface ResourceEmptyState {
704
+ title?: string;
705
+ description?: string;
706
+ /** Phosphor icon name without the "ph-" prefix. */
707
+ icon?: string;
708
+ variant?: 'default' | 'danger' | 'warning' | 'success';
709
+ }
710
+ interface ResourceConfig<T extends DataRecord$1 = DataRecord$1> {
711
+ id: string;
712
+ title: string;
713
+ apiUrl: string;
714
+ /**
715
+ * Backend adapter that controls how the engine interacts with the API.
716
+ * - `HydraAdapter` (default) — API Platform / JSON-LD + Hydra backends.
717
+ * - `RestAdapter` — plain OpenAPI / REST backends with numeric or UUID ids.
718
+ * - Provide a custom implementation for any other convention.
719
+ */
720
+ adapter?: BackendAdapter;
721
+ /**
722
+ * Manual field definitions for this resource.
723
+ * Omit (or pass an empty array) to let SmartCrudPage auto-infer fields from
724
+ * the Hydra/OpenAPI schema. Prefer `fieldContract` for augmenting inferred fields.
725
+ */
726
+ fields?: Field[] | FieldDef<T>[];
727
+ /**
728
+ * Form-only field definitions. When set, the grid uses `fields` and the
729
+ * create/edit form uses `formFields` — avoids re-fetching the grid on every
730
+ * reactive form rule evaluation (e.g. visibleWhen while typing).
731
+ */
732
+ formFields?: Field[];
733
+ /**
734
+ * Canonical production field contract for SmartCrud.
735
+ * SmartCrud runtime treats this as authoritative over legacy
736
+ * `fields` + `fieldOverrides` combinations whenever it is present.
737
+ */
738
+ fieldContract?: SmartCrudFieldContract<T>;
739
+ /**
740
+ * @deprecated Prefer callback/state coordination. This remains only as a legacy
741
+ * escape hatch for code that still listens to CRUD event names directly.
742
+ */
743
+ events?: FormEventNames;
744
+ /** Detail rows rendered in the main grid's expandable row panel. */
745
+ gridDetail?: ResourceGridDetail;
746
+ /** Detail rows rendered inside the create/edit form. */
747
+ formDetail?: ResourceFormDetail;
748
+ sort?: Array<{
749
+ selector: string;
750
+ desc: boolean;
751
+ }>;
752
+ filter?: FilterRule[];
753
+ mode?: 'normal' | 'minimal';
754
+ paging?: boolean;
755
+ /** Enables adapter-provided header filter dropdowns. Disabled by default; filter row remains the default. */
756
+ headerFilter?: boolean;
757
+ stateStoring?: boolean;
758
+ /** Fine-grained RBAC permission overrides. May be static or a callable that is
759
+ * evaluated at render time. */
760
+ permissions?: ResourcePermissions;
761
+ dialogWidth?: number;
762
+ dialogHeight?: number;
763
+ /**
764
+ * Where the create/edit form is rendered. Defaults to `'dialog'`.
765
+ *
766
+ * Examples:
767
+ * viewMode: 'drawer'
768
+ * viewMode: { mode: 'drawer', drawerSize: 'lg' }
769
+ * viewMode: 'page'
770
+ */
771
+ viewMode?: CrudViewMode | CrudViewModeConfig;
772
+ format?: 'json' | 'multipart';
773
+ toolbar?: ResourceToolbar<T>;
774
+ rowActions?: ResourceRowActions<T>;
775
+ onSaveSuccess?: (response: T) => void;
776
+ onSaveError?: (error?: unknown) => void;
777
+ onDeleteSuccess?: (response: T) => void;
778
+ onDeleteError?: (error?: unknown) => void;
779
+ /** Bulk actions rendered in the bulk toolbar when rows are selected. */
780
+ bulkActions?: BulkAction[];
781
+ /**
782
+ * Grid editing mode. Inline modes are interpreted by the active grid adapter.
783
+ * - `'popup'` (default) opens the resource dialog and form.
784
+ * - `'row'` | `'cell'` | `'batch'` enable inline editing when supported.
785
+ */
786
+ editMode?: 'popup' | 'row' | 'cell' | 'batch';
787
+ /** Optional layout descriptor for the dialog form: tabs or collapsible sections. */
788
+ formLayout?: FormLayout;
789
+ /** Named column visibility presets. When defined, a preset selector is shown in the toolbar. */
790
+ columnPresets?: ColumnPreset[];
791
+ /** Key of the preset to activate by default (overridden by any localStorage value). */
792
+ defaultPreset?: string;
793
+ /** Custom empty state when the grid has no rows. Falls back to the generic no-records message. */
794
+ emptyState?: ResourceEmptyState;
795
+ /** Optional audit trail configuration. When enabled, shows a "Historial" button and panel. */
796
+ auditTrail?: AuditTrailConfig;
797
+ /** Optional URL routing configuration — enables deep-linking and filter sync. */
798
+ routing?: ResourceRouting;
799
+ /**
800
+ * Called whenever a detail-grid row is added, updated, or removed.
801
+ * Use this to recompute header-form fields that depend on detail data
802
+ * (e.g., recalculating a `total` field from line items).
803
+ *
804
+ * @param formRef - ref to the form handle (call `formRef.current?.setFieldValue(...)` etc.)
805
+ */
806
+ onDetailRowsChanged?: (formRef: RefObject<FormHandle | null>) => void;
807
+ /**
808
+ * Enable or disable real-time Mercure subscription for this resource.
809
+ *
810
+ * - `true` (default): `SmartCrudPage` opens an SSE subscription to the Mercure hub
811
+ * and refreshes the grid automatically when another session modifies the resource.
812
+ * - `false`: disables the Mercure subscription for this resource. The grid still
813
+ * refreshes via the existing RxJS event bus for operations in the same session.
814
+ *
815
+ * Has no effect if the Mercure hub URL has not been discovered (graceful degradation).
816
+ */
817
+ mercure?: boolean;
818
+ /**
819
+ * Internal: HTTP methods inferred from `hydra:supportedOperation` in the API doc.
820
+ * Populated automatically by SmartCrudPage from useResourceSchema.
821
+ * Do NOT set this manually — it is overridden by any explicit `allowX` / `permissions` config.
822
+ * e.g. ['GET', 'POST', 'PATCH', 'DELETE']
823
+ */
824
+ _supportedOperations?: string[];
825
+ }
826
+ //#endregion
827
+ //#region packages/crud/crud/defineResource.d.ts
828
+ /** Zero config — `id` and `title` derived from the URL. */
829
+ declare function defineResource(apiUrl: string): ResourceConfig;
830
+ /**
831
+ * URL + partial overrides (canonical form).
832
+ * Pass `mercure: false` to disable the real-time Mercure subscription.
833
+ */
834
+ declare function defineResource<T extends DataRecord$1>(apiUrl: string, overrides: Partial<Omit<ResourceConfig<T>, 'apiUrl'>> & {
835
+ id?: string;
836
+ }): ResourceConfig<T>;
837
+ //#endregion
838
+ //#region packages/crud/crud/CrudPage.d.ts
839
+ interface CrudPageProps<T extends DataRecord$1 = DataRecord$1> {
840
+ resource: ResourceConfig<T>;
841
+ /**
842
+ * Called whenever any form field value changes.
843
+ * Receives a snapshot of the full current form data object.
844
+ * Wire this to SmartCrudPage's formData state for reactive rule evaluation.
845
+ */
846
+ onFormDataChange?: (data: FormDataRecord) => void;
847
+ /**
848
+ * When provided, open the edit dialog for this record on mount.
849
+ * Enables URL deep-linking (e.g. /products/42 → edit record 42).
850
+ * Defaults to null — existing behaviour unchanged when omitted.
851
+ */
852
+ initialRecordId?: string | number | null;
853
+ /**
854
+ * When true, open the add dialog on mount.
855
+ * Enables URL deep-linking (e.g. /products/new → open add dialog).
856
+ * Defaults to false — existing behaviour unchanged when omitted.
857
+ */
858
+ initialIsNew?: boolean;
859
+ computedValues?: FormDataRecord;
860
+ initialFilters?: Record<string, string>;
861
+ onFiltersChange?: (filters: Record<string, string>) => void;
862
+ /**
863
+ * Optional external form ref. When provided, CrudPage uses it instead of
864
+ * creating an internal one — allows the parent to call setFieldValue /
865
+ * getFieldValue on the active dialog form (e.g. for field observers).
866
+ */
867
+ formRef?: React.RefObject<FormHandle | null>;
868
+ /**
869
+ * Called whenever grid row selection changes, after internal selection state
870
+ * is updated. Receives the full selected row objects.
871
+ */
872
+ onSelectionChanged?: (rows: DataRecord$1[]) => void;
873
+ /** Disables the edit action on every grid row (passed through to DataGridView). */
874
+ editDisabled?: boolean;
875
+ /** Disables the delete action on every grid row (passed through to DataGridView). */
876
+ deleteDisabled?: boolean;
877
+ /** External ref forwarded to the DataGridView — allows the parent to call
878
+ * showLoading / hideLoading / refresh / getSelectedRow imperatively. */
879
+ gridRef?: React.RefObject<GridHandle | null>;
880
+ onOperationChange?: (operation: SmartCrudOperation | null) => void;
881
+ }
882
+ /**
883
+ * Public export — wraps CrudPageInner in its own DialogStoreProvider so that
884
+ * existing pages do not need to add a provider themselves.
885
+ */
886
+ declare const CrudPage: <T extends DataRecord$1 = DataRecord$1>({
887
+ resource,
888
+ onFormDataChange,
889
+ initialRecordId,
890
+ initialIsNew,
891
+ computedValues,
892
+ initialFilters,
893
+ onFiltersChange,
894
+ formRef,
895
+ onSelectionChanged,
896
+ editDisabled,
897
+ deleteDisabled,
898
+ gridRef,
899
+ onOperationChange
900
+ }: CrudPageProps<T>) => React.JSX.Element;
901
+ //#endregion
902
+ //#region packages/crud/crud/resolveSmartCrudFields.d.ts
903
+ type FieldOverride = Partial<Field> & {
904
+ key: string;
905
+ };
906
+ //#endregion
907
+ //#region packages/crud/crud/SmartCrudPage.d.ts
908
+ interface SmartCrudPageProps<T extends DataRecord$1 = DataRecord$1> {
909
+ resource: ResourceConfig<T>;
910
+ /**
911
+ * @deprecated Use `resource.fieldContract` (defineFieldContract) instead.
912
+ * Per-field overrides applied on top of auto-inferred Hydra fields.
913
+ * Ignored when `resource.fieldContract` is present.
914
+ */
915
+ fieldOverrides?: FieldOverride[];
916
+ /** External form ref forwarded to CrudPage — lets the parent call setFieldValue / getFieldValue. */
917
+ formRef?: RefObject<FormHandle | null>;
918
+ /** Called whenever grid row selection changes. Receives the full selected row objects. */
919
+ onSelectionChanged?: (rows: DataRecord$1[]) => void;
920
+ /** Disables the edit action on every grid row. */
921
+ editDisabled?: boolean;
922
+ /** Disables the delete action on every grid row. */
923
+ deleteDisabled?: boolean;
924
+ /** External ref forwarded to the DataGridView — allows the parent to call
925
+ * showLoading / hideLoading / refresh / getSelectedRow imperatively. */
926
+ gridRef?: RefObject<GridHandle | null>;
927
+ }
928
+ /**
929
+ * SmartCrudPage — wraps CrudPage with Hydra auto-discovery and declarative rules.
930
+ *
931
+ * ## Field resolution
932
+ * - If `resource.fields` is a non-empty array, it is used as-is (pass-through).
933
+ * - If `resource.fields` is empty / absent, fields are inferred from the Hydra
934
+ * API spec at `/api/docs.json` via `useResourceSchema`.
935
+ * - While the schema loads: renders a skeleton loader.
936
+ * - If the schema fetch errors: renders a user-visible error with a retry button.
937
+ *
938
+ * ## Declarative rules pipeline (via `useSmartCrudFields`)
939
+ * 1. `useFieldPermissions` — RBAC: hides or disables fields based on user roles
940
+ * 2. `useConditionalRules` — evaluates visibleWhen / disabledWhen / computed
941
+ * 3. `useDependsOn` — invalidates entity queries when dependency fields change
942
+ *
943
+ * ## Operation & form state (via `useSmartCrudOperation`)
944
+ * Manages `activeOperation` + `formData` as a unified state pair, synced
945
+ * from routing changes and the resource event bus (ADD/EDIT/CANCEL/SUCCESS).
946
+ *
947
+ * URL deep-linking is wired via `initialRecordId` / `initialIsNew` props on CrudPage.
948
+ */
949
+ declare function SmartCrudPage<T extends DataRecord$1 = DataRecord$1>({
950
+ resource,
951
+ fieldOverrides,
952
+ formRef,
953
+ onSelectionChanged,
954
+ editDisabled,
955
+ deleteDisabled,
956
+ gridRef
957
+ }: SmartCrudPageProps<T>): React.JSX.Element;
958
+ //#endregion
959
+ //#region packages/crud/crud/SmartCrudRolesContext.d.ts
960
+ declare function SmartCrudRolesProvider({
961
+ children,
962
+ roles
963
+ }: React.PropsWithChildren<{
964
+ roles?: string[];
965
+ }>): React.JSX.Element;
966
+ declare function useSmartCrudRoles(): string[];
967
+ //#endregion
968
+ //#region packages/crud/crud/AuditTrailPanel.d.ts
969
+ interface AuditTrailPanelProps {
970
+ url: string | null;
971
+ renderEntry?: (entry: AuditEntry) => ReactNode;
972
+ visible: boolean;
973
+ onClose: () => void;
974
+ }
975
+ declare function AuditTrailPanel({
976
+ url,
977
+ renderEntry,
978
+ visible,
979
+ onClose
980
+ }: AuditTrailPanelProps): React.JSX.Element | null;
981
+ //#endregion
982
+ //#region packages/crud/field/BaseFieldBuilder.d.ts
983
+ declare class BaseFieldBuilder<TRecord extends DataRecord$1 = DataRecord$1> {
984
+ protected _field: Field;
985
+ constructor(type: FieldType);
986
+ isIdentity(isIdentity: boolean): this;
987
+ col(col: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12): this;
988
+ layoutHint(value: FormLayoutHint): this;
989
+ cardRole(value: 'title' | 'primary' | 'secondary' | 'hidden'): this;
990
+ preferredColSpan(value: 6 | 12): this;
991
+ minColSpan(value: 6 | 12): this;
992
+ forceFullWidth(value?: boolean): this;
993
+ name(name: string): this;
994
+ label(label: string): this;
995
+ width(width: number | string): this;
996
+ height(height: number): this;
997
+ minWidth(minWidth: number): this;
998
+ align(align: 'left' | 'center' | 'right'): this;
999
+ sortable(sortable: boolean): this;
1000
+ filterable(filterable: boolean): this;
1001
+ hideable(hideable: boolean): this;
1002
+ validators(validators: ValidationRule[]): this;
1003
+ valueType(valueType: 'string' | 'number' | 'date' | 'boolean' | 'object' | 'datetime'): this;
1004
+ filterValue(filterValue: string | number | boolean | Date | null | undefined): this;
1005
+ data(data: DataRecord$1[]): this;
1006
+ format(format: string): this;
1007
+ formatter(formatter: (cell: GridCellContext<TRecord>) => React.ReactNode): this;
1008
+ itemFormatter(itemFormatter: ItemFormatterFn): this;
1009
+ visible(visible: boolean): this;
1010
+ defaultValue(defaultValue: string | number | boolean | Date | null | undefined | (() => unknown)): this;
1011
+ onChange(onChange: OnChangeFn): this;
1012
+ onSelect(onSelect: (e: unknown) => void): this;
1013
+ onClick(onClick: (e: unknown) => void): this;
1014
+ readonly(readonly: boolean): this;
1015
+ disabled(disabled: boolean): this;
1016
+ hidden(hidden: boolean): this;
1017
+ required(required: boolean): this;
1018
+ precision(value: number): this;
1019
+ accept(value: string | null | undefined): this;
1020
+ buttons(value: FieldButton[]): this;
1021
+ searchEnabled(value: boolean): this;
1022
+ searchExpr(value: string[]): this;
1023
+ helpText(value: string): this;
1024
+ contentRender(value: string | ((...args: unknown[]) => React.ReactNode) | null | undefined): this;
1025
+ visibleOnForm(value: boolean): this;
1026
+ autoSelectIfSingle(value: boolean): this;
1027
+ url(url: string): this;
1028
+ loadOptions(param: LoadOption[]): this;
1029
+ filters(filters: FilterRule[]): this;
1030
+ byKeyUrl(byKeyUrl: string): this;
1031
+ textField(textField: string): this;
1032
+ valueField(valueField: string): this;
1033
+ selectedFilterOperation(operation: '<' | '<=' | '<>' | '=' | '>' | '>=' | 'between' | 'contains' | 'endswith' | 'notcontains' | 'startswith'): this;
1034
+ sendAsString(value: boolean): this;
1035
+ multiple(value: boolean): this;
1036
+ maxLength(value: number): this;
1037
+ visibleWhen(fn: (formData: TRecord) => boolean): this;
1038
+ disabledWhen(fn: (formData: TRecord) => boolean): this;
1039
+ computed(fn: (formData: TRecord) => unknown): this;
1040
+ defaultWhen(fn: (formData: TRecord) => unknown): this;
1041
+ requiredWhen(fn: (formData: TRecord) => boolean): this;
1042
+ clearWhenHidden(value?: boolean): this;
1043
+ dependsOn(fields: string[]): this;
1044
+ permissions(perms: {
1045
+ visible?: string[];
1046
+ editable?: string[];
1047
+ }): this;
1048
+ build(): Field;
1049
+ }
1050
+ //#endregion
1051
+ //#region packages/crud/field/FieldBuilders.d.ts
1052
+ /**
1053
+ * Factory for the standard hidden identity field (type NONE, name 'id').
1054
+ *
1055
+ * Usage:
1056
+ * identityField().build()
1057
+ * identityField().required(true).build()
1058
+ * identityField().valueType('number').build()
1059
+ *
1060
+ * Defaults set automatically:
1061
+ * isIdentity(true), visible(false), required(true), name('id'), label('Id')
1062
+ */
1063
+ declare class IdentityFieldBuilder extends BaseFieldBuilder<DataRecord$1> {
1064
+ constructor();
1065
+ }
1066
+ declare function identityField(): IdentityFieldBuilder;
1067
+ /**
1068
+ * Builder for ENTITY (remote select) fields.
1069
+ *
1070
+ * Required constructor args: url, valueField, textField — the three properties
1071
+ * that are ALWAYS present on every ENTITY field in the codebase.
1072
+ *
1073
+ * Usage:
1074
+ * new EntityFieldBuilder('customers', 'id', 'businessName')
1075
+ * .label('Cliente')
1076
+ * .name('customer')
1077
+ * .formatter(cell => cell.value?.businessName)
1078
+ * .build()
1079
+ */
1080
+ declare class EntityFieldBuilder<TRecord extends DataRecord$1 = DataRecord$1> extends BaseFieldBuilder<TRecord> {
1081
+ constructor(url: string, valueField: string, textField: string);
1082
+ }
1083
+ declare function entityField<TRecord extends DataRecord$1 = DataRecord$1>(url: string, valueField: string, textField: string): EntityFieldBuilder<TRecord>;
1084
+ /**
1085
+ * Builder for CURRENCY fields.
1086
+ *
1087
+ * Defaults applied automatically:
1088
+ * sendAsString(true), align('right')
1089
+ *
1090
+ * Usage:
1091
+ * new CurrencyFieldBuilder()
1092
+ * .name('grandTotal')
1093
+ * .label('Total')
1094
+ * .formatter(cell => NumberUtils.formatCurrency(cell.value, cell.data?.currency))
1095
+ * .build()
1096
+ */
1097
+ declare class CurrencyFieldBuilder<TRecord extends DataRecord$1 = DataRecord$1> extends BaseFieldBuilder<TRecord> {
1098
+ constructor();
1099
+ }
1100
+ declare function currencyField<TRecord extends DataRecord$1 = DataRecord$1>(): CurrencyFieldBuilder<TRecord>;
1101
+ /**
1102
+ * Factory for generic file upload fields (FILE type).
1103
+ *
1104
+ * Uploads immediately to apiBaseUrl+'media' and submits the returned Media IRI.
1105
+ * Use `.accept()` to restrict mime types or extensions.
1106
+ *
1107
+ * Usage:
1108
+ * fileField('/api/')
1109
+ * .name('attachment')
1110
+ * .label('Adjunto')
1111
+ * .accept('application/pdf')
1112
+ * .build()
1113
+ */
1114
+ declare class FileFieldBuilder<TRecord extends DataRecord$1 = DataRecord$1> extends BaseFieldBuilder<TRecord> {
1115
+ constructor(apiBaseUrl: string);
1116
+ }
1117
+ declare function fileField<TRecord extends DataRecord$1 = DataRecord$1>(apiBaseUrl: string): FileFieldBuilder<TRecord>;
1118
+ /**
1119
+ * Preset for image uploads — shorthand over fileField with image defaults.
1120
+ *
1121
+ * Defaults: url=apiBaseUrl+'media', accept='image/*', align='center'
1122
+ */
1123
+ declare class ImageFieldBuilder<TRecord extends DataRecord$1 = DataRecord$1> extends FileFieldBuilder<TRecord> {
1124
+ constructor(apiBaseUrl: string);
1125
+ }
1126
+ declare function imageField<TRecord extends DataRecord$1 = DataRecord$1>(apiBaseUrl: string): ImageFieldBuilder<TRecord>;
1127
+ /**
1128
+ * Builder for DATE fields.
1129
+ *
1130
+ * Defaults applied automatically:
1131
+ * type = DATE, defaultValue = new Date()
1132
+ *
1133
+ * Usage:
1134
+ * dateField()
1135
+ * .name('issueDate')
1136
+ * .label('Fecha')
1137
+ * .formatter(cell => SharedUtils.dateFormatter(cell.value))
1138
+ * .build()
1139
+ */
1140
+ declare class DateFieldBuilder<TRecord extends DataRecord$1 = DataRecord$1> extends BaseFieldBuilder<TRecord> {
1141
+ constructor();
1142
+ }
1143
+ declare function dateField<TRecord extends DataRecord$1 = DataRecord$1>(): DateFieldBuilder<TRecord>;
1144
+ /**
1145
+ * Builder for DATETIME fields.
1146
+ *
1147
+ * Defaults applied automatically:
1148
+ * type = DATETIME, defaultValue = new Date()
1149
+ *
1150
+ * Usage:
1151
+ * datetimeField()
1152
+ * .name('openedAt')
1153
+ * .label('Apertura')
1154
+ * .formatter(cell => SharedUtils.dateTimeFormatter(cell.value))
1155
+ * .build()
1156
+ */
1157
+ declare class DateTimeFieldBuilder<TRecord extends DataRecord$1 = DataRecord$1> extends BaseFieldBuilder<TRecord> {
1158
+ constructor();
1159
+ }
1160
+ declare function datetimeField<TRecord extends DataRecord$1 = DataRecord$1>(): DateTimeFieldBuilder<TRecord>;
1161
+ /**
1162
+ * Builder for NUMBER fields.
1163
+ *
1164
+ * Usage:
1165
+ * numberField()
1166
+ * .name('quantity')
1167
+ * .label('Cantidad')
1168
+ * .precision(2)
1169
+ * .align('center')
1170
+ * .build()
1171
+ */
1172
+ declare class NumberFieldBuilder<TRecord extends DataRecord$1 = DataRecord$1> extends BaseFieldBuilder<TRecord> {
1173
+ constructor();
1174
+ }
1175
+ declare function numberField<TRecord extends DataRecord$1 = DataRecord$1>(): NumberFieldBuilder<TRecord>;
1176
+ /** A single option item for ENUM / SELECT fields. */
1177
+ type EnumOption = {
1178
+ value: string | number;
1179
+ text: string;
1180
+ };
1181
+ /**
1182
+ * Builder for ENUM (local select) fields.
1183
+ *
1184
+ * The options array is a required constructor arg — every ENUM field in the
1185
+ * codebase always provides it.
1186
+ *
1187
+ * Usage:
1188
+ * enumField([
1189
+ * { value: 'income', text: 'Ingreso' },
1190
+ * { value: 'expense', text: 'Egreso' },
1191
+ * ])
1192
+ * .name('type')
1193
+ * .label('Tipo')
1194
+ * .formatter(cell => cell.value === 'income' ? 'Ingreso' : 'Egreso')
1195
+ * .build()
1196
+ */
1197
+ declare class EnumFieldBuilder<TRecord extends DataRecord$1 = DataRecord$1> extends BaseFieldBuilder<TRecord> {
1198
+ constructor(options: EnumOption[]);
1199
+ }
1200
+ declare function enumField<TRecord extends DataRecord$1 = DataRecord$1>(options: EnumOption[]): EnumFieldBuilder<TRecord>;
1201
+ /**
1202
+ * Builder for TEXT (plain string input) fields.
1203
+ *
1204
+ * Usage:
1205
+ * textField()
1206
+ * .name('businessName')
1207
+ * .label('Razón social')
1208
+ * .required(true)
1209
+ * .build()
1210
+ */
1211
+ declare class TextFieldBuilder<TRecord extends DataRecord$1 = DataRecord$1> extends BaseFieldBuilder<TRecord> {
1212
+ constructor();
1213
+ }
1214
+ declare function textField<TRecord extends DataRecord$1 = DataRecord$1>(): TextFieldBuilder<TRecord>;
1215
+ /**
1216
+ * Builder for TEXTAREA (multi-line text) fields.
1217
+ *
1218
+ * Usage:
1219
+ * textareaField()
1220
+ * .name('note')
1221
+ * .label('Nota')
1222
+ * .build()
1223
+ */
1224
+ declare class TextareaFieldBuilder<TRecord extends DataRecord$1 = DataRecord$1> extends BaseFieldBuilder<TRecord> {
1225
+ constructor();
1226
+ }
1227
+ declare function textareaField<TRecord extends DataRecord$1 = DataRecord$1>(): TextareaFieldBuilder<TRecord>;
1228
+ /**
1229
+ * Builder for NONE (display-only, no editor) fields.
1230
+ *
1231
+ * Usage:
1232
+ * noneField()
1233
+ * .name('status')
1234
+ * .label('Status')
1235
+ * .formatter(cell => statusFormatter(cell.value))
1236
+ * .build()
1237
+ */
1238
+ declare class NoneFieldBuilder<TRecord extends DataRecord$1 = DataRecord$1> extends BaseFieldBuilder<TRecord> {
1239
+ constructor();
1240
+ }
1241
+ declare function noneField<TRecord extends DataRecord$1 = DataRecord$1>(): NoneFieldBuilder<TRecord>;
1242
+ /**
1243
+ * Builder for SWITCH (boolean toggle) fields.
1244
+ *
1245
+ * Usage:
1246
+ * switchField()
1247
+ * .name('active')
1248
+ * .label('Activo')
1249
+ * .defaultValue(true)
1250
+ * .formatter(SharedUtils.booleanFormatter)
1251
+ * .build()
1252
+ */
1253
+ declare class SwitchFieldBuilder<TRecord extends DataRecord$1 = DataRecord$1> extends BaseFieldBuilder<TRecord> {
1254
+ constructor();
1255
+ }
1256
+ declare function switchField<TRecord extends DataRecord$1 = DataRecord$1>(): SwitchFieldBuilder<TRecord>;
1257
+ /**
1258
+ * Builder for SELECT (local dropdown, value+text pairs) fields.
1259
+ *
1260
+ * Usage:
1261
+ * selectField()
1262
+ * .name('currency')
1263
+ * .label('Moneda')
1264
+ * .data([{ value: 'PEN', text: 'Soles' }, { value: 'USD', text: 'Dólares' }])
1265
+ * .build()
1266
+ */
1267
+ declare class SelectFieldBuilder<TRecord extends DataRecord$1 = DataRecord$1> extends BaseFieldBuilder<TRecord> {
1268
+ constructor();
1269
+ }
1270
+ declare function selectField<TRecord extends DataRecord$1 = DataRecord$1>(): SelectFieldBuilder<TRecord>;
1271
+ /**
1272
+ * Builder for CHECKBOX (boolean check) fields.
1273
+ *
1274
+ * Usage:
1275
+ * checkboxField()
1276
+ * .name('emitInvoice')
1277
+ * .label('Emitir comprobante')
1278
+ * .defaultValue(false)
1279
+ * .build()
1280
+ */
1281
+ declare class CheckboxFieldBuilder<TRecord extends DataRecord$1 = DataRecord$1> extends BaseFieldBuilder<TRecord> {
1282
+ constructor();
1283
+ }
1284
+ declare function checkboxField<TRecord extends DataRecord$1 = DataRecord$1>(): CheckboxFieldBuilder<TRecord>;
1285
+ /**
1286
+ * Builder for PASSWORD (masked text input) fields.
1287
+ *
1288
+ * Usage:
1289
+ * passwordField()
1290
+ * .name('password')
1291
+ * .label('Contraseña')
1292
+ * .required(true)
1293
+ * .build()
1294
+ */
1295
+ declare class PasswordFieldBuilder<TRecord extends DataRecord$1 = DataRecord$1> extends BaseFieldBuilder<TRecord> {
1296
+ constructor();
1297
+ }
1298
+ declare function passwordField<TRecord extends DataRecord$1 = DataRecord$1>(): PasswordFieldBuilder<TRecord>;
1299
+ //#endregion
1300
+ //#region packages/crud/field/FieldBuilder.d.ts
1301
+ declare class FieldBuilder<TRecord extends DataRecord$1 = DataRecord$1> {
1302
+ private readonly _field;
1303
+ constructor();
1304
+ isIdentity(isIdentity: boolean): FieldBuilder;
1305
+ type(type: FieldType): FieldBuilder;
1306
+ col(col: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12): FieldBuilder;
1307
+ layoutHint(value: FormLayoutHint): FieldBuilder;
1308
+ preferredColSpan(value: 6 | 12): FieldBuilder;
1309
+ minColSpan(value: 6 | 12): FieldBuilder;
1310
+ forceFullWidth(value?: boolean): FieldBuilder;
1311
+ name(name: string): FieldBuilder;
1312
+ label(label: string): FieldBuilder;
1313
+ width(width: number | string): FieldBuilder;
1314
+ height(height: number): FieldBuilder;
1315
+ minWidth(minWidth: number): FieldBuilder;
1316
+ align(align: 'left' | 'center' | 'right'): FieldBuilder;
1317
+ sortable(sortable: boolean): FieldBuilder;
1318
+ filterable(filterable: boolean): FieldBuilder;
1319
+ hideable(hideable: boolean): FieldBuilder;
1320
+ validators(validators: ValidationRule[]): FieldBuilder;
1321
+ url(url: string): FieldBuilder;
1322
+ loadOptions(param: LoadOption[]): FieldBuilder;
1323
+ filters(filters: FilterRule[]): FieldBuilder;
1324
+ byKeyUrl(byKeyUrl: string): FieldBuilder;
1325
+ textField(textField: string): FieldBuilder;
1326
+ valueField(valueField: string): FieldBuilder;
1327
+ valueType(valueType: 'string' | 'number' | 'date' | 'boolean' | 'object' | 'datetime'): FieldBuilder;
1328
+ selectedFilterOperation(operation: '<' | '<=' | '<>' | '=' | '>' | '>=' | 'between' | 'contains' | 'endswith' | 'notcontains' | 'startswith'): FieldBuilder;
1329
+ filterValue(filterValue: string | number | boolean | Date | null | undefined): FieldBuilder;
1330
+ data(data: DataRecord$1[]): FieldBuilder;
1331
+ format(format: string): FieldBuilder;
1332
+ formatter(formatter: (cell: GridCellContext<TRecord>) => React.ReactNode): FieldBuilder<TRecord>;
1333
+ itemFormatter(itemFormatter: ItemFormatterFn): FieldBuilder;
1334
+ visible(visible: boolean): FieldBuilder;
1335
+ defaultValue(defaultValue: string | number | boolean | Date | null | undefined | (() => unknown)): FieldBuilder;
1336
+ onChange(onChange: OnChangeFn): FieldBuilder;
1337
+ onSelect(onSelect: (e: unknown) => void): FieldBuilder;
1338
+ onClick(onClick: (e: unknown) => void): FieldBuilder;
1339
+ autoSelectIfSingle(value: boolean): FieldBuilder;
1340
+ readonly(readonly: boolean): FieldBuilder;
1341
+ disabled(disabled: boolean): FieldBuilder;
1342
+ hidden(hidden: boolean): FieldBuilder;
1343
+ required(required: boolean): FieldBuilder;
1344
+ precision(value: number): FieldBuilder;
1345
+ accept(value: string | null | undefined): FieldBuilder;
1346
+ buttons(value: FieldButton[]): FieldBuilder;
1347
+ searchEnabled(value: boolean): FieldBuilder;
1348
+ searchExpr(value: string[]): FieldBuilder;
1349
+ helpText(value: string): this;
1350
+ contentRender(value: string | ((...args: unknown[]) => React.ReactNode) | null | undefined): this;
1351
+ visibleOnForm(value: boolean): this;
1352
+ multiple(value: boolean): FieldBuilder;
1353
+ sendAsString(value: boolean): FieldBuilder;
1354
+ maxLength(value: number): FieldBuilder;
1355
+ visibleWhen(fn: (formData: TRecord) => boolean): FieldBuilder<TRecord>;
1356
+ disabledWhen(fn: (formData: TRecord) => boolean): FieldBuilder<TRecord>;
1357
+ computed(fn: (formData: TRecord) => unknown): FieldBuilder<TRecord>;
1358
+ defaultWhen(fn: (formData: TRecord) => unknown): FieldBuilder<TRecord>;
1359
+ requiredWhen(fn: (formData: TRecord) => boolean): FieldBuilder<TRecord>;
1360
+ clearWhenHidden(value?: boolean): FieldBuilder;
1361
+ dependsOn(fields: string[]): FieldBuilder;
1362
+ permissions(value: NonNullable<Field['permissions']>): FieldBuilder;
1363
+ build(): Field;
1364
+ }
1365
+ //#endregion
1366
+ //#region packages/crud/datagrid/DataGridEvents.d.ts
1367
+ declare const DATA_GRID_EVENTS: {
1368
+ SELECTION_CHANGED: string;
1369
+ TOOLBAR_EVENT: string;
1370
+ };
1371
+ //#endregion
1372
+ //#region packages/crud/summary/SummaryTypes.d.ts
1373
+ type SummaryType = 'sum' | 'count' | 'avg' | 'min' | 'max' | 'custom';
1374
+ type SummaryFormat = 'currency' | 'fixedPoint' | 'decimal' | 'percent' | Intl.NumberFormatOptions | ((value: unknown, item: SummaryItem) => string);
1375
+ interface SummaryCalculateContext {
1376
+ rows: DataRecord$1[];
1377
+ column?: string;
1378
+ item: SummaryItem;
1379
+ }
1380
+ interface SummaryTextContext {
1381
+ value: unknown;
1382
+ valueText: string;
1383
+ item: SummaryItem;
1384
+ }
1385
+ interface SummaryItem {
1386
+ /** Field/column name used to read values and align table-based summaries. */
1387
+ column?: string;
1388
+ /** Optional label shown by table footer renderers before the computed value. */
1389
+ label?: string;
1390
+ /** Built-in aggregation or a custom calculator for reusable domain summaries. */
1391
+ summaryType?: SummaryType | ((context: SummaryCalculateContext) => unknown);
1392
+ /** Template applied after value formatting, e.g. "Total: {0}". */
1393
+ displayFormat?: string;
1394
+ /** Number format preset, Intl.NumberFormatOptions, or custom formatter. */
1395
+ valueFormat?: SummaryFormat;
1396
+ /** Final text customization hook. */
1397
+ customizeText?: (cellInfo: SummaryTextContext) => string;
1398
+ /** Decimal digits used by number presets. Defaults to 2 for currency/fixedPoint. */
1399
+ precision?: number;
1400
+ /** ISO currency used by the currency preset. Defaults to PEN. */
1401
+ currency?: string;
1402
+ /** Intl currency display for the currency preset. Defaults to narrowSymbol. */
1403
+ currencyDisplay?: Intl.NumberFormatOptions['currencyDisplay'];
1404
+ /** Text alignment override for renderers that are not tied to a Field. */
1405
+ align?: 'left' | 'center' | 'right';
1406
+ }
1407
+ interface DetailSummaryOptions {
1408
+ items: SummaryItem[];
1409
+ /** Keeps the summary visible at the bottom of the scrollable detail table. */
1410
+ sticky?: boolean;
1411
+ /** Allows temporarily disabling summaries without changing the item list. */
1412
+ visible?: boolean;
1413
+ }
1414
+ //#endregion
1415
+ //#region packages/crud/summary/SummaryUtils.d.ts
1416
+ declare function computeSummaryValue(rows: DataRecord$1[], item: SummaryItem): unknown;
1417
+ declare function formatSummaryValue(value: unknown, item: SummaryItem): string;
1418
+ declare function resolveSummaryText(rows: DataRecord$1[], item: SummaryItem): string;
1419
+ //#endregion
1420
+ //#region packages/crud/datagrid/DataGridViewOptions.d.ts
1421
+ interface DataGridSelectionChangedEvent {
1422
+ selectedRowsData?: DataRecord$1[];
1423
+ }
1424
+ type DataGridSummaryItem = SummaryItem;
1425
+ interface DataGridViewOptions {
1426
+ id: string;
1427
+ title: string;
1428
+ url: string;
1429
+ detailUrl?: string;
1430
+ fields: Field[];
1431
+ detailFields?: Field[] | ((parentRow: DataRecord$1) => Field[]);
1432
+ toolbar?: ResourceToolbarItems;
1433
+ rowActions?: ResourceRowActions;
1434
+ /**
1435
+ * @deprecated Prefer onAdd/onEdit/onDelete callbacks. Events remain as a
1436
+ * legacy fallback for direct DataGridView consumers.
1437
+ */
1438
+ events?: DataGridEventNames;
1439
+ allowAdd?: boolean;
1440
+ allowEdit?: boolean;
1441
+ allowView?: boolean;
1442
+ allowDelete?: boolean;
1443
+ allowExport?: boolean;
1444
+ addDisabled?: boolean;
1445
+ editDisabled?: boolean;
1446
+ deleteDisabled?: boolean;
1447
+ summaryFields?: DataGridSummaryItem[];
1448
+ filter?: FilterRule[];
1449
+ sort?: Array<{
1450
+ selector: string;
1451
+ desc: boolean;
1452
+ }>;
1453
+ mode?: 'minimal' | 'normal' | 'full';
1454
+ paging?: boolean;
1455
+ pageSize?: number;
1456
+ hasBackButton?: boolean;
1457
+ columnsHidingEnabled?: boolean;
1458
+ stateStoringEnabled?: boolean;
1459
+ toolbarVisible?: boolean;
1460
+ selectionMode?: 'single' | 'multiple';
1461
+ inlineActions?: boolean;
1462
+ onBack?: () => void;
1463
+ onAdd?: () => void;
1464
+ onEdit?: (row: DataRecord$1) => void;
1465
+ onView?: (row: DataRecord$1) => void;
1466
+ onDelete?: (row: DataRecord$1) => void;
1467
+ onSelectionChanged?: (event: DataGridSelectionChangedEvent) => void;
1468
+ onRowPrepared?: (event: unknown) => void;
1469
+ onContentReady?: () => void;
1470
+ onFilterChange?: (filters: Record<string, string>) => void;
1471
+ filterRow?: boolean;
1472
+ headerFilter?: boolean;
1473
+ manualLoad?: boolean;
1474
+ beforeToolbar?: () => ReactNode;
1475
+ errorMessage?: string | null;
1476
+ onDismissError?: () => void;
1477
+ editMode?: 'popup' | 'row' | 'cell' | 'batch';
1478
+ visibleColumns?: string[] | null;
1479
+ /** Custom empty state when the grid has no rows. */
1480
+ emptyState?: ResourceEmptyState;
1481
+ /** Backend adapter controlling entity key lookup and display. Defaults to HydraAdapter. */
1482
+ adapter?: BackendAdapter;
1483
+ /** Alternate row background (zebra stripes). Defaults to false. */
1484
+ zebraRows?: boolean;
1485
+ }
1486
+ //#endregion
1487
+ //#region packages/crud/datagrid/NativeDataGridView.d.ts
1488
+ declare const NativeDataGridView: React.ForwardRefExoticComponent<DataGridViewOptions & React.RefAttributes<GridHandle>>;
1489
+ //#endregion
1490
+ //#region packages/crud/dialog/CrudDialogView.d.ts
1491
+ interface CrudDialogViewOptions {
1492
+ title?: string;
1493
+ width?: number;
1494
+ height?: number;
1495
+ maxHeight?: number;
1496
+ visible?: boolean;
1497
+ /**
1498
+ * @deprecated Prefer controlled open state plus onSave/onCancel callbacks.
1499
+ * Events remain as a legacy fallback for direct DialogView consumers.
1500
+ */
1501
+ events?: DialogEventNames;
1502
+ children?: React.ReactNode;
1503
+ positiveText?: string;
1504
+ negativeText?: string;
1505
+ footerVisible?: boolean;
1506
+ fitContent?: boolean;
1507
+ isOpen?: boolean;
1508
+ onClose?: () => void;
1509
+ onCancel?: () => void;
1510
+ onSave?: () => void;
1511
+ /** When false, only the cancel/close button is shown in the footer. */
1512
+ saveVisible?: boolean;
1513
+ }
1514
+ interface CrudDialogViewEvents {
1515
+ open: (title?: string) => void;
1516
+ close: () => void;
1517
+ }
1518
+ declare const CrudDialogView: React.ForwardRefExoticComponent<CrudDialogViewOptions & React.RefAttributes<CrudDialogViewEvents>>;
1519
+ //#endregion
1520
+ //#region packages/crud/view/CrudDrawerView.d.ts
1521
+ interface CrudDrawerViewOptions {
1522
+ title?: string;
1523
+ /** Token width: sm 480, md 640, lg 880, xl 1120. Ignored when `drawerWidth` is set. */
1524
+ drawerSize?: CrudDrawerSize;
1525
+ drawerWidth?: number | string;
1526
+ drawerSide?: 'right' | 'left';
1527
+ visible?: boolean;
1528
+ /**
1529
+ * @deprecated Prefer controlled open state plus onSave/onCancel callbacks.
1530
+ * Events remain as a legacy fallback for direct DrawerView consumers.
1531
+ */
1532
+ events?: DialogEventNames;
1533
+ children?: React.ReactNode;
1534
+ positiveText?: string;
1535
+ negativeText?: string;
1536
+ footerVisible?: boolean;
1537
+ isOpen?: boolean;
1538
+ onClose?: () => void;
1539
+ onCancel?: () => void;
1540
+ onSave?: () => void;
1541
+ }
1542
+ interface CrudDrawerViewEvents {
1543
+ open: (title?: string) => void;
1544
+ close: () => void;
1545
+ }
1546
+ /**
1547
+ * Event-driven drawer shell for legacy pages (SalePage, PriceListPage, etc.).
1548
+ * Mirrors `DialogView` API but slides in from the side so the grid stays visible.
1549
+ */
1550
+ declare const CrudDrawerView: React.ForwardRefExoticComponent<CrudDrawerViewOptions & React.RefAttributes<CrudDrawerViewEvents>>;
1551
+ //#endregion
1552
+ //#region packages/crud/view/CrudPageView.d.ts
1553
+ interface CrudPageViewOptions {
1554
+ title?: string;
1555
+ visible?: boolean;
1556
+ /**
1557
+ * Event-driven page shell for legacy pages that compose DataGridView + FormView directly.
1558
+ */
1559
+ events?: DialogEventNames;
1560
+ children?: React.ReactNode;
1561
+ isOpen?: boolean;
1562
+ onClose?: () => void;
1563
+ onCancel?: () => void;
1564
+ onSave?: () => void;
1565
+ }
1566
+ interface CrudPageViewEvents {
1567
+ open: (title?: string) => void;
1568
+ close: () => void;
1569
+ }
1570
+ declare const CrudPageView: React.ForwardRefExoticComponent<CrudPageViewOptions & React.RefAttributes<CrudPageViewEvents>>;
1571
+ //#endregion
1572
+ //#region packages/crud/form/FormViewOptions.d.ts
1573
+ interface FormViewOptions {
1574
+ className?: string;
1575
+ url: string;
1576
+ detailUrl?: string;
1577
+ fields: Field[];
1578
+ detailFields?: Field[];
1579
+ /** Optional summary footer for master-detail line tables. */
1580
+ detailSummary?: DetailSummaryOptions;
1581
+ detailPropertyName?: string;
1582
+ allowAdding?: boolean;
1583
+ allowUpdating?: boolean;
1584
+ allowDeleting?: boolean;
1585
+ /**
1586
+ * @deprecated Prefer operation/rowData plus the imperative FormHandle save/deleteRow methods.
1587
+ * Events remain as a legacy fallback for direct FormView consumers.
1588
+ */
1589
+ events?: FormEventNames;
1590
+ editable?: boolean;
1591
+ format?: 'json' | 'multipart';
1592
+ requiredDetail?: boolean;
1593
+ /** Backend adapter controlling entity serialization and URL building. Defaults to HydraAdapter. */
1594
+ adapter?: BackendAdapter;
1595
+ /** Called after a successful POST or PATCH. Receives the server response. */
1596
+ onSaveSuccess?: (response: unknown) => void;
1597
+ /** Called when POST or PATCH fails after HTTP error handling. */
1598
+ onSaveError?: (error?: unknown) => void;
1599
+ /** Called after a successful DELETE. */
1600
+ onDeleteSuccess?: (response: unknown) => void;
1601
+ /** Called when DELETE fails. */
1602
+ onDeleteError?: (error?: unknown) => void;
1603
+ /** Called whenever the loading state changes. */
1604
+ onLoadingChange?: (loading: boolean) => void;
1605
+ /** Optional layout descriptor for tabs or collapsible sections. */
1606
+ formLayout?: FormLayout;
1607
+ /** Presentation context used by auto column-span resolution. */
1608
+ presentationContext?: FormPresentationContext;
1609
+ /** Called whenever any form field value changes with a full form data snapshot. */
1610
+ onFieldDataChanged?: FormDataChangedHandler;
1611
+ /** Latest runtime-computed values pushed down by SmartCrudPage. */
1612
+ computedValues?: FormDataSnapshot;
1613
+ /** Callback/state-driven operation. When set, replaces ADD/EDIT event bootstrapping. */
1614
+ operation?: 'add' | 'edit' | null;
1615
+ /** Row payload used when operation changes. */
1616
+ rowData?: FormDataRecord | null;
1617
+ /** Increment to force re-applying the current operation and row payload. */
1618
+ operationVersion?: number;
1619
+ }
1620
+ //#endregion
1621
+ //#region packages/crud/form/NativeFormView.d.ts
1622
+ declare const NativeFormView: React.ForwardRefExoticComponent<FormViewOptions & React.RefAttributes<FormHandle>>;
1623
+ //#endregion
1624
+ //#region packages/crud/form/FormEvents.d.ts
1625
+ declare const FORM_EVENTS: {
1626
+ FIELD_CHANGED: string;
1627
+ ROW_ADDED: string;
1628
+ ROW_REMOVED: string;
1629
+ ROW_UPDATED: string;
1630
+ LOADING: string;
1631
+ LOADING_DETAIL: string;
1632
+ };
1633
+ //#endregion
1634
+ //#region packages/crud/crud/dialogStore.d.ts
1635
+ type DialogMode = 'add' | 'edit' | 'view';
1636
+ //#endregion
1637
+ //#region packages/crud/view/CrudFormShellProps.d.ts
1638
+ /**
1639
+ * Common API consumed by every CRUD form shell — Dialog, Drawer, Page.
1640
+ *
1641
+ * The shell is purely a presentational container around the `FormView` passed
1642
+ * in `children`. The orchestrator (`CrudPage`) owns the form lifecycle and
1643
+ * tells the shell only when to open/close.
1644
+ */
1645
+ interface CrudFormShellProps {
1646
+ /** Whether the form is currently being shown. */
1647
+ isOpen: boolean;
1648
+ /** add | edit | view — drives the title and (for some shells) intent UI. */
1649
+ mode: DialogMode;
1650
+ /** Localised title (already mapped from mode by the orchestrator). */
1651
+ title: string;
1652
+ /** Called when the user dismisses the shell (Escape, scrim, back nav). */
1653
+ onClose: () => void;
1654
+ /** Called when the user clicks the Cancel button. */
1655
+ onCancel: () => void;
1656
+ /** Called when the user clicks the Save button. */
1657
+ onSave: () => void;
1658
+ /** Override the default save button label. */
1659
+ saveLabel?: string;
1660
+ /** Dialog-only sizing. Drawer/Page shells ignore these. */
1661
+ width?: number;
1662
+ height?: number;
1663
+ /** Drawer-only sizing. */
1664
+ drawerWidth?: number | string;
1665
+ drawerSide?: 'right' | 'left';
1666
+ /**
1667
+ * Legacy event bus — passed through to keep the existing event-driven
1668
+ * close/loading behaviour working until consumers migrate to callbacks.
1669
+ */
1670
+ events?: DialogEventNames;
1671
+ /** The rendered `FormView`. */
1672
+ children: React.ReactNode;
1673
+ }
1674
+ //#endregion
1675
+ //#region packages/crud/view/viewMode.d.ts
1676
+ interface ResolvedViewMode {
1677
+ mode: CrudViewMode;
1678
+ drawerWidth: number | string;
1679
+ drawerSide: 'right' | 'left';
1680
+ /** Set when the resource used a size token instead of an explicit width. */
1681
+ drawerSize?: CrudDrawerSize;
1682
+ }
1683
+ /**
1684
+ * Normalises the `viewMode` field of `ResourceConfig` into a fully-resolved
1685
+ * object with defaults applied. Accepts the shorthand string form
1686
+ * (`'dialog' | 'drawer' | 'page'`) or the full config object.
1687
+ */
1688
+ declare function resolveViewMode(raw: CrudViewMode | CrudViewModeConfig | undefined): ResolvedViewMode;
1689
+ //#endregion
1690
+ //#region packages/crud/view/CrudFormShell.d.ts
1691
+ interface CrudFormShellPropsWithMode extends CrudFormShellProps {
1692
+ viewMode: ResolvedViewMode;
1693
+ }
1694
+ /**
1695
+ * Dispatches the form rendering to the correct shell based on the resource's
1696
+ * `viewMode`. All three shells consume the same `CrudFormShellProps`, so the
1697
+ * orchestrator (`CrudPage`) never has to know which shell is active.
1698
+ */
1699
+ declare const CrudFormShell: React.FC<CrudFormShellPropsWithMode>;
1700
+ //#endregion
1701
+ //#region packages/crud/view/CrudDialogShell.d.ts
1702
+ /**
1703
+ * Dialog form shell — preserves the legacy CRUD UX.
1704
+ * Thin wrapper around `CrudDialogView` so the orchestrator can stay shell-agnostic.
1705
+ */
1706
+ declare const CrudDialogShell: React.FC<CrudFormShellProps>;
1707
+ //#endregion
1708
+ //#region packages/crud/view/CrudDrawerShell.d.ts
1709
+ /**
1710
+ * Drawer form shell — slides in from the side and leaves the grid visible.
1711
+ *
1712
+ * Thin wrapper around the generic <Drawer> from @nubitio/ui that adds the
1713
+ * CRUD-specific footer (Cancel + Save buttons).
1714
+ */
1715
+ declare const CrudDrawerShell: React.FC<CrudFormShellProps>;
1716
+ //#endregion
1717
+ //#region packages/crud/view/CrudPageShell.d.ts
1718
+ /**
1719
+ * Page form shell — renders inline (no portal) and is expected to replace the
1720
+ * grid view via the `wrapper--with-page` CSS hook set by `CrudPage`.
1721
+ *
1722
+ * URL deep-linking is already wired through `useRouting`; the shell itself
1723
+ * does not navigate — it just exposes Back/Cancel/Save callbacks that the
1724
+ * orchestrator maps to `navigate()` calls or close-dialog dispatches.
1725
+ */
1726
+ declare const CrudPageShell: React.FC<CrudFormShellProps>;
1727
+ //#endregion
1728
+ //#region packages/crud/crud/ToolbarSelect.d.ts
1729
+ type ToolbarSelectOption = AppDropdownOption;
1730
+ interface ToolbarSelectProps {
1731
+ id: string;
1732
+ label: string;
1733
+ icon?: string;
1734
+ value: string;
1735
+ options: ToolbarSelectOption[];
1736
+ onChange: (value: string) => void;
1737
+ disabled?: boolean;
1738
+ }
1739
+ /** @deprecated Use `AppDropdown` with `variant="toolbar"` from `@nubitio/ui`. */
1740
+ declare function ToolbarSelect({
1741
+ id,
1742
+ label,
1743
+ icon,
1744
+ value,
1745
+ options,
1746
+ onChange,
1747
+ disabled
1748
+ }: ToolbarSelectProps): import("react").JSX.Element;
1749
+ //#endregion
1750
+ //#region packages/crud/crud/ColumnPresetSelector.d.ts
1751
+ interface ColumnPresetSelectorProps {
1752
+ resourceId: string;
1753
+ presets: ColumnPreset[];
1754
+ activePreset: string | null;
1755
+ onPresetChange: (key: string | null) => void;
1756
+ columnsLabel: string;
1757
+ allColumnsLabel: string;
1758
+ }
1759
+ declare function ColumnPresetSelector({
1760
+ resourceId,
1761
+ presets,
1762
+ activePreset,
1763
+ onPresetChange,
1764
+ columnsLabel,
1765
+ allColumnsLabel
1766
+ }: ColumnPresetSelectorProps): import("react").JSX.Element;
1767
+ //#endregion
1768
+ //#region packages/crud/crud/useColumnPreset.d.ts
1769
+ interface ColumnPresetState {
1770
+ activePreset: string | null;
1771
+ setPreset: (key: string | null) => void;
1772
+ visibleColumns: string[] | null;
1773
+ }
1774
+ declare function useColumnPreset(resource: ResourceConfig): ColumnPresetState;
1775
+ //#endregion
1776
+ //#region packages/crud/adapter/HydraAdapter.d.ts
1777
+ /**
1778
+ * Default backend adapter for API Platform / JSON-LD + Hydra backends.
1779
+ *
1780
+ * Conventions assumed:
1781
+ * - Records carry an `@id` IRI (e.g. `/api/users/5`) as their canonical identifier.
1782
+ * - Entity fields are serialized as IRI strings in POST/PATCH bodies.
1783
+ * - Collection responses follow the `hydra:member` / `hydra:totalItems` shape.
1784
+ * - `_iri` is a synthetic alias for `@id` used internally by the engine.
1785
+ */
1786
+ declare const HydraAdapter: BackendAdapter;
1787
+ //#endregion
1788
+ //#region packages/crud/adapter/RestAdapter.d.ts
1789
+ /**
1790
+ * Backend adapter for plain OpenAPI / REST backends.
1791
+ *
1792
+ * Conventions assumed:
1793
+ * - Records use a plain `id` field (numeric or string UUID) as their identifier.
1794
+ * - Entity fields are serialized as scalar IDs in POST/PATCH bodies.
1795
+ * - Collection responses are either a plain array or `{ items: [...], total: N }`.
1796
+ * Also handles `{ data: [...], total: N }` (common in Laravel / many REST frameworks).
1797
+ */
1798
+ declare const RestAdapter: BackendAdapter;
1799
+ //#endregion
1800
+ //#region packages/crud/schema/ResourceSchema.d.ts
1801
+ interface ResourceSchemaRequest {
1802
+ apiUrl: string;
1803
+ }
1804
+ interface ResourceSchemaResolution {
1805
+ fields: Field[];
1806
+ isLoading: boolean;
1807
+ error: Error | undefined;
1808
+ supportedOperations: string[];
1809
+ }
1810
+ interface ResourceSchemaResolver {
1811
+ useResourceSchema(request: ResourceSchemaRequest): ResourceSchemaResolution;
1812
+ }
1813
+ interface ResourceSchemaProviderProps {
1814
+ children: React.ReactNode;
1815
+ resolver: ResourceSchemaResolver;
1816
+ }
1817
+ declare function ResourceSchemaProvider({
1818
+ children,
1819
+ resolver
1820
+ }: ResourceSchemaProviderProps): React.JSX.Element;
1821
+ //#endregion
1822
+ //#region packages/crud/data/ResourceStore.d.ts
1823
+ type ResourceFilterDescriptor = unknown[];
1824
+ type ResourceSortDescriptor = {
1825
+ selector?: string;
1826
+ desc?: boolean;
1827
+ } | string;
1828
+ interface ResourceFilterRule {
1829
+ field: string;
1830
+ operator: string;
1831
+ value: string | number | boolean;
1832
+ }
1833
+ type ResourceLoadOption = Record<string, unknown>;
1834
+ type ResourceLoadOptions = DataRecord$1 & {
1835
+ filter?: ResourceFilterDescriptor;
1836
+ sort?: ResourceSortDescriptor[];
1837
+ appendData?: DataRecord$1[];
1838
+ prependData?: DataRecord$1[];
1839
+ searchExpr?: unknown;
1840
+ searchValue?: unknown;
1841
+ searchOperation?: unknown;
1842
+ };
1843
+ type ResourceLoadResult<TRecord extends DataRecord$1 = DataRecord$1> = GridData$1<TRecord>;
1844
+ interface ResourceStoreOptions {
1845
+ url: string;
1846
+ idField: string;
1847
+ byKeyUrl?: string | null;
1848
+ defaultFilterRules?: ResourceFilterDescriptor[];
1849
+ defaultSortRules?: ResourceSortDescriptor[];
1850
+ options?: ResourceLoadOption[];
1851
+ iriMode?: boolean;
1852
+ httpClient?: CoreHttpClient;
1853
+ }
1854
+ interface ResourceStore<TRecord extends DataRecord$1 = DataRecord$1> {
1855
+ load(options: ResourceLoadOptions): Promise<ResourceLoadResult<TRecord>>;
1856
+ byKey?(key: unknown): Promise<TRecord | null>;
1857
+ }
1858
+ type ResourceStoreFactory = (options: ResourceStoreOptions) => ResourceStore;
1859
+ interface ResourceStoreProviderProps {
1860
+ children: React.ReactNode;
1861
+ factory: ResourceStoreFactory;
1862
+ }
1863
+ declare function ResourceStoreProvider({
1864
+ children,
1865
+ factory
1866
+ }: ResourceStoreProviderProps): React.JSX.Element;
1867
+ declare function useResourceStoreFactory(): ResourceStoreFactory;
1868
+ //#endregion
1869
+ export { type AuditEntry, type AuditTrailConfig, AuditTrailPanel, type AuditTrailPanelProps, type BackendAdapter, type BulkAction, type ColSpan, type ColumnPreset, ColumnPresetSelector, type ColumnPresetState, CrudDialogShell, CrudDrawerShell, type CrudDrawerSize, type CrudDrawerViewEvents, type CrudDrawerViewOptions, CrudFormShell, type CrudFormShellProps, CrudPage, CrudPageShell, type CrudPageViewEvents, type CrudPageViewOptions, type CrudViewMode, type CrudViewModeConfig, DATA_GRID_EVENTS, DEFAULT_DRAWER_SIZE, DEFAULT_DRAWER_WIDTH, DRAWER_WIDTHS, type DataGridSelectionChangedEvent, type DataGridSummaryItem, NativeDataGridView as DataGridView, type DataGridViewOptions, type DataRecord, type DetailSummaryOptions, CrudDialogView as DialogView, type DrawerSize, CrudDrawerView as DrawerView, type EnumOption, FORM_EVENTS, type Field, FieldBuilder, type FieldColSpanContext, type FieldDef, type FieldOverride, FieldType, type FilterRule, type FormHandle, type FormLayout, type FormLayoutHint, type FormOnChangeFn, type FormPresentationContext, type FormPresentationMode, type FormSection, type FormTab, NativeFormView as FormView, type FormViewOptions, type FormatterFn, type GridCellContext, type GridData, type GridHandle, type GridOnChangeFn, HydraAdapter, type ItemFormatterFn, type LoadOption, type OnChangeFn, CrudPageView as PageView, type ResolvedViewMode, type ResourceConfig, type ResourceEmptyState, type ResourceFilterDescriptor, type ResourceFilterRule, type ResourceFormDetail, type ResourceGridDetail, type ResourceLoadOption, type ResourceLoadOptions, type ResourcePermissions, type ResourceRouting, type ResourceRowActions, ResourceSchemaProvider, type ResourceSchemaProviderProps, type ResourceSchemaResolution, type ResourceSchemaResolver, type ResourceSortDescriptor, type ResourceStore, type ResourceStoreFactory, type ResourceStoreOptions, ResourceStoreProvider, type ResourceStoreProviderProps, type ResourceToolbar, type ResourceToolbarAction, type ResourceToolbarActionVariant, type ResourceToolbarContext, type ResourceToolbarItems, RestAdapter, type SmartCrudFieldContract, type SmartCrudFieldOperation, type SmartCrudFieldPatch, type SmartCrudHydraFieldContract, type SmartCrudHydraFieldDirective, type SmartCrudManualField, type SmartCrudManualFieldContract, type SmartCrudOperation, SmartCrudPage, SmartCrudRolesProvider, type SummaryCalculateContext, type SummaryFormat, type SummaryItem, type SummaryTextContext, type SummaryType, ToolbarSelect, type ToolbarSelectOption, type ToolbarSelectProps, type ValidationRule, buildFieldColSpanContext, checkboxField, computeSummaryValue, createCrudEvents, currencyField, dateField, datetimeField, defineFieldContract, defineFields, defineResource, entityField, enumField, fileField, formatSummaryValue, identityField, imageField, isLongTextField, isShortField, noneField, numberField, parseDrawerWidthPx, passwordField, resolveDrawerLayoutBucket, resolveDrawerSize, resolveDrawerWidth, resolveFieldColSpan, resolveFieldsColSpans, resolveSummaryText, resolveViewMode, selectField, switchField, textField, textareaField, useColumnPreset, useResourceStoreFactory, useSmartCrudRoles, validateFieldContract };