@standardbeagle/edit-db 0.3.229 → 0.4.327
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.
- package/LICENSE.txt +21 -0
- package/README.md +305 -0
- package/dist/common/schema.d.ts +1 -1
- package/dist/components/confirm-dialog.d.ts +14 -0
- package/dist/components/content-editor.d.ts +12 -0
- package/dist/components/content-panel.d.ts +18 -0
- package/dist/components/content-viewer.d.ts +7 -0
- package/dist/components/data-table-column-header.d.ts +8 -0
- package/dist/components/data-table-column-header.test.d.ts +0 -0
- package/dist/components/data-table.d.ts +71 -2
- package/dist/components/data-table.test.d.ts +0 -0
- package/dist/components/detail-panel.d.ts +10 -0
- package/dist/components/filters/boolean-filter.d.ts +6 -0
- package/dist/components/filters/date-filter.d.ts +6 -0
- package/dist/components/filters/fk-filter.d.ts +15 -0
- package/dist/components/filters/number-filter.d.ts +6 -0
- package/dist/components/filters/text-filter.d.ts +6 -0
- package/dist/components/fk-cell-popover.d.ts +14 -0
- package/dist/components/row-actions.d.ts +14 -0
- package/dist/components/table-dimensions.test.d.ts +1 -0
- package/dist/components/ui/button.d.ts +1 -1
- package/dist/components/ui/dialog.d.ts +12 -12
- package/dist/components/ui/hover-card.d.ts +6 -0
- package/dist/components/ui/input.d.ts +1 -1
- package/dist/components/ui/sheet.d.ts +14 -0
- package/dist/components/ui/table.d.ts +9 -2
- package/dist/data-data-table.d.ts +6 -1
- package/dist/data-edit.d.ts +14 -0
- package/dist/data-edit.test.d.ts +0 -0
- package/dist/data-panel.d.ts +11 -0
- package/dist/edit-db.css +1 -1
- package/dist/editor.d.ts +32 -0
- package/dist/editor.es.js +9501 -6510
- package/dist/editor.umd.cjs +55 -34
- package/dist/hooks/useColumnNav.d.ts +28 -0
- package/dist/hooks/useDataTable.d.ts +54 -3
- package/dist/hooks/useDeleteMutation.d.ts +10 -0
- package/dist/hooks/useDeleteMutation.test.d.ts +0 -0
- package/dist/hooks/useSchema.d.ts +25 -0
- package/dist/hooks/useTableStats.d.ts +76 -0
- package/dist/hooks/useTableStats.test.d.ts +1 -0
- package/dist/lib/composite-pk-roundtrip.test.d.ts +1 -0
- package/dist/lib/content-detect.d.ts +14 -0
- package/dist/lib/drill-stack.d.ts +52 -0
- package/dist/lib/drill-stack.test.d.ts +1 -0
- package/dist/lib/humanize.d.ts +5 -0
- package/dist/lib/pk-hygiene.test.d.ts +1 -0
- package/dist/lib/query-builder.d.ts +52 -0
- package/dist/lib/query-builder.test.d.ts +1 -0
- package/dist/lib/row-id.d.ts +14 -0
- package/dist/lib/row-id.test.d.ts +1 -0
- package/dist/tableList.d.ts +15 -0
- package/dist/tableList.test.d.ts +0 -0
- package/dist/types/schema.d.ts +88 -0
- package/package.json +21 -16
package/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 BifrostQL
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
# @standardbeagle/edit-db
|
|
2
|
+
|
|
3
|
+
> React GraphQL database editor with automatic form generation, validation, and data table components.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@standardbeagle/edit-db)
|
|
6
|
+
[](https://react.dev/)
|
|
7
|
+
[](https://graphql.org/)
|
|
8
|
+
[](https://www.typescriptlang.org/)
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
`@standardbeagle/edit-db` is a React component library for building database administration interfaces. Connect it to any GraphQL API—especially [BifrostQL](https://github.com/standardbeagle/BifrostQL)—and get a fully functional data editor with zero configuration.
|
|
13
|
+
|
|
14
|
+
**Key features:**
|
|
15
|
+
|
|
16
|
+
- **Automatic form generation** from GraphQL schema introspection
|
|
17
|
+
- **Built-in validation** with support for required fields, patterns, ranges, and custom rules
|
|
18
|
+
- **Data table with sorting, filtering, and pagination** powered by TanStack Table
|
|
19
|
+
- **Foreign key navigation** with automatic relationship detection
|
|
20
|
+
- **Responsive design** using Tailwind CSS and shadcn/ui components
|
|
21
|
+
- **TypeScript support** with full type definitions
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
Install the package and its peer dependencies:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @standardbeagle/edit-db @tanstack/react-query
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
yarn add @standardbeagle/edit-db @tanstack/react-query
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pnpm add @standardbeagle/edit-db @tanstack/react-query
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Prerequisites
|
|
40
|
+
|
|
41
|
+
- React 18 or higher
|
|
42
|
+
- @tanstack/react-query 5.x
|
|
43
|
+
- A GraphQL API endpoint (BifrostQL recommended)
|
|
44
|
+
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
import { Editor } from '@standardbeagle/edit-db';
|
|
49
|
+
import '@standardbeagle/edit-db/style.css';
|
|
50
|
+
|
|
51
|
+
function App() {
|
|
52
|
+
return (
|
|
53
|
+
<Editor
|
|
54
|
+
uri="https://api.example.com/graphql"
|
|
55
|
+
uiPath="/admin"
|
|
56
|
+
/>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export default App;
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Usage Examples
|
|
64
|
+
|
|
65
|
+
### Basic Setup with BifrostQL
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import { Editor } from '@standardbeagle/edit-db';
|
|
69
|
+
import '@standardbeagle/edit-db/style.css';
|
|
70
|
+
|
|
71
|
+
function DatabaseAdmin() {
|
|
72
|
+
return (
|
|
73
|
+
<div className="h-screen">
|
|
74
|
+
<Editor
|
|
75
|
+
uri="/graphql"
|
|
76
|
+
uiPath="/admin"
|
|
77
|
+
onLocate={(path) => console.log('Navigation:', path)}
|
|
78
|
+
/>
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Custom GraphQL Fetcher
|
|
85
|
+
|
|
86
|
+
For advanced use cases, provide a custom fetcher:
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
import { Editor, GraphQLFetcher } from '@standardbeagle/edit-db';
|
|
90
|
+
|
|
91
|
+
class CustomFetcher implements GraphQLFetcher {
|
|
92
|
+
async query<T>(query: string, variables?: Record<string, unknown>): Promise<T> {
|
|
93
|
+
const response = await fetch('/api/graphql', {
|
|
94
|
+
method: 'POST',
|
|
95
|
+
headers: {
|
|
96
|
+
'Content-Type': 'application/json',
|
|
97
|
+
'Authorization': `Bearer ${getAuthToken()}`,
|
|
98
|
+
},
|
|
99
|
+
body: JSON.stringify({ query, variables }),
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
if (!response.ok) {
|
|
103
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const result = await response.json();
|
|
107
|
+
|
|
108
|
+
if (result.errors) {
|
|
109
|
+
throw new Error(result.errors[0].message);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return result.data;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function App() {
|
|
117
|
+
const fetcher = useMemo(() => new CustomFetcher(), []);
|
|
118
|
+
|
|
119
|
+
return <Editor fetcher={fetcher} uiPath="/admin" />;
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Navigation Tracking
|
|
124
|
+
|
|
125
|
+
Track user navigation for analytics or state management:
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
function App() {
|
|
129
|
+
const [currentPath, setCurrentPath] = useState('');
|
|
130
|
+
|
|
131
|
+
return (
|
|
132
|
+
<>
|
|
133
|
+
<nav>Current: {currentPath}</nav>
|
|
134
|
+
<Editor
|
|
135
|
+
uri="/graphql"
|
|
136
|
+
uiPath="/admin"
|
|
137
|
+
onLocate={setCurrentPath}
|
|
138
|
+
/>
|
|
139
|
+
</>
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Configuration Options
|
|
145
|
+
|
|
146
|
+
### Editor Props
|
|
147
|
+
|
|
148
|
+
| Prop | Type | Required | Description |
|
|
149
|
+
|------|------|----------|-------------|
|
|
150
|
+
| `uri` | `string` | Optional* | GraphQL endpoint URL |
|
|
151
|
+
| `fetcher` | `GraphQLFetcher` | Optional* | Custom fetcher instance |
|
|
152
|
+
| `uiPath` | `string` | Optional | Base path for routing (default: `/`) |
|
|
153
|
+
| `onLocate` | `(path: string) => void` | Optional | Navigation callback |
|
|
154
|
+
|
|
155
|
+
*Either `uri` or `fetcher` is required.
|
|
156
|
+
|
|
157
|
+
### GraphQL Schema Requirements
|
|
158
|
+
|
|
159
|
+
The editor expects a BifrostQL-compatible schema with the `_dbSchema` query:
|
|
160
|
+
|
|
161
|
+
```graphql
|
|
162
|
+
type Query {
|
|
163
|
+
_dbSchema: [DbSchemaItem!]!
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
type DbSchemaItem {
|
|
167
|
+
graphQlName: String!
|
|
168
|
+
dbName: String!
|
|
169
|
+
labelColumn: String!
|
|
170
|
+
primaryKeys: [String!]!
|
|
171
|
+
isEditable: Boolean!
|
|
172
|
+
metadata: [MetadataItem!]!
|
|
173
|
+
columns: [DbColumnItem!]!
|
|
174
|
+
multiJoins: [JoinItem!]!
|
|
175
|
+
singleJoins: [JoinItem!]!
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
type DbColumnItem {
|
|
179
|
+
graphQlName: String!
|
|
180
|
+
dbName: String!
|
|
181
|
+
paramType: String!
|
|
182
|
+
dbType: String!
|
|
183
|
+
isPrimaryKey: Boolean!
|
|
184
|
+
isIdentity: Boolean!
|
|
185
|
+
isNullable: Boolean!
|
|
186
|
+
isReadOnly: Boolean!
|
|
187
|
+
metadata: [MetadataItem!]!
|
|
188
|
+
# Optional validation metadata
|
|
189
|
+
maxLength: Int
|
|
190
|
+
minLength: Int
|
|
191
|
+
min: Float
|
|
192
|
+
max: Float
|
|
193
|
+
step: Float
|
|
194
|
+
pattern: String
|
|
195
|
+
patternMessage: String
|
|
196
|
+
inputType: String
|
|
197
|
+
defaultValue: String
|
|
198
|
+
enumValues: [String!]
|
|
199
|
+
enumLabels: [String!]
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Component Architecture
|
|
204
|
+
|
|
205
|
+
### Main Components
|
|
206
|
+
|
|
207
|
+
#### `<Editor />`
|
|
208
|
+
The root component that sets up React Query, schema context, and routing.
|
|
209
|
+
|
|
210
|
+
#### `<MainFrame />`
|
|
211
|
+
Handles the application layout with sidebar navigation and main content area.
|
|
212
|
+
|
|
213
|
+
#### `<DataPanel />`
|
|
214
|
+
Displays data tables with sorting, filtering, and pagination.
|
|
215
|
+
|
|
216
|
+
#### `<DataEdit />`
|
|
217
|
+
Renders edit forms with automatic field generation based on schema metadata.
|
|
218
|
+
|
|
219
|
+
### Custom Hooks
|
|
220
|
+
|
|
221
|
+
| Hook | Purpose |
|
|
222
|
+
|------|---------|
|
|
223
|
+
| `useSchema()` | Access database schema and table metadata |
|
|
224
|
+
| `useDataTable()` | Manage table data, sorting, filtering, and pagination |
|
|
225
|
+
| `useTableMutation()` | Handle insert, update, and delete operations |
|
|
226
|
+
| `useTableRef()` | Fetch reference data for foreign key dropdowns |
|
|
227
|
+
| `usePath()` | Client-side routing without page reloads |
|
|
228
|
+
| `useColumnNav()` | Manage side panel navigation for related records |
|
|
229
|
+
|
|
230
|
+
### Form Validation
|
|
231
|
+
|
|
232
|
+
Validation rules are automatically applied from schema metadata:
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
// Required fields
|
|
236
|
+
{ isNullable: false }
|
|
237
|
+
|
|
238
|
+
// String length
|
|
239
|
+
{ maxLength: 255, minLength: 1 }
|
|
240
|
+
|
|
241
|
+
// Numeric ranges
|
|
242
|
+
{ min: 0, max: 100, step: 1 }
|
|
243
|
+
|
|
244
|
+
// Pattern matching
|
|
245
|
+
{ pattern: '^[A-Z]{2}-\\d{4}$', patternMessage: 'Format: XX-0000' }
|
|
246
|
+
|
|
247
|
+
// Enum values
|
|
248
|
+
{ enumValues: ['active', 'inactive'], enumLabels: ['Active', 'Inactive'] }
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Styling
|
|
252
|
+
|
|
253
|
+
The package uses Tailwind CSS for styling. Import the stylesheet:
|
|
254
|
+
|
|
255
|
+
```tsx
|
|
256
|
+
import '@standardbeagle/edit-db/style.css';
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
For custom theming, override CSS variables:
|
|
260
|
+
|
|
261
|
+
```css
|
|
262
|
+
:root {
|
|
263
|
+
--background: 0 0% 100%;
|
|
264
|
+
--foreground: 222.2 84% 4.9%;
|
|
265
|
+
--primary: 222.2 47.4% 11.2%;
|
|
266
|
+
--primary-foreground: 210 40% 98%;
|
|
267
|
+
/* ... */
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## TypeScript Support
|
|
272
|
+
|
|
273
|
+
Full TypeScript definitions are included:
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
import type {
|
|
277
|
+
EditorProps,
|
|
278
|
+
GraphQLFetcher,
|
|
279
|
+
Schema,
|
|
280
|
+
Table,
|
|
281
|
+
Column
|
|
282
|
+
} from '@standardbeagle/edit-db';
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## Browser Support
|
|
286
|
+
|
|
287
|
+
- Chrome 90+
|
|
288
|
+
- Firefox 88+
|
|
289
|
+
- Safari 14+
|
|
290
|
+
- Edge 90+
|
|
291
|
+
|
|
292
|
+
## Related Packages
|
|
293
|
+
|
|
294
|
+
- [BifrostQL](https://github.com/standardbeagle/BifrostQL) - Zero-config GraphQL API for databases
|
|
295
|
+
- [@tanstack/react-table](https://tanstack.com/table) - Headless UI for building data tables
|
|
296
|
+
- [@tanstack/react-query](https://tanstack.com/query) - Data fetching and caching
|
|
297
|
+
- [@tanstack/react-form](https://tanstack.com/form) - Form state management
|
|
298
|
+
|
|
299
|
+
## License
|
|
300
|
+
|
|
301
|
+
MIT © Standard Beagle
|
|
302
|
+
|
|
303
|
+
## Contributing
|
|
304
|
+
|
|
305
|
+
Contributions are welcome! Please see the [main BifrostQL repository](https://github.com/standardbeagle/BifrostQL) for contribution guidelines.
|
package/dist/common/schema.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare const GET_SCHEMA = "{\n schema: __schema {\n queryType {\n fields {\n name\n type {\n fields {\n name\n type {\n ofType {\n fields {\n name\n type {\n kind\n ofType {\n name\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n ";
|
|
2
|
-
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 isPrimaryKey\n isIdentity\n isNullable\n isReadOnly\n metadata {\n key\n value\n }\n }\n multiJoins {\n name\n sourceColumnNames\n destinationTable\n destinationColumnNames\n }\n singleJoins {\n name\n sourceColumnNames\n destinationTable\n destinationColumnNames\n }\n }\n}";
|
|
2
|
+
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 maxLength\n minLength\n min\n max\n step\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 sourceColumnNames\n destinationTable\n destinationColumnNames\n }\n singleJoins {\n name\n sourceColumnNames\n destinationTable\n destinationColumnNames\n }\n }\n}";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
interface ConfirmDialogProps {
|
|
3
|
+
open: boolean;
|
|
4
|
+
onOpenChange: (open: boolean) => void;
|
|
5
|
+
title: string;
|
|
6
|
+
description: ReactNode;
|
|
7
|
+
confirmLabel?: string;
|
|
8
|
+
cancelLabel?: string;
|
|
9
|
+
variant?: 'default' | 'destructive';
|
|
10
|
+
isPending?: boolean;
|
|
11
|
+
onConfirm: () => void;
|
|
12
|
+
}
|
|
13
|
+
export declare function ConfirmDialog({ open, onOpenChange, title, description, confirmLabel, cancelLabel, variant, isPending, onConfirm, }: ConfirmDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface ContentEditorProps {
|
|
2
|
+
name: string;
|
|
3
|
+
label: string;
|
|
4
|
+
value: string;
|
|
5
|
+
dbType: string;
|
|
6
|
+
onChange: (value: string) => void;
|
|
7
|
+
onBlur: () => void;
|
|
8
|
+
required?: boolean;
|
|
9
|
+
invalid?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function ContentEditor({ name, label, value, dbType, onChange, onBlur, required, invalid, }: ContentEditorProps): import("react/jsx-runtime").JSX.Element | null;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface ContentPanelTarget {
|
|
2
|
+
value: string;
|
|
3
|
+
columnName: string;
|
|
4
|
+
columnLabel: string;
|
|
5
|
+
dbType: string;
|
|
6
|
+
rowIndex: number;
|
|
7
|
+
isReadOnly: boolean;
|
|
8
|
+
}
|
|
9
|
+
interface ContentPanelProps {
|
|
10
|
+
target: ContentPanelTarget | null;
|
|
11
|
+
onClose: () => void;
|
|
12
|
+
onNavigate: (direction: 'prev' | 'next') => void;
|
|
13
|
+
onSave?: (value: string) => void;
|
|
14
|
+
canNavigatePrev: boolean;
|
|
15
|
+
canNavigateNext: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare function ContentPanel({ target, onClose, onNavigate, onSave, canNavigatePrev, canNavigateNext, }: ContentPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Column, Table } from '@tanstack/react-table';
|
|
2
|
+
interface DataTableColumnHeaderProps<TData, TValue> {
|
|
3
|
+
column: Column<TData, TValue>;
|
|
4
|
+
table: Table<TData>;
|
|
5
|
+
title: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function DataTableColumnHeader<TData, TValue>({ column, table: tableInstance, title, }: DataTableColumnHeaderProps<TData, TValue>): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export {};
|
|
File without changes
|
|
@@ -1,15 +1,84 @@
|
|
|
1
|
-
import { ColumnDef, SortingState } from '@tanstack/react-table';
|
|
1
|
+
import { ColumnDef, ColumnFiltersState, SortingState } from '@tanstack/react-table';
|
|
2
|
+
import { PkFilter } from '../lib/row-id';
|
|
3
|
+
/**
|
|
4
|
+
* Props for the DataTable component.
|
|
5
|
+
* @interface DataTableProps
|
|
6
|
+
* @template TData - The type of data rows displayed in the table
|
|
7
|
+
*/
|
|
2
8
|
interface DataTableProps<TData> {
|
|
9
|
+
/** Column definitions for the table */
|
|
3
10
|
columns: ColumnDef<TData, unknown>[];
|
|
11
|
+
/** Data rows to display */
|
|
4
12
|
data: TData[];
|
|
13
|
+
/** Table name for persisting column sizing to localStorage */
|
|
14
|
+
tableName?: string;
|
|
15
|
+
/** Total number of pages */
|
|
5
16
|
pageCount: number;
|
|
17
|
+
/** Current page index (0-based) */
|
|
6
18
|
pageIndex: number;
|
|
19
|
+
/** Number of rows per page */
|
|
7
20
|
pageSize: number;
|
|
21
|
+
/** Current sorting state */
|
|
8
22
|
sorting: SortingState;
|
|
23
|
+
/** Active column filters */
|
|
24
|
+
columnFilters: ColumnFiltersState;
|
|
25
|
+
/** Whether data is currently loading */
|
|
9
26
|
loading?: boolean;
|
|
27
|
+
/** Enable row selection checkboxes */
|
|
28
|
+
selectable?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Primary key column names in declaration order.
|
|
31
|
+
* - Single-column PK: `['id']` (or whichever column).
|
|
32
|
+
* - Composite PK: multiple entries — the row id becomes a composite-encoded string.
|
|
33
|
+
* - Empty / omitted: synthetic `row-${index}` ids; edit/delete actions are disabled.
|
|
34
|
+
*/
|
|
35
|
+
primaryKeys?: string[];
|
|
36
|
+
/** Currently selected row ID — must be a value produced by `rowIdOf` (composite-encoded). */
|
|
37
|
+
selectedRowId?: string | null;
|
|
38
|
+
/** Callback when a row is selected */
|
|
39
|
+
onRowSelect?: (rowId: string | null) => void;
|
|
40
|
+
/** Callback when sorting changes */
|
|
10
41
|
onSortingChange: (sorting: SortingState) => void;
|
|
42
|
+
/** Callback when column filters change */
|
|
43
|
+
onColumnFiltersChange: (filters: ColumnFiltersState) => void;
|
|
44
|
+
/** Callback when page index changes */
|
|
11
45
|
onPageIndexChange: (pageIndex: number) => void;
|
|
46
|
+
/** Callback when page size changes */
|
|
12
47
|
onPageSizeChange: (pageSize: number) => void;
|
|
48
|
+
/** Callback when edit action is triggered for a row */
|
|
49
|
+
onEditRow?: (pk: PkFilter) => void;
|
|
50
|
+
/** Callback when delete action is triggered for a row */
|
|
51
|
+
onDeleteRow?: (pk: PkFilter) => void;
|
|
52
|
+
/** Callback when deleting multiple selected rows */
|
|
53
|
+
onDeleteSelected?: (pks: PkFilter[]) => void;
|
|
13
54
|
}
|
|
14
|
-
|
|
55
|
+
/**
|
|
56
|
+
* DataTable component - A comprehensive data table with sorting, filtering,
|
|
57
|
+
* pagination, and column resizing capabilities.
|
|
58
|
+
*
|
|
59
|
+
* Built on top of TanStack Table (@tanstack/react-table) with a Tailwind CSS
|
|
60
|
+
* interface. Supports row selection, inline actions, and persistent column sizing.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```tsx
|
|
64
|
+
* <DataTable
|
|
65
|
+
* columns={columns}
|
|
66
|
+
* data={rows}
|
|
67
|
+
* pageCount={10}
|
|
68
|
+
* pageIndex={0}
|
|
69
|
+
* pageSize={20}
|
|
70
|
+
* sorting={[{ id: 'name', desc: false }]}
|
|
71
|
+
* columnFilters={[]}
|
|
72
|
+
* onSortingChange={setSorting}
|
|
73
|
+
* onColumnFiltersChange={setFilters}
|
|
74
|
+
* onPageIndexChange={setPageIndex}
|
|
75
|
+
* onPageSizeChange={setPageSize}
|
|
76
|
+
* />
|
|
77
|
+
* ```
|
|
78
|
+
*
|
|
79
|
+
* @template TData - The type of data rows
|
|
80
|
+
* @param props - DataTable configuration props
|
|
81
|
+
* @returns React element containing the data table interface
|
|
82
|
+
*/
|
|
83
|
+
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, }: DataTableProps<TData>): import("react/jsx-runtime").JSX.Element;
|
|
15
84
|
export {};
|
|
File without changes
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Table } from '../types/schema';
|
|
2
|
+
import { ColumnPanel } from '../data-panel';
|
|
3
|
+
interface DetailPanelProps {
|
|
4
|
+
parentTable: Table;
|
|
5
|
+
selectedRowId: string;
|
|
6
|
+
onClose?: () => void;
|
|
7
|
+
onOpenColumn?: (panel: ColumnPanel) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare function DetailPanel({ parentTable, selectedRowId, onClose, onOpenColumn }: DetailPanelProps): import("react/jsx-runtime").JSX.Element | null;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Column } from '@tanstack/react-table';
|
|
2
|
+
interface BooleanFilterProps<TData, TValue> {
|
|
3
|
+
column: Column<TData, TValue>;
|
|
4
|
+
}
|
|
5
|
+
export declare function BooleanFilter<TData, TValue>({ column }: BooleanFilterProps<TData, TValue>): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Column } from '@tanstack/react-table';
|
|
2
|
+
interface DateFilterProps<TData, TValue> {
|
|
3
|
+
column: Column<TData, TValue>;
|
|
4
|
+
}
|
|
5
|
+
export declare function DateFilter<TData, TValue>({ column }: DateFilterProps<TData, TValue>): import("react/jsx-runtime").JSX.Element | null;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Column } from '@tanstack/react-table';
|
|
2
|
+
interface FkFilterProps<TData, TValue> {
|
|
3
|
+
column: Column<TData, TValue>;
|
|
4
|
+
joinTable: string;
|
|
5
|
+
joinLabelColumn: string;
|
|
6
|
+
/**
|
|
7
|
+
* The destination column of the join (FK target). Used to project the option values
|
|
8
|
+
* so the filter applies against the same column the FK points at. Do NOT substitute
|
|
9
|
+
* the target table's first primary-key column here — on composite-PK or denormalized-FK
|
|
10
|
+
* targets those are different columns.
|
|
11
|
+
*/
|
|
12
|
+
joinFkColumn: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function FkFilter<TData, TValue>({ column, joinTable, joinLabelColumn, joinFkColumn }: FkFilterProps<TData, TValue>): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Column } from '@tanstack/react-table';
|
|
2
|
+
interface NumberFilterProps<TData, TValue> {
|
|
3
|
+
column: Column<TData, TValue>;
|
|
4
|
+
}
|
|
5
|
+
export declare function NumberFilter<TData, TValue>({ column }: NumberFilterProps<TData, TValue>): import("react/jsx-runtime").JSX.Element | null;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Column } from '@tanstack/react-table';
|
|
2
|
+
interface TextFilterProps<TData, TValue> {
|
|
3
|
+
column: Column<TData, TValue>;
|
|
4
|
+
}
|
|
5
|
+
export declare function TextFilter<TData, TValue>({ column }: TextFilterProps<TData, TValue>): import("react/jsx-runtime").JSX.Element | null;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
interface FkCellPopoverProps {
|
|
3
|
+
tableName: string;
|
|
4
|
+
recordId: string | number;
|
|
5
|
+
/**
|
|
6
|
+
* The column on `tableName` whose value is `recordId`. Callers pass the FK target
|
|
7
|
+
* column from the join metadata (`destinationColumnNames[0]`). Using the target's
|
|
8
|
+
* "primary key" column here is wrong for composite-PK and denormalized-FK targets.
|
|
9
|
+
*/
|
|
10
|
+
filterColumn: string;
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
export declare function FkCellPopover({ tableName, recordId, filterColumn, children }: FkCellPopoverProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface RowActionsProps {
|
|
2
|
+
anchorEl: HTMLElement;
|
|
3
|
+
onEdit?: () => void;
|
|
4
|
+
onDelete?: () => void;
|
|
5
|
+
onMouseEnter: () => void;
|
|
6
|
+
onDismiss: () => void;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Floating row action toolbar using the Popover API.
|
|
10
|
+
* Anchored to the row element, positioned below-left with automatic
|
|
11
|
+
* flip to above when near the viewport bottom.
|
|
12
|
+
*/
|
|
13
|
+
export declare function RowActions({ anchorEl, onEdit, onDelete, onMouseEnter, onDismiss }: RowActionsProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -2,7 +2,7 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
declare const buttonVariants: (props?: ({
|
|
4
4
|
variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
|
|
5
|
-
size?: "default" | "sm" | "lg" | "icon" | null | undefined;
|
|
5
|
+
size?: "default" | "icon" | "sm" | "lg" | "icon-sm" | null | undefined;
|
|
6
6
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
7
7
|
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
8
8
|
asChild?: boolean;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { Dialog as DialogPrimitive } from 'radix-ui';
|
|
2
2
|
import * as React from "react";
|
|
3
|
-
declare
|
|
4
|
-
declare
|
|
5
|
-
declare
|
|
6
|
-
declare
|
|
7
|
-
declare
|
|
8
|
-
declare
|
|
3
|
+
declare const Dialog: React.ForwardRefExoticComponent<DialogPrimitive.DialogProps & React.RefAttributes<never>>;
|
|
4
|
+
declare const DialogTrigger: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogTriggerProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
5
|
+
declare const DialogPortal: React.ForwardRefExoticComponent<DialogPrimitive.DialogPortalProps & React.RefAttributes<never>>;
|
|
6
|
+
declare const DialogClose: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogCloseProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
7
|
+
declare const DialogOverlay: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogOverlayProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
8
|
+
declare const DialogContent: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
|
|
9
9
|
showCloseButton?: boolean;
|
|
10
|
-
}
|
|
11
|
-
declare
|
|
12
|
-
declare
|
|
10
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
11
|
+
declare const DialogHeader: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
12
|
+
declare const DialogFooter: React.ForwardRefExoticComponent<Omit<React.ClassAttributes<HTMLDivElement> & React.HTMLAttributes<HTMLDivElement> & {
|
|
13
13
|
showCloseButton?: boolean;
|
|
14
|
-
}
|
|
15
|
-
declare
|
|
16
|
-
declare
|
|
14
|
+
}, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
15
|
+
declare const DialogTitle: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogTitleProps & React.RefAttributes<HTMLHeadingElement>, "ref"> & React.RefAttributes<HTMLHeadingElement>>;
|
|
16
|
+
declare const DialogDescription: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogDescriptionProps & React.RefAttributes<HTMLParagraphElement>, "ref"> & React.RefAttributes<HTMLParagraphElement>>;
|
|
17
17
|
export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { HoverCard as HoverCardPrimitive } from 'radix-ui';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
declare const HoverCard: React.ForwardRefExoticComponent<HoverCardPrimitive.HoverCardProps & React.RefAttributes<never>>;
|
|
4
|
+
declare const HoverCardTrigger: React.ForwardRefExoticComponent<Omit<HoverCardPrimitive.HoverCardTriggerProps & React.RefAttributes<HTMLAnchorElement>, "ref"> & React.RefAttributes<HTMLAnchorElement>>;
|
|
5
|
+
declare const HoverCardContent: React.ForwardRefExoticComponent<Omit<HoverCardPrimitive.HoverCardContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
6
|
+
export { HoverCard, HoverCardTrigger, HoverCardContent };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
declare
|
|
2
|
+
declare const Input: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref"> & React.RefAttributes<HTMLInputElement>>;
|
|
3
3
|
export { Input };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Dialog as DialogPrimitive } from 'radix-ui';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
declare function Sheet({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>): import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
declare function SheetTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive.Trigger>): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
declare function SheetPortal({ ...props }: React.ComponentProps<typeof DialogPrimitive.Portal>): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
declare function SheetClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
declare function SheetOverlay({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Overlay>): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
declare function SheetContent({ className, children, side, ...props }: React.ComponentProps<typeof DialogPrimitive.Content> & {
|
|
9
|
+
side?: "top" | "right" | "bottom" | "left";
|
|
10
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
declare function SheetHeader({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
declare function SheetTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
declare function SheetDescription({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Description>): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
export { Sheet, SheetClose, SheetContent, SheetDescription, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, };
|