@standardbeagle/edit-db 0.4.494 → 0.4.583

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/common/saved-objects.d.ts +40 -0
  2. package/dist/common/schema-queries.d.ts +1 -0
  3. package/dist/components/bulk-edit-dialog.d.ts +18 -0
  4. package/dist/components/content-viewer.d.ts +8 -1
  5. package/dist/components/data-table.d.ts +49 -2
  6. package/dist/components/detail-panel.d.ts +2 -2
  7. package/dist/components/export-button.d.ts +19 -0
  8. package/dist/components/export-button.test.d.ts +1 -0
  9. package/dist/components/filters/number-filter.d.ts +8 -1
  10. package/dist/components/fk-cell-popover.d.ts +5 -5
  11. package/dist/components/form-runner-host.d.ts +14 -0
  12. package/dist/components/form-runner.d.ts +43 -0
  13. package/dist/components/form-subform.d.ts +11 -0
  14. package/dist/components/form-subform.test.d.ts +0 -0
  15. package/dist/components/grouped-grid-summary.d.ts +17 -0
  16. package/dist/components/grouped-grid-summary.test.d.ts +0 -0
  17. package/dist/components/m2m-panel.d.ts +4 -5
  18. package/dist/components/ui/table.test.d.ts +1 -0
  19. package/dist/data-edit.d.ts +17 -4
  20. package/dist/data-panel.d.ts +0 -11
  21. package/dist/edit-db.css +1 -1
  22. package/dist/editor.d.ts +22 -1
  23. package/dist/editor.es.js +6822 -4695
  24. package/dist/editor.stories.d.ts +0 -1
  25. package/dist/editor.umd.cjs +41 -27
  26. package/dist/hooks/useColumnNav.d.ts +3 -3
  27. package/dist/hooks/useColumnSizingPersistence.d.ts +19 -0
  28. package/dist/hooks/useColumnVisibilityPersistence.d.ts +34 -0
  29. package/dist/hooks/useColumnVisibilityPersistence.test.d.ts +1 -0
  30. package/dist/hooks/useCompositeTableRef.d.ts +2 -2
  31. package/dist/hooks/useDataTable.d.ts +46 -5
  32. package/dist/hooks/useDebouncedCommit.test.d.ts +1 -0
  33. package/dist/hooks/useDeltaMutation.d.ts +20 -0
  34. package/dist/hooks/useDeltaMutation.test.d.ts +0 -0
  35. package/dist/hooks/useEditorConfig.d.ts +27 -0
  36. package/dist/hooks/useFitMode.d.ts +23 -0
  37. package/dist/hooks/useFitMode.test.d.ts +1 -0
  38. package/dist/hooks/usePanelSize.d.ts +28 -0
  39. package/dist/hooks/usePanelSize.test.d.ts +1 -0
  40. package/dist/hooks/usePath.d.ts +1 -0
  41. package/dist/hooks/useRowHoverActions.d.ts +26 -0
  42. package/dist/hooks/useSchema.d.ts +8 -2
  43. package/dist/hooks/useSchemaFilter.test.d.ts +1 -0
  44. package/dist/hooks/useTableExport.d.ts +13 -0
  45. package/dist/hooks/useTableMutation.d.ts +1 -4
  46. package/dist/hooks/useTableRef.d.ts +3 -3
  47. package/dist/hooks/useTableStats.d.ts +0 -24
  48. package/dist/index.d.ts +13 -1
  49. package/dist/lib/column-order.d.ts +17 -0
  50. package/dist/lib/column-order.test.d.ts +1 -0
  51. package/dist/lib/content-detect.d.ts +34 -0
  52. package/dist/lib/content-detect.sniff.test.d.ts +1 -0
  53. package/dist/lib/drill-stack.d.ts +19 -2
  54. package/dist/lib/export.d.ts +122 -0
  55. package/dist/lib/export.test.d.ts +1 -0
  56. package/dist/lib/field-validation.d.ts +16 -0
  57. package/dist/lib/fk.d.ts +13 -0
  58. package/dist/lib/form-definition.d.ts +57 -0
  59. package/dist/lib/form-definition.test.d.ts +1 -0
  60. package/dist/lib/form-runner-nav.d.ts +19 -0
  61. package/dist/lib/form-runner-nav.test.d.ts +1 -0
  62. package/dist/lib/form-subform.d.ts +12 -0
  63. package/dist/lib/form-subform.test.d.ts +1 -0
  64. package/dist/lib/form-widget.d.ts +36 -0
  65. package/dist/lib/form-widget.test.d.ts +1 -0
  66. package/dist/lib/format-value.d.ts +26 -0
  67. package/dist/lib/grid-grouping.d.ts +63 -0
  68. package/dist/lib/grid-grouping.test.d.ts +1 -0
  69. package/dist/lib/m2m.d.ts +26 -1
  70. package/dist/lib/mutation-payload.d.ts +37 -0
  71. package/dist/lib/mutation-payload.test.d.ts +1 -0
  72. package/dist/lib/query-builder.d.ts +116 -9
  73. package/dist/lib/row-id.d.ts +11 -0
  74. package/dist/lib/rows-by-pk-query.test.d.ts +1 -0
  75. package/dist/lib/scalar-types.d.ts +30 -0
  76. package/dist/lib/scalar-types.test.d.ts +1 -0
  77. package/dist/lib/table-action.d.ts +24 -0
  78. package/dist/{tableList.d.ts → table-list.d.ts} +1 -1
  79. package/dist/table-list.test.d.ts +0 -0
  80. package/dist/table-view.chart.test.d.ts +1 -0
  81. package/dist/table-view.d.ts +22 -0
  82. package/dist/table-view.test.d.ts +0 -0
  83. package/dist/types/schema.d.ts +45 -10
  84. package/package.json +2 -2
  85. package/dist/common/schema.d.ts +0 -2
  86. package/dist/data-data-table.d.ts +0 -17
  87. /package/dist/common/{schema.test.d.ts → saved-objects.test.d.ts} +0 -0
  88. /package/dist/{components/filters/use-debounced-commit.test.d.ts → common/schema-queries.test.d.ts} +0 -0
  89. /package/dist/{data-data-table.test.d.ts → components/bulk-edit-dialog.test.d.ts} +0 -0
  90. /package/dist/components/{table-dimensions.test.d.ts → content-viewer.test.d.ts} +0 -0
  91. /package/dist/{tableList.test.d.ts → components/form-runner.test.d.ts} +0 -0
  92. /package/dist/{components/filters/use-debounced-commit.d.ts → hooks/useDebouncedCommit.d.ts} +0 -0
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Client for the server's `/_saved-objects` REST endpoint (list/get/put/delete of
3
+ * user-authored objects). A small REST helper — the GraphQL fetcher seam is
4
+ * GraphQL-only, so this is a sibling transport, not an extension of it. Paths are
5
+ * resolved against `baseUrl` (default `''` = the page origin, like the other
6
+ * `/api/*` REST clients).
7
+ *
8
+ * Types are declared here to keep this shipped stack self-contained; they mirror
9
+ * the canonical contract in `@bifrostql/types` (`SavedObject`) and the C# source of
10
+ * truth in `BifrostQL.Core/SavedObjects`.
11
+ */
12
+ export type SavedObjectType = 'query' | 'form' | 'report' | 'dashboard';
13
+ export interface SavedObject {
14
+ id: string;
15
+ type: SavedObjectType;
16
+ name: string;
17
+ folder?: string;
18
+ definition: unknown;
19
+ version: number;
20
+ }
21
+ /** Thrown when a `put` is rejected because the object was modified concurrently (HTTP 409). */
22
+ export declare class SavedObjectConflictError extends Error {
23
+ constructor(message: string);
24
+ }
25
+ export interface SavedObjectsClient {
26
+ /**
27
+ * Lists stored objects, skipping any entry that does not parse so one corrupt
28
+ * record cannot take out the whole list. Skipped entries are reported through
29
+ * `onSkipped` rather than discarded silently — a caller that shows a list is
30
+ * expected to tell the user some of it could not be read.
31
+ */
32
+ list(type?: SavedObjectType, signal?: AbortSignal, onSkipped?: (skipped: number) => void): Promise<SavedObject[]>;
33
+ get(type: SavedObjectType, id: string, signal?: AbortSignal): Promise<SavedObject | null>;
34
+ put(object: SavedObject, signal?: AbortSignal): Promise<SavedObject>;
35
+ remove(type: SavedObjectType, id: string, signal?: AbortSignal): Promise<void>;
36
+ }
37
+ export declare const SAVED_OBJECTS_PATH = "/_saved-objects";
38
+ export declare function createSavedObjectsClient(baseUrl?: string): SavedObjectsClient;
39
+ /** Validates an unknown value as a {@link SavedObject}; returns null when it does not conform. */
40
+ export declare function parseSavedObject(value: unknown): SavedObject | null;
@@ -0,0 +1 @@
1
+ export declare const GET_DB_SCHEMA = "\nquery dbSchema {\n _dbSchema {\n dbName\n graphQlName\n labelColumn\n primaryKeys\n isEditable\n metadata {\n key\n value\n }\n columns {\n dbName\n graphQlName\n paramType\n dbType\n isPrimaryKey\n isIdentity\n isNullable\n isReadOnly\n isLargeValue\n maxLength\n minLength\n min\n max\n step\n precision\n scale\n pattern\n patternMessage\n inputType\n defaultValue\n enumValues\n enumLabels\n metadata {\n key\n value\n }\n }\n multiJoins {\n name\n fieldName\n sourceColumnNames\n destinationTable\n destinationColumnNames\n }\n singleJoins {\n name\n fieldName\n sourceColumnNames\n destinationTable\n destinationColumnNames\n }\n manyToManyJoins {\n name\n targetTable\n junctionTable\n junctionTargetField\n sourceColumnNames\n junctionSourceColumnNames\n junctionTargetColumnNames\n targetColumnNames\n hasPayload\n }\n indexes {\n name\n isUnique\n isClustered\n isPrimaryKey\n columns\n }\n }\n}";
@@ -0,0 +1,18 @@
1
+ import { Table } from '../types/schema';
2
+ import { PkFilter } from '../lib/row-id';
3
+ interface BulkEditDialogProps {
4
+ table: Table;
5
+ /** Primary-key filters of the selected rows (composite-safe, from pkFilterFor). */
6
+ pks: PkFilter[];
7
+ onClose: () => void;
8
+ }
9
+ /**
10
+ * Jira-style bulk edit: apply one shared set of field changes to every selected
11
+ * row, saved as ONE `delta: { updated }` document — one server transaction (a
12
+ * failure anywhere applies nothing) that rides the set-based bulk fast path at
13
+ * batch scale. Before saving, the selected rows are re-read fresh in a single
14
+ * query so echoed non-nullable columns reflect current server state (the grid's
15
+ * projection excludes large values and may be stale).
16
+ */
17
+ export declare function BulkEditDialog({ table, pks, onClose }: BulkEditDialogProps): import("react").JSX.Element;
18
+ export {};
@@ -2,6 +2,13 @@ interface ContentViewerProps {
2
2
  value: unknown;
3
3
  dbType?: string;
4
4
  onExpand?: () => void;
5
+ /**
6
+ * True when the column's value is deliberately NOT selected by the grid query
7
+ * (large-value/LOB columns, fetched on demand). A missing value then means
8
+ * "not fetched", which must not render as NULL — that would misreport real
9
+ * content as absent. Expanding fetches the actual value.
10
+ */
11
+ deferred?: boolean;
5
12
  }
6
- export declare function ContentViewer({ value, dbType, onExpand }: ContentViewerProps): import("react").JSX.Element;
13
+ export declare function ContentViewer({ value, dbType, onExpand, deferred }: ContentViewerProps): import("react").JSX.Element;
7
14
  export {};
@@ -1,5 +1,8 @@
1
1
  import { ColumnDef, ColumnFiltersState, SortingState } from '@tanstack/react-table';
2
+ import { ExportRunner } from '../lib/export';
2
3
  import { PkFilter } from '../lib/row-id';
4
+ import { Column } from '../types/schema';
5
+ import { GridGroupMemberRequest, GroupingRow, GroupingSort } from '../lib/grid-grouping';
3
6
  /**
4
7
  * Props for the DataTable component.
5
8
  * @interface DataTableProps
@@ -22,8 +25,14 @@ interface DataTableProps<TData> {
22
25
  sorting: SortingState;
23
26
  /** Active column filters */
24
27
  columnFilters: ColumnFiltersState;
25
- /** Whether data is currently loading */
28
+ /** Whether data is currently loading (no rows to show yet) */
26
29
  loading?: boolean;
30
+ /**
31
+ * Whether a page/sort/filter refresh is in flight while the previous rows
32
+ * stay on screen. `loading` covers only the no-rows-yet case; without this
33
+ * flag a slow page turn gives zero feedback and reads as a dead click.
34
+ */
35
+ fetching?: boolean;
27
36
  /** Enable row selection checkboxes */
28
37
  selectable?: boolean;
29
38
  /**
@@ -51,6 +60,21 @@ interface DataTableProps<TData> {
51
60
  onDeleteRow?: (pk: PkFilter) => void;
52
61
  /** Callback when deleting multiple selected rows */
53
62
  onDeleteSelected?: (pks: PkFilter[]) => void;
63
+ /** Bulk edit of the selected rows — one shared change set, one delta transaction. */
64
+ onBulkEditSelected?: (pks: PkFilter[]) => void;
65
+ /** Column ids editable INLINE: double-click a cell to edit; Enter/blur commits into the staged set, Escape cancels. */
66
+ inlineEditableColumns?: ReadonlySet<string>;
67
+ /** Column ids whose inline editor is a boolean toggle instead of a text input. */
68
+ inlineBooleanColumns?: ReadonlySet<string>;
69
+ /** Staged (unsaved) cell edits keyed by row id; rendered dirty and shown in place of the stored value. */
70
+ pendingEdits?: ReadonlyMap<string, Record<string, unknown>>;
71
+ /** Commits one edited cell into the staged set (owned by the caller so edits survive refetches). */
72
+ onCellCommit?: (rowId: string, columnId: string, value: unknown) => void;
73
+ /** Save/discard the whole staged set — rendered in the toolbar with the unsaved count. */
74
+ onSaveAllEdits?: () => void;
75
+ onDiscardAllEdits?: () => void;
76
+ /** True while the staged set is being saved; locks the toolbar buttons. */
77
+ savingEdits?: boolean;
54
78
  /**
55
79
  * Whether parent/child drill-down ("stacking") mode is active. When the
56
80
  * companion `onToggleStacking` is supplied, a graphical toggle renders next
@@ -60,6 +84,29 @@ interface DataTableProps<TData> {
60
84
  stackingEnabled?: boolean;
61
85
  /** Toggle stacking mode on/off. When omitted, the toggle is not rendered. */
62
86
  onToggleStacking?: (next: boolean) => void;
87
+ /**
88
+ * Full-result-set export runner (pages every matching row for the current
89
+ * filters/sort). When supplied, an Export control renders in the toolbar.
90
+ */
91
+ exportRows?: ExportRunner;
92
+ /** Total matching rows — drives the export's above-cap confirmation. */
93
+ totalRows?: number;
94
+ /** Opens a chart prefilled from this table and its schema-aware filters. */
95
+ onVisualize?: () => void;
96
+ /** Schema columns offered by the URL-backed server grouping selector. */
97
+ groupableColumns?: readonly Column[];
98
+ grouping?: {
99
+ column: Column;
100
+ sumColumn: Column | null;
101
+ rows: GroupingRow[];
102
+ loading: boolean;
103
+ error: Error | null;
104
+ sort: GroupingSort;
105
+ onSortChange: (sort: GroupingSort) => void;
106
+ memberRequest: (value: unknown) => GridGroupMemberRequest;
107
+ } | null;
108
+ onGroupingChange?: (columnName: string | null) => void;
109
+ onGroupingSumChange?: (columnName: string | null) => void;
63
110
  }
64
111
  /**
65
112
  * DataTable component - A comprehensive data table with sorting, filtering,
@@ -89,5 +136,5 @@ interface DataTableProps<TData> {
89
136
  * @param props - DataTable configuration props
90
137
  * @returns React element containing the data table interface
91
138
  */
92
- export declare function DataTable<TData>({ columns, data, tableName, pageCount, pageIndex, pageSize, sorting, columnFilters, loading, selectable, primaryKeys, selectedRowId, onRowSelect, onSortingChange, onColumnFiltersChange, onPageIndexChange, onPageSizeChange, onEditRow, onDeleteRow, onDeleteSelected, stackingEnabled, onToggleStacking, }: DataTableProps<TData>): import("react").JSX.Element;
139
+ export declare function DataTable<TData>({ columns, data, tableName, pageCount, pageIndex, pageSize, sorting, columnFilters, loading, fetching, selectable, primaryKeys, selectedRowId, onRowSelect, onSortingChange, onColumnFiltersChange, onPageIndexChange, onPageSizeChange, onEditRow, onDeleteRow, onDeleteSelected, onBulkEditSelected, inlineEditableColumns, inlineBooleanColumns, pendingEdits, onCellCommit, onSaveAllEdits, onDiscardAllEdits, savingEdits, stackingEnabled, onToggleStacking, exportRows, totalRows, onVisualize, groupableColumns, grouping, onGroupingChange, onGroupingSumChange, }: DataTableProps<TData>): import("react").JSX.Element;
93
140
  export {};
@@ -1,10 +1,10 @@
1
1
  import { Table } from '../types/schema';
2
- import { ColumnPanel } from '../data-panel';
2
+ import { DrillFrame } from '../lib/drill-stack';
3
3
  interface DetailPanelProps {
4
4
  parentTable: Table;
5
5
  selectedRowId: string;
6
6
  onClose?: () => void;
7
- onOpenColumn?: (panel: ColumnPanel) => void;
7
+ onOpenColumn?: (panel: DrillFrame) => void;
8
8
  }
9
9
  export declare function DetailPanel({ parentTable, selectedRowId, onClose, onOpenColumn }: DetailPanelProps): import("react").JSX.Element | null;
10
10
  export {};
@@ -0,0 +1,19 @@
1
+ import { ExportRunner } from '../lib/export';
2
+ interface ExportButtonProps {
3
+ /** Bound runner that pages the full filtered/sorted result set. */
4
+ exportRows: ExportRunner;
5
+ /** Total matching rows — drives the above-cap confirmation. */
6
+ total: number;
7
+ /** Base name for the downloaded file. */
8
+ tableName: string;
9
+ /** Above this many rows the export prompts for confirmation. */
10
+ rowCap?: number;
11
+ }
12
+ /**
13
+ * Toolbar control that exports the full result set through the shared export
14
+ * util. Above `rowCap` it confirms first; while running it swaps to a Cancel
15
+ * button that aborts paging (leaving no file). Cancellation is silent — no error
16
+ * toast — since the user asked for it.
17
+ */
18
+ export declare function ExportButton({ exportRows, total, tableName, rowCap, }: ExportButtonProps): import("react").JSX.Element;
19
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -2,6 +2,13 @@ import { Column } from '@tanstack/react-table';
2
2
  interface NumberFilterProps<TData, TValue> {
3
3
  column: Column<TData, TValue>;
4
4
  }
5
- export declare function parseNumeric(raw: string, isInt: boolean): number | null;
5
+ /**
6
+ * Validates the typed text and returns the value to filter by: the digits
7
+ * unchanged for a bigint/decimal column (a JS number would round them), otherwise
8
+ * a number. Null means the text is not (yet) a complete numeric literal, which the
9
+ * caller reads as "no filter". Thin wrapper over the shared classifier so the
10
+ * filter, the edit form and the write path all agree on what a column accepts.
11
+ */
12
+ export declare function parseNumeric(raw: string, paramType: string): number | string | null;
6
13
  export declare function NumberFilter<TData, TValue>({ column }: NumberFilterProps<TData, TValue>): import("react").JSX.Element | null;
7
14
  export {};
@@ -2,16 +2,16 @@ import { ReactNode } from 'react';
2
2
  import { Column, Join, Table } from '../types/schema';
3
3
  interface FkCellPopoverProps {
4
4
  tableName: string;
5
- recordId: string | number;
5
+ fkValue: string | number;
6
6
  /**
7
- * The column on `tableName` whose value is `recordId`. Callers pass the FK target
7
+ * The column on `tableName` whose value is `fkValue`. Callers pass the FK target
8
8
  * column from the join metadata (`destinationColumnNames[0]`). Using the target's
9
9
  * "primary key" column here is wrong for composite-PK and denormalized-FK targets.
10
10
  */
11
11
  filterColumn: string;
12
12
  /**
13
13
  * The full join descriptor. When the join is composite, the popover ignores
14
- * `recordId`/`filterColumn` and builds an `{and: [...]}` filter from every
14
+ * `fkValue`/`filterColumn` and builds an `{and: [...]}` filter from every
15
15
  * `sourceColumnNames` value on `sourceRow`. Single-FK callers can omit this.
16
16
  */
17
17
  join?: Join;
@@ -28,6 +28,6 @@ interface PreviewPlan {
28
28
  cacheKey: unknown;
29
29
  }
30
30
  /** Exported for tests: pure query-plan derivation with no React/query dependencies. */
31
- export declare function buildPreviewPlan(tableName: string, destTable: Table, previewColumns: Column[], join: Join | undefined, sourceRow: Record<string, unknown> | undefined, recordId: string | number, filterColumn: string): PreviewPlan | null;
32
- export declare function FkCellPopover({ tableName, recordId, filterColumn, join, sourceRow, children }: FkCellPopoverProps): import("react").JSX.Element;
31
+ export declare function buildPreviewPlan(tableName: string, destTable: Table, previewColumns: Column[], join: Join | undefined, sourceRow: Record<string, unknown> | undefined, fkValue: string | number, filterColumn: string): PreviewPlan | null;
32
+ export declare function FkCellPopover({ tableName, fkValue, filterColumn, join, sourceRow, children }: FkCellPopoverProps): import("react").JSX.Element;
33
33
  export {};
@@ -0,0 +1,14 @@
1
+ import { GraphQLFetcher } from '../common/fetcher';
2
+ import { FormDefinition } from '../lib/form-definition';
3
+ import { FieldWidgetHint } from '../lib/form-widget';
4
+ interface FormRunnerHostProps {
5
+ /** The GraphQL fetcher every read/write routes through (transport-agnostic). */
6
+ fetcher: GraphQLFetcher;
7
+ /** The saved form definition to render. */
8
+ definition: FormDefinition;
9
+ /** Optional app-metadata widget hints keyed by column name. */
10
+ fieldMetadata?: Record<string, FieldWidgetHint>;
11
+ onClose?: () => void;
12
+ }
13
+ export declare function FormRunnerHost({ fetcher, definition, fieldMetadata, onClose }: FormRunnerHostProps): import("react").JSX.Element;
14
+ export {};
@@ -0,0 +1,43 @@
1
+ import { SchemaContextValue, Table } from '../types/schema';
2
+ import { FormDefinition } from '../lib/form-definition';
3
+ import { FieldWidgetHint } from '../lib/form-widget';
4
+ /**
5
+ * Resolves the definition's bound table against the introspected schema. The
6
+ * builder may store a qualified "schema.name" while the schema keys on the
7
+ * GraphQL name, so match on either form. Returns undefined when the table is no
8
+ * longer in the published schema.
9
+ */
10
+ export declare function resolveDefinitionTable(schema: SchemaContextValue, tableId: string): Table | undefined;
11
+ interface FormRunnerViewProps {
12
+ table: Table;
13
+ definition: FormDefinition;
14
+ /** App-metadata widget hints keyed by column name (widget / visible / readOnly). */
15
+ fieldMetadata?: Record<string, FieldWidgetHint>;
16
+ onClose?: () => void;
17
+ schema?: SchemaContextValue;
18
+ /** Values fixed by a containing form when creating a related record. */
19
+ initialValues?: Record<string, unknown>;
20
+ /** Fields supplied by a containing form; retain them in mutations but do not render inputs. */
21
+ hiddenFields?: readonly string[];
22
+ /** Opens the runner directly in create mode for a related-record action. */
23
+ startInNewMode?: boolean;
24
+ /** Opens the runner on this row for a related-record edit action. */
25
+ initialPkRoute?: string;
26
+ }
27
+ /**
28
+ * The bound runtime for a resolved table. Split from {@link FormRunner} so it can
29
+ * be exercised directly with a `Table` and a fetcher, without a schema fetch.
30
+ */
31
+ export declare function FormRunnerView({ table, definition, fieldMetadata, onClose, schema, initialValues, hiddenFields, startInNewMode, initialPkRoute }: FormRunnerViewProps): import("react").JSX.Element;
32
+ interface FormRunnerProps {
33
+ definition: FormDefinition;
34
+ fieldMetadata?: Record<string, FieldWidgetHint>;
35
+ onClose?: () => void;
36
+ }
37
+ /**
38
+ * Top-level form runner: resolves the definition's table from the introspected
39
+ * schema, then hands off to {@link FormRunnerView}. Renders loading / error /
40
+ * not-found states so a stale definition cannot crash the tree.
41
+ */
42
+ export declare function FormRunner({ definition, fieldMetadata, onClose }: FormRunnerProps): import("react").JSX.Element;
43
+ export {};
@@ -0,0 +1,11 @@
1
+ import { Table } from '../types/schema';
2
+ import { FormSubform } from '../lib/form-definition';
3
+ interface Props {
4
+ parent: Table;
5
+ child: Table;
6
+ subform: FormSubform;
7
+ row: Record<string, unknown>;
8
+ }
9
+ /** Related child rows in a form. The selected parent values are always passed as GraphQL variables. */
10
+ export declare function FormSubformPanel({ parent, child, subform, row }: Props): import("react").JSX.Element;
11
+ export {};
File without changes
@@ -0,0 +1,17 @@
1
+ import { GridGroupMemberRequest, GroupingRow, GroupingSort } from '../lib/grid-grouping';
2
+ interface GroupedGridSummaryProps {
3
+ label: string;
4
+ rows: readonly GroupingRow[];
5
+ loading?: boolean;
6
+ error?: Error | null;
7
+ sumLabel?: string;
8
+ /** Uses the active grid page-size preference, not an unrelated constant. */
9
+ pageSize: number;
10
+ /** Aggregate bucket order; member rows retain the active flat-grid order. */
11
+ sort: GroupingSort;
12
+ onSortChange: (sort: GroupingSort) => void;
13
+ memberRequest: (value: unknown) => GridGroupMemberRequest;
14
+ }
15
+ /** Server aggregate groups with local group paging and one expandable, server-filtered member bucket. */
16
+ export declare function GroupedGridSummary({ label, rows, loading, error, sumLabel, pageSize, sort, onSortChange, memberRequest }: GroupedGridSummaryProps): import("react").JSX.Element;
17
+ export {};
File without changes
@@ -1,10 +1,9 @@
1
- import { ManyToManyJoin, Table } from '../types/schema';
2
- import { ColumnPanel } from '../data-panel';
1
+ import { ManyToManyJoin } from '../types/schema';
2
+ import { DrillFrame } from '../lib/drill-stack';
3
3
  interface M2mPanelProps {
4
- parentTable: Table;
5
4
  m2m: ManyToManyJoin;
6
5
  parentRowId: string;
7
- onOpenColumn?: (panel: ColumnPanel) => void;
6
+ onOpenColumn?: (panel: DrillFrame) => void;
8
7
  }
9
8
  /**
10
9
  * One detail tab for a many-to-many relationship. The junction is skipped for
@@ -13,5 +12,5 @@ interface M2mPanelProps {
13
12
  * (insert a junction row) and detached (delete the junction row by its primary
14
13
  * key).
15
14
  */
16
- export declare function M2mPanel({ parentTable, m2m, parentRowId, onOpenColumn }: M2mPanelProps): import("react").JSX.Element;
15
+ export declare function M2mPanel({ m2m, parentRowId, onOpenColumn }: M2mPanelProps): import("react").JSX.Element;
17
16
  export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,5 @@
1
1
  import { ReactElement } from 'react';
2
+ import { Column } from './types/schema';
2
3
  export declare const NONE_VALUE = "__none__";
3
4
  /**
4
5
  * Maps a form value to the Radix `<Select>` control value. Radix shows the
@@ -7,6 +8,18 @@ export declare const NONE_VALUE = "__none__";
7
8
  * indistinguishable from never having picked one.
8
9
  */
9
10
  export declare function selectControlValue(value: unknown, offersNone: boolean): string;
11
+ /**
12
+ * Radix's Select emits onValueChange('') when the item matching the current
13
+ * value UNMOUNTS — which happens legitimately here whenever an FK select swaps
14
+ * its fallback "raw key" item for the freshly-fetched window item, or the
15
+ * option window reloads. That emission is never a user action (a user picks a
16
+ * real value or the NONE_VALUE sentinel), but handled as one it silently
17
+ * cleared the stored FK to '' and the dialog showed the placeholder over a row
18
+ * that HAS a value — then Save failed "required". Drop it.
19
+ */
20
+ export declare function guardSelectClear(onChange: (val: string) => void): (val: string) => void;
21
+ export type FkRole = 'none' | 'anchor-single' | 'anchor-composite' | 'member-composite';
22
+ export declare function isFkOrEnumColumn(column: Column, fkRole: FkRole): boolean;
10
23
  /**
11
24
  * DataEdit component - Form interface for creating and editing database records.
12
25
  *
@@ -16,7 +29,7 @@ export declare function selectControlValue(value: unknown, offersNone: boolean):
16
29
  * @example
17
30
  * ```tsx
18
31
  * // Used within the router context
19
- * <Route path="/:table/edit/:editid" element={<DataEdit />} />
32
+ * <Route path="/:table/edit/:editId" element={<DataEdit />} />
20
33
  * ```
21
34
  *
22
35
  * @returns React element containing the edit form dialog
@@ -26,10 +39,10 @@ export declare function DataEdit(): ReactElement;
26
39
  * Prop-driven edit dialog. Use this to edit a record in place — from a grid at
27
40
  * any nesting depth — without changing the route, so the surrounding drill
28
41
  * context (parent → child → grandchild, side columns) is preserved. `table` is
29
- * the table's `graphQlName`; `editid` is the encoded PK route ('' to insert).
42
+ * the table's `graphQlName`; `editId` is the encoded PK route ('' to insert).
30
43
  */
31
- export declare function DataEditDialog({ table, editid, onClose }: {
44
+ export declare function DataEditDialog({ table, editId, onClose }: {
32
45
  table: string;
33
- editid: string;
46
+ editId: string;
34
47
  onClose: () => void;
35
48
  }): ReactElement;
@@ -1,12 +1 @@
1
- /**
2
- * A side-panel drill frame. `filterTable` + `filterId` + `filterColumn`
3
- * describe the FK scoping applied to `tableName`'s rows — they're optional so
4
- * the same shape can also represent a simple "open table X" panel.
5
- */
6
- export interface ColumnPanel {
7
- tableName: string;
8
- filterTable?: string;
9
- filterId?: string;
10
- filterColumn?: string;
11
- }
12
1
  export declare function DataPanel(): import("react").JSX.Element;