@xnetjs/react 0.0.2 → 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,383 @@
1
+ import { ColumnDefinition, ViewConfig, DatabaseDocumentModel, FilterGroup, SortConfig, NodeQueryMaterializedViewOptions, CellValue, Schema, DatabaseSchemaMetadata } from '@xnetjs/data';
2
+ export { ColumnConfig, ColumnDefinition, ColumnType, ViewConfig, ViewType } from '@xnetjs/data';
3
+ import * as Y from 'yjs';
4
+
5
+ /**
6
+ * useDatabaseDoc - Hook for database column and view operations
7
+ *
8
+ * Provides reactive access to the database's Y.Doc structure:
9
+ * - Column definitions (CRDT-ordered)
10
+ * - View configurations
11
+ * - Column and view CRUD operations
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * const {
16
+ * columns,
17
+ * views,
18
+ * createColumn,
19
+ * updateColumn,
20
+ * deleteColumn,
21
+ * reorderColumn,
22
+ * createView,
23
+ * updateView,
24
+ * deleteView
25
+ * } = useDatabaseDoc(databaseId)
26
+ * ```
27
+ */
28
+
29
+ interface UseDatabaseDocResult {
30
+ /** All column definitions (CRDT-ordered) */
31
+ columns: ColumnDefinition[];
32
+ /** All view configurations */
33
+ views: ViewConfig[];
34
+ /** Y.Doc for direct access (if needed) */
35
+ doc: Y.Doc | null;
36
+ /** Which document storage model currently backs this database */
37
+ storageMode: DatabaseDocumentModel;
38
+ /** Whether this doc can still be explicitly materialized into the canonical model */
39
+ /** Whether the doc is loading */
40
+ loading: boolean;
41
+ /** Any error that occurred */
42
+ error: Error | null;
43
+ /** Create a new column */
44
+ createColumn: (definition: Omit<ColumnDefinition, 'id'>) => string | null;
45
+ /** Update a column's properties */
46
+ updateColumn: (columnId: string, updates: Partial<Omit<ColumnDefinition, 'id'>>) => void;
47
+ /** Delete a column */
48
+ deleteColumn: (columnId: string) => void;
49
+ /** Reorder a column to a new position */
50
+ reorderColumn: (columnId: string, newIndex: number) => void;
51
+ /** Duplicate a column */
52
+ duplicateColumn: (columnId: string, newName?: string) => string | null;
53
+ /** Get a single column by ID */
54
+ getColumn: (columnId: string) => ColumnDefinition | null;
55
+ /** Create a new view */
56
+ createView: (config: Omit<ViewConfig, 'id'>) => string | null;
57
+ /** Update a view's properties */
58
+ updateView: (viewId: string, updates: Partial<Omit<ViewConfig, 'id'>>) => void;
59
+ /** Delete a view */
60
+ deleteView: (viewId: string) => void;
61
+ /** Duplicate a view */
62
+ duplicateView: (viewId: string, newName?: string) => string | null;
63
+ /** Get a single view by ID */
64
+ getView: (viewId: string) => ViewConfig | null;
65
+ }
66
+ /**
67
+ * Hook for database column and view operations.
68
+ *
69
+ * Provides reactive access to the database's Y.Doc structure with
70
+ * CRDT-based column ordering and real-time schema sync.
71
+ */
72
+ declare function useDatabaseDoc(databaseId: string): UseDatabaseDocResult;
73
+
74
+ /**
75
+ * useDatabase - Hook for database row operations with pagination
76
+ *
77
+ * Provides:
78
+ * - Paginated row queries
79
+ * - Row CRUD operations
80
+ * - Integration with useDatabaseDoc for columns/views
81
+ *
82
+ * @example
83
+ * ```tsx
84
+ * const {
85
+ * rows,
86
+ * columns,
87
+ * views,
88
+ * loading,
89
+ * hasMore,
90
+ * loadMore,
91
+ * createRow,
92
+ * updateRow,
93
+ * deleteRow
94
+ * } = useDatabase(databaseId)
95
+ * ```
96
+ */
97
+
98
+ interface UseDatabaseOptions {
99
+ /** Active view ID (uses first view if not specified) */
100
+ view?: string;
101
+ /** Override view filters */
102
+ filters?: FilterGroup;
103
+ /** Override view sorts */
104
+ sorts?: SortConfig[];
105
+ /** Search query (full-text search) - not yet implemented */
106
+ search?: string;
107
+ /** Page size (default: 50) */
108
+ pageSize?: number;
109
+ /**
110
+ * Opt into SQLite materialized row lists for stable persisted views.
111
+ * Pass true to derive a database/view cache key, or pass explicit options.
112
+ */
113
+ materializedView?: boolean | string | NodeQueryMaterializedViewOptions;
114
+ }
115
+ interface DatabaseRow {
116
+ /** Row ID */
117
+ id: string;
118
+ /** Sort key for ordering */
119
+ sortKey: string;
120
+ /** Cell values keyed by column ID */
121
+ cells: Record<string, CellValue>;
122
+ /** Creation timestamp */
123
+ createdAt: number;
124
+ /** Creator DID */
125
+ createdBy: string;
126
+ }
127
+ interface UseDatabaseResult {
128
+ /** Column definitions */
129
+ columns: ColumnDefinition[];
130
+ /** View configurations */
131
+ views: ViewConfig[];
132
+ /** Loaded rows */
133
+ rows: DatabaseRow[];
134
+ /** Total row count */
135
+ total: number;
136
+ /** Whether more rows are available */
137
+ hasMore: boolean;
138
+ /** Load more rows */
139
+ loadMore: () => Promise<void>;
140
+ /** Active view configuration */
141
+ activeView: ViewConfig | null;
142
+ /** Set the active view */
143
+ setActiveView: (viewId: string) => void;
144
+ /** Create a new row */
145
+ createRow: (values?: Record<string, CellValue>) => Promise<string>;
146
+ /** Update a row's cell values */
147
+ updateRow: (rowId: string, values: Record<string, CellValue>) => Promise<void>;
148
+ /** Delete a row */
149
+ deleteRow: (rowId: string) => Promise<void>;
150
+ /** Reorder a row */
151
+ reorderRow: (rowId: string, before?: string, after?: string) => Promise<void>;
152
+ /** Delete multiple rows */
153
+ deleteRows: (rowIds: string[]) => Promise<void>;
154
+ /** Whether initially loading */
155
+ loading: boolean;
156
+ /** Whether loading more rows */
157
+ loadingMore: boolean;
158
+ /** Any error that occurred */
159
+ error: Error | null;
160
+ /** Refetch all rows */
161
+ refetch: () => Promise<void>;
162
+ }
163
+ /**
164
+ * Hook for database row operations with pagination.
165
+ */
166
+ declare function useDatabase(databaseId: string, options?: UseDatabaseOptions): UseDatabaseResult;
167
+
168
+ /**
169
+ * useDatabaseRow - Hook for single row operations with optimistic updates
170
+ *
171
+ * Provides:
172
+ * - Row data with cell values
173
+ * - Y.Doc for rich text cells
174
+ * - Optimistic updates
175
+ * - Delete operation
176
+ *
177
+ * @example
178
+ * ```tsx
179
+ * const {
180
+ * row,
181
+ * doc,
182
+ * update,
183
+ * delete: deleteRow,
184
+ * loading
185
+ * } = useDatabaseRow(rowId)
186
+ * ```
187
+ */
188
+
189
+ interface DatabaseRowData {
190
+ /** Row ID */
191
+ id: string;
192
+ /** Database ID this row belongs to */
193
+ databaseId: string;
194
+ /** Sort key for ordering */
195
+ sortKey: string;
196
+ /** Cell values keyed by column ID */
197
+ cells: Record<string, CellValue>;
198
+ /** Creation timestamp */
199
+ createdAt: number;
200
+ /** Creator DID */
201
+ createdBy: string;
202
+ }
203
+ interface UseDatabaseRowResult {
204
+ /** Row data */
205
+ row: DatabaseRowData | null;
206
+ /** Y.Doc for rich text cells (if any) */
207
+ doc: Y.Doc | null;
208
+ /** Update cell values (with optimistic UI) */
209
+ update: (values: Record<string, CellValue>) => Promise<void>;
210
+ /** Delete this row */
211
+ delete: () => Promise<void>;
212
+ /** Loading state */
213
+ loading: boolean;
214
+ /** Error state */
215
+ error: Error | null;
216
+ }
217
+ /**
218
+ * Hook for single row operations with optimistic updates.
219
+ */
220
+ declare function useDatabaseRow(rowId: string): UseDatabaseRowResult;
221
+
222
+ /**
223
+ * useCell - Hook for individual cell editing with debounced saves
224
+ *
225
+ * Provides:
226
+ * - Cell value with optimistic updates
227
+ * - Debounced persistence
228
+ * - Clear operation
229
+ *
230
+ * @example
231
+ * ```tsx
232
+ * const { value, setValue, saving } = useCell<string>(rowId, 'title')
233
+ *
234
+ * return (
235
+ * <Input
236
+ * value={value ?? ''}
237
+ * onChange={(e) => setValue(e.target.value)}
238
+ * className={saving ? 'opacity-50' : ''}
239
+ * />
240
+ * )
241
+ * ```
242
+ */
243
+
244
+ interface UseCellResult<T extends CellValue = CellValue> {
245
+ /** Cell value */
246
+ value: T | null;
247
+ /** Update cell value (debounced save) */
248
+ setValue: (value: T | null) => void;
249
+ /** Clear cell value */
250
+ clear: () => void;
251
+ /** Whether cell is being saved */
252
+ saving: boolean;
253
+ /** Error from last save */
254
+ error: Error | null;
255
+ }
256
+ interface UseCellOptions {
257
+ /** Debounce delay in ms (default: 300) */
258
+ debounce?: number;
259
+ }
260
+ /**
261
+ * Hook for individual cell editing with debounced saves.
262
+ */
263
+ declare function useCell<T extends CellValue = CellValue>(rowId: string, columnId: string, options?: UseCellOptions): UseCellResult<T>;
264
+
265
+ /**
266
+ * useRelatedRows - Hook for loading related row data for relation columns
267
+ *
268
+ * Fetches the row data for a list of row IDs, typically from a relation column.
269
+ *
270
+ * @example
271
+ * ```tsx
272
+ * const { rows, loading, error } = useRelatedRows(['row1', 'row2'])
273
+ * // rows contains the full row data for display
274
+ * ```
275
+ */
276
+
277
+ interface UseRelatedRowsResult {
278
+ /** Loaded row data */
279
+ rows: DatabaseRow[];
280
+ /** Whether rows are loading */
281
+ loading: boolean;
282
+ /** Any error that occurred */
283
+ error: Error | null;
284
+ }
285
+ /**
286
+ * Hook for loading related row data.
287
+ *
288
+ * @param rowIds - Array of row IDs to load
289
+ * @returns Object containing rows, loading state, and error
290
+ */
291
+ declare function useRelatedRows(rowIds: string[]): UseRelatedRowsResult;
292
+
293
+ /**
294
+ * useReverseRelations - Hook for finding rows that link TO a given row
295
+ *
296
+ * Finds all rows in other databases that have relation columns pointing
297
+ * to the specified row. Useful for showing "backlinks" or "linked from" sections.
298
+ *
299
+ * @example
300
+ * ```tsx
301
+ * const { relations, loading, error } = useReverseRelations(taskId, tasksDatabaseId)
302
+ * // relations contains all rows that link to this task
303
+ * ```
304
+ */
305
+
306
+ interface ReverseRelation {
307
+ /** The row that links to the target row */
308
+ row: DatabaseRow;
309
+ /** The relation column through which it links */
310
+ column: ColumnDefinition;
311
+ /** ID of the source database */
312
+ sourceDatabaseId: string;
313
+ /** Title of the source database */
314
+ sourceDatabaseTitle: string;
315
+ }
316
+ interface UseReverseRelationsResult {
317
+ /** Found reverse relations */
318
+ relations: ReverseRelation[];
319
+ /** Whether relations are loading */
320
+ loading: boolean;
321
+ /** Any error that occurred */
322
+ error: Error | null;
323
+ /** Refetch the relations */
324
+ refetch: () => void;
325
+ }
326
+ /**
327
+ * Hook for finding reverse relations (backlinks) to a row.
328
+ *
329
+ * @param rowId - The row ID to find links to
330
+ * @param databaseId - The database containing the row
331
+ * @returns Object containing relations, loading state, and error
332
+ */
333
+ declare function useReverseRelations(rowId: string, databaseId: string): UseReverseRelationsResult;
334
+
335
+ /**
336
+ * useDatabaseSchema - Hook for database-defined schema access
337
+ *
338
+ * Provides reactive access to a database's schema metadata and properties.
339
+ * Works with the schema registry to resolve database-defined schemas.
340
+ *
341
+ * @example
342
+ * ```tsx
343
+ * const {
344
+ * schema,
345
+ * metadata,
346
+ * loading,
347
+ * error
348
+ * } = useDatabaseSchema(databaseId)
349
+ *
350
+ * // Access schema version
351
+ * console.log(metadata?.version) // "1.2.0"
352
+ *
353
+ * // Access schema properties
354
+ * schema?.properties.forEach(prop => console.log(prop.name))
355
+ * ```
356
+ */
357
+
358
+ interface UseDatabaseSchemaResult {
359
+ /** The resolved Schema object, or null if not loaded */
360
+ schema: Schema | null;
361
+ /** The schema metadata from the database's Y.Doc */
362
+ metadata: DatabaseSchemaMetadata | null;
363
+ /** The schema IRI for this database */
364
+ schemaIRI: string | null;
365
+ /** Whether the schema is loading */
366
+ loading: boolean;
367
+ /** Any error that occurred */
368
+ error: Error | null;
369
+ /** Force refresh the schema */
370
+ refresh: () => void;
371
+ }
372
+ /**
373
+ * Hook for accessing a database's schema.
374
+ *
375
+ * Loads the database's Y.Doc, extracts schema metadata and columns,
376
+ * builds the Schema object, and registers it with the schema registry.
377
+ *
378
+ * @param databaseId - The database node ID
379
+ * @returns The schema, metadata, and loading state
380
+ */
381
+ declare function useDatabaseSchema(databaseId: string | undefined): UseDatabaseSchemaResult;
382
+
383
+ export { type DatabaseRow, type DatabaseRowData, type ReverseRelation, type UseCellOptions, type UseCellResult, type UseDatabaseDocResult, type UseDatabaseOptions, type UseDatabaseResult, type UseDatabaseRowResult, type UseDatabaseSchemaResult, type UseRelatedRowsResult, type UseReverseRelationsResult, useCell, useDatabase, useDatabaseDoc, useDatabaseRow, useDatabaseSchema, useRelatedRows, useReverseRelations };
@@ -0,0 +1,19 @@
1
+ import {
2
+ useCell,
3
+ useDatabase,
4
+ useDatabaseDoc,
5
+ useDatabaseRow,
6
+ useDatabaseSchema,
7
+ useRelatedRows,
8
+ useReverseRelations
9
+ } from "./chunk-KSHTDZ2V.js";
10
+ import "./chunk-IHTMVTTE.js";
11
+ export {
12
+ useCell,
13
+ useDatabase,
14
+ useDatabaseDoc,
15
+ useDatabaseRow,
16
+ useDatabaseSchema,
17
+ useRelatedRows,
18
+ useReverseRelations
19
+ };