@lunora/studio 0.0.0 → 1.0.0-alpha.10

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 (80) hide show
  1. package/LICENSE.md +105 -0
  2. package/README.md +123 -9
  3. package/__assets__/package-og.svg +14 -0
  4. package/dist/index.d.ts +1403 -0
  5. package/dist/index.js +41 -0
  6. package/dist/mount.d.ts +21 -0
  7. package/dist/mount.js +26 -0
  8. package/dist/packem_shared/ADMIN_FUNCTIONS-DjXgvJb6.js +46 -0
  9. package/dist/packem_shared/ApiDocsPanel-yVSGHK3H.js +842 -0
  10. package/dist/packem_shared/ApiReferencePanel-1vubqG5s.js +229 -0
  11. package/dist/packem_shared/ApiTab-rwttyQ1-.js +251 -0
  12. package/dist/packem_shared/AuditPanel-D9Eh7j7E.js +200 -0
  13. package/dist/packem_shared/CommandPalette-BtgkBzZI.js +373 -0
  14. package/dist/packem_shared/ConfirmButton-C2eVi2Qv.js +59 -0
  15. package/dist/packem_shared/ConnectionBadge-B2DDM2Tn.js +111 -0
  16. package/dist/packem_shared/DEFAULT_AUTO_REFRESH_MS-Vxwaxx51.js +50 -0
  17. package/dist/packem_shared/DEFAULT_INSIGHT_THRESHOLDS-DjF0h-gA.js +89 -0
  18. package/dist/packem_shared/DEFAULT_LOCALE-CiX4W7Kr.js +27 -0
  19. package/dist/packem_shared/DataBrowser-CyckZRwj.js +4480 -0
  20. package/dist/packem_shared/DataFilters-FNquMaiu.js +249 -0
  21. package/dist/packem_shared/ErrorBoundary-BzAApI7J.js +66 -0
  22. package/dist/packem_shared/ExportImportPanel-BGJqFK9X.js +197 -0
  23. package/dist/packem_shared/FileBrowser-0pCpdKPE.js +2932 -0
  24. package/dist/packem_shared/FunctionRunner-7NH3KcTg.js +343 -0
  25. package/dist/packem_shared/FunctionStatsPanel-CXynSuqT.js +375 -0
  26. package/dist/packem_shared/GlobalDataBrowser-DAxzB-Br.js +289 -0
  27. package/dist/packem_shared/HealthPanel-CyLs7qZm.js +648 -0
  28. package/dist/packem_shared/HomePanel-BOkFRbuj.js +1334 -0
  29. package/dist/packem_shared/InsightsPanel-CvXMoZuv.js +461 -0
  30. package/dist/packem_shared/LogsPanel-BrUstOk6.js +827 -0
  31. package/dist/packem_shared/MailPanel-GnnrNqL6.js +440 -0
  32. package/dist/packem_shared/MetricsPanel-BN_uUU-_.js +1611 -0
  33. package/dist/packem_shared/MigrationsPanel-DaZuUHje.js +239 -0
  34. package/dist/packem_shared/OpenRpcReferencePanel-vbcYbv3V.js +191 -0
  35. package/dist/packem_shared/PitrPanel-LJGNP_IX.js +252 -0
  36. package/dist/packem_shared/STUDIO_ROOT_CLASS-D12gX2dV.js +3 -0
  37. package/dist/packem_shared/ScheduledJobs-UmVaMbJy.js +262 -0
  38. package/dist/packem_shared/SchemaViewer-Bam6ylvw.js +2512 -0
  39. package/dist/packem_shared/SecurityAdvisorPanel-DTmjUNqt.js +92 -0
  40. package/dist/packem_shared/SettingsPanel-C2wDK-8F.js +390 -0
  41. package/dist/packem_shared/ShardInput-gx_DZXXn.js +107 -0
  42. package/dist/packem_shared/SqlEditorPanel-D5wMIxcg.js +13 -0
  43. package/dist/packem_shared/Studio-DpgYe4qt.js +33 -0
  44. package/dist/packem_shared/StudioApp-C7aaizqc.js +657 -0
  45. package/dist/packem_shared/StudioI18nProvider-B-tDCZIi.js +48 -0
  46. package/dist/packem_shared/TableEditor-DzK3Z6rL.js +371 -0
  47. package/dist/packem_shared/advisor-view-CGcfMiPq.js +159 -0
  48. package/dist/packem_shared/aggregateMetrics-D4nUHEKU.js +108 -0
  49. package/dist/packem_shared/app.d-Nbhpihxv.d.ts +300 -0
  50. package/dist/packem_shared/badge-B2PKA1-5.js +49 -0
  51. package/dist/packem_shared/bar-chart-CzJAgqkp.js +3245 -0
  52. package/dist/packem_shared/button-BhsN2uZH.js +49 -0
  53. package/dist/packem_shared/card-DURq3ElK.js +175 -0
  54. package/dist/packem_shared/cf-links-2cktDedA.js +8 -0
  55. package/dist/packem_shared/checkbox-UNkzAxl-.js +63 -0
  56. package/dist/packem_shared/data-grid-B5CaV3wS.js +183 -0
  57. package/dist/packem_shared/dropdown-menu-WY4B_eJO.js +280 -0
  58. package/dist/packem_shared/empty-state-DY_oe0k6.js +98 -0
  59. package/dist/packem_shared/grid-features-CzUfqgsM.js +840 -0
  60. package/dist/packem_shared/input-XH4r1Pt1.js +53 -0
  61. package/dist/packem_shared/internal-rXJEAhXS.js +68 -0
  62. package/dist/packem_shared/label-D8ykjn5J.js +46 -0
  63. package/dist/packem_shared/live-status-FZ0psC1z.js +44 -0
  64. package/dist/packem_shared/reference-view-B4E49Lip.js +2180 -0
  65. package/dist/packem_shared/shard-history-DyebH1R5.js +38 -0
  66. package/dist/packem_shared/sparkline-10dG-_f0.js +93 -0
  67. package/dist/packem_shared/sql-editor-panel-Smfl_FDF.js +2562 -0
  68. package/dist/packem_shared/storage-tier-CL98eOvn.js +85 -0
  69. package/dist/packem_shared/studio-9Mq0PdMi.js +10831 -0
  70. package/dist/packem_shared/table-_RzNvy3R.js +246 -0
  71. package/dist/packem_shared/table-list-sidebar-Bg7uzbvC.js +832 -0
  72. package/dist/packem_shared/textarea-D3gaCU_-.js +46 -0
  73. package/dist/packem_shared/use-admin-query-4JQW2rr1.js +88 -0
  74. package/dist/packem_shared/useDebounced-Dxncpg6z.js +32 -0
  75. package/dist/packem_shared/utils-B05Dmz_H.js +8 -0
  76. package/dist/packem_shared/virtual-rect-CVMUskSm.js +10 -0
  77. package/dist/standalone/studio.js +378 -0
  78. package/dist/styles.css +2 -0
  79. package/package.json +78 -17
  80. package/src/theme.css +59 -0
@@ -0,0 +1,4480 @@
1
+ import { c } from 'react/compiler-runtime';
2
+ import { useLunora } from '@lunora/react';
3
+ import { useState, useRef, useEffect, useMemo, useCallback } from 'react';
4
+ import { ConfirmButton } from './ConfirmButton-C2eVi2Qv.js';
5
+ import { ShardInput } from './ShardInput-gx_DZXXn.js';
6
+ import { E as EmptyState } from './empty-state-DY_oe0k6.js';
7
+ import { useT } from './DEFAULT_LOCALE-CiX4W7Kr.js';
8
+ import { ADMIN_FUNCTIONS } from './ADMIN_FUNCTIONS-DjXgvJb6.js';
9
+ import { h as formatCell, f as fireAndForget, c as callOptions, a as adminRef, b as formatTimestamp } from './internal-rXJEAhXS.js';
10
+ import { useReactTable, getSortedRowModel, getCoreRowModel, flexRender } from '@tanstack/react-table';
11
+ import { useVirtualizer } from '@tanstack/react-virtual';
12
+ import { C as Checkbox } from './checkbox-UNkzAxl-.js';
13
+ import { c as cn } from './utils-B05Dmz_H.js';
14
+ import { f as flooredRectObserver } from './virtual-rect-CVMUskSm.js';
15
+ import { G as GridContainer, C as CellValue, T as TransposedTable } from './data-grid-B5CaV3wS.js';
16
+ import { jsxDEV, Fragment } from 'react/jsx-dev-runtime';
17
+ import { u as useFacets, T as TableListSidebar, G as GridPagination, D as DataFacets } from './table-list-sidebar-Bg7uzbvC.js';
18
+ import { toFilterClauses, DataFilters } from './DataFilters-FNquMaiu.js';
19
+ import { M as ModalShell, G as GridActionsBar, C as CellDetailDialog } from './grid-features-CzUfqgsM.js';
20
+ import { u as useAdminQuery } from './use-admin-query-4JQW2rr1.js';
21
+ import useDebounced from './useDebounced-Dxncpg6z.js';
22
+ import { r as recordShard, l as loadRecentShards } from './shard-history-DyebH1R5.js';
23
+
24
+ const CAMEL_BOUNDARY_RE = /([a-z\d])([A-Z])/gu;
25
+ const WORD_SEPARATOR_RE = /[\s_-]+/u;
26
+ const SENSITIVE_COLUMN_NAMES = /* @__PURE__ */ new Set(["access_token", "api_key", "apikey", "card_number", "client_secret", "credit_card", "cvv", "passwd", "password", "private_key", "pwd", "refresh_token", "secret", "ssn", "token"]);
27
+ const tokenize = (name) => {
28
+ const segments = name.replaceAll(CAMEL_BOUNDARY_RE, "$1 $2").split(WORD_SEPARATOR_RE).map((part) => part.toLowerCase()).filter((part) => part.length > 0);
29
+ const tokens = new Set(segments);
30
+ for (let index = 0; index < segments.length - 1; index += 1) {
31
+ const current = segments[index];
32
+ const next = segments[index + 1];
33
+ if (current === void 0 || next === void 0) {
34
+ continue;
35
+ }
36
+ tokens.add(`${current}${next}`);
37
+ tokens.add(`${current}_${next}`);
38
+ }
39
+ return [...tokens];
40
+ };
41
+ const CUSTOM_MASK_SENTINEL = "•••";
42
+ const fnv1aHex = (input) => {
43
+ let hash = 2166136261;
44
+ for (let index = 0; index < input.length; index += 1) {
45
+ hash ^= input.codePointAt(index) ?? 0;
46
+ hash = Math.imul(hash, 16777619);
47
+ }
48
+ return (hash >>> 0).toString(16).padStart(8, "0");
49
+ };
50
+ const maskValue = (value, strategy) => {
51
+ try {
52
+ if (strategy === "redact") {
53
+ return null;
54
+ }
55
+ if (strategy === "hash") {
56
+ if (value === null || value === void 0) {
57
+ return value;
58
+ }
59
+ return fnv1aHex(typeof value === "string" ? value : JSON.stringify(value));
60
+ }
61
+ return CUSTOM_MASK_SENTINEL;
62
+ } catch {
63
+ return CUSTOM_MASK_SENTINEL;
64
+ }
65
+ };
66
+ const maskColumnsForTable = (columns, table) => {
67
+ const map = /* @__PURE__ */ new Map();
68
+ for (const entry of columns) {
69
+ if (entry.table === table) {
70
+ map.set(entry.column, entry.strategy);
71
+ }
72
+ }
73
+ return map;
74
+ };
75
+ const isSensitiveColumnName = (name) => {
76
+ for (const token of tokenize(name)) {
77
+ if (SENSITIVE_COLUMN_NAMES.has(token)) {
78
+ return true;
79
+ }
80
+ }
81
+ return false;
82
+ };
83
+ const mergeSensitiveColumns = (explicit, columnNames) => {
84
+ const heuristic = columnNames.filter((column) => !explicit.has(column) && isSensitiveColumnName(column));
85
+ if (heuristic.length === 0) {
86
+ return explicit;
87
+ }
88
+ const merged = new Map(explicit);
89
+ for (const column of heuristic) {
90
+ merged.set(column, "redact");
91
+ }
92
+ return merged;
93
+ };
94
+ const maskCell = (value, column, view) => {
95
+ if (!view.enabled) {
96
+ return value;
97
+ }
98
+ const strategy = view.columns.get(column);
99
+ return strategy === void 0 ? value : maskValue(value, strategy);
100
+ };
101
+ const maskRows = (rows, view) => {
102
+ if (!view.enabled || view.columns.size === 0) {
103
+ return rows;
104
+ }
105
+ return rows.map((row) => {
106
+ const masked = {
107
+ ...row
108
+ };
109
+ for (const [column, strategy] of view.columns) {
110
+ if (column in masked) {
111
+ masked[column] = maskValue(masked[column], strategy);
112
+ }
113
+ }
114
+ return masked;
115
+ });
116
+ };
117
+
118
+ const useStagedEdits = () => {
119
+ const $ = c(11);
120
+ let t0;
121
+ if ($[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
122
+ t0 = {};
123
+ $[0] = t0;
124
+ } else {
125
+ t0 = $[0];
126
+ }
127
+ const [staged, setStaged] = useState(t0);
128
+ let t1;
129
+ if ($[1] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
130
+ t1 = (rowId, column, value) => {
131
+ setStaged((previous) => ({
132
+ ...previous,
133
+ [rowId]: {
134
+ ...previous[rowId],
135
+ [column]: value
136
+ }
137
+ }));
138
+ };
139
+ $[1] = t1;
140
+ } else {
141
+ t1 = $[1];
142
+ }
143
+ const stage = t1;
144
+ let t2;
145
+ if ($[2] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
146
+ t2 = () => {
147
+ setStaged({});
148
+ };
149
+ $[2] = t2;
150
+ } else {
151
+ t2 = $[2];
152
+ }
153
+ const clear = t2;
154
+ let t3;
155
+ if ($[3] !== staged) {
156
+ t3 = (rowId_0, column_0) => {
157
+ const row = staged[rowId_0];
158
+ return row !== void 0 && column_0 in row ? {
159
+ value: row[column_0]
160
+ } : void 0;
161
+ };
162
+ $[3] = staged;
163
+ $[4] = t3;
164
+ } else {
165
+ t3 = $[4];
166
+ }
167
+ const stagedValue = t3;
168
+ let t4;
169
+ if ($[5] !== staged) {
170
+ t4 = Object.values(staged).reduce(_temp$1, 0);
171
+ $[5] = staged;
172
+ $[6] = t4;
173
+ } else {
174
+ t4 = $[6];
175
+ }
176
+ const count = t4;
177
+ let t5;
178
+ if ($[7] !== count || $[8] !== staged || $[9] !== stagedValue) {
179
+ t5 = {
180
+ clear,
181
+ count,
182
+ stage,
183
+ staged,
184
+ stagedValue
185
+ };
186
+ $[7] = count;
187
+ $[8] = staged;
188
+ $[9] = stagedValue;
189
+ $[10] = t5;
190
+ } else {
191
+ t5 = $[10];
192
+ }
193
+ return t5;
194
+ };
195
+ const coerceCellValue = (raw, original) => {
196
+ if (typeof original === "number") {
197
+ const parsed = Number(raw);
198
+ return raw.trim() === "" || Number.isNaN(parsed) ? raw : parsed;
199
+ }
200
+ if (typeof original === "boolean") {
201
+ if (raw === "true") {
202
+ return true;
203
+ }
204
+ if (raw === "false") {
205
+ return false;
206
+ }
207
+ }
208
+ return raw;
209
+ };
210
+ const StagedDiffPanel = (t0) => {
211
+ const $ = c(29);
212
+ const {
213
+ changes,
214
+ committing,
215
+ onCommit,
216
+ onDiscard
217
+ } = t0;
218
+ const t = useT();
219
+ let t1;
220
+ if ($[0] !== changes.length || $[1] !== t) {
221
+ t1 = t("{count} pending changes", {
222
+ count: changes.length
223
+ });
224
+ $[0] = changes.length;
225
+ $[1] = t;
226
+ $[2] = t1;
227
+ } else {
228
+ t1 = $[2];
229
+ }
230
+ let t2;
231
+ if ($[3] !== t1) {
232
+ t2 = /* @__PURE__ */ jsxDEV("span", {
233
+ className: "font-mono text-[11px] tracking-wide uppercase text-warning",
234
+ "data-testid": "db-staged-count",
235
+ children: t1
236
+ }, void 0, false);
237
+ $[3] = t1;
238
+ $[4] = t2;
239
+ } else {
240
+ t2 = $[4];
241
+ }
242
+ let t3;
243
+ if ($[5] !== committing || $[6] !== t) {
244
+ t3 = committing ? t("Committing…") : t("Commit");
245
+ $[5] = committing;
246
+ $[6] = t;
247
+ $[7] = t3;
248
+ } else {
249
+ t3 = $[7];
250
+ }
251
+ let t4;
252
+ if ($[8] !== committing || $[9] !== onCommit || $[10] !== t3) {
253
+ t4 = /* @__PURE__ */ jsxDEV("button", {
254
+ className: "ms-auto rounded-md bg-primary px-2.5 py-1 text-xs font-medium text-primary-foreground outline-none transition-colors hover:bg-primary/90 focus-visible:bg-primary/90 disabled:pointer-events-none disabled:opacity-50",
255
+ "data-testid": "db-staged-commit",
256
+ disabled: committing,
257
+ onClick: onCommit,
258
+ type: "button",
259
+ children: t3
260
+ }, void 0, false);
261
+ $[8] = committing;
262
+ $[9] = onCommit;
263
+ $[10] = t3;
264
+ $[11] = t4;
265
+ } else {
266
+ t4 = $[11];
267
+ }
268
+ let t5;
269
+ if ($[12] !== t) {
270
+ t5 = t("Discard");
271
+ $[12] = t;
272
+ $[13] = t5;
273
+ } else {
274
+ t5 = $[13];
275
+ }
276
+ let t6;
277
+ if ($[14] !== committing || $[15] !== onDiscard || $[16] !== t5) {
278
+ t6 = /* @__PURE__ */ jsxDEV("button", {
279
+ className: "rounded-md border border-border px-2.5 py-1 text-xs font-medium text-foreground outline-none transition-colors hover:bg-accent focus-visible:bg-accent disabled:pointer-events-none disabled:opacity-50",
280
+ "data-testid": "db-staged-discard",
281
+ disabled: committing,
282
+ onClick: onDiscard,
283
+ type: "button",
284
+ children: t5
285
+ }, void 0, false);
286
+ $[14] = committing;
287
+ $[15] = onDiscard;
288
+ $[16] = t5;
289
+ $[17] = t6;
290
+ } else {
291
+ t6 = $[17];
292
+ }
293
+ let t7;
294
+ if ($[18] !== t2 || $[19] !== t4 || $[20] !== t6) {
295
+ t7 = /* @__PURE__ */ jsxDEV("div", {
296
+ className: "flex flex-wrap items-center gap-2",
297
+ children: [t2, t4, t6]
298
+ }, void 0, true);
299
+ $[18] = t2;
300
+ $[19] = t4;
301
+ $[20] = t6;
302
+ $[21] = t7;
303
+ } else {
304
+ t7 = $[21];
305
+ }
306
+ let t8;
307
+ if ($[22] !== changes) {
308
+ t8 = changes.map(_temp2);
309
+ $[22] = changes;
310
+ $[23] = t8;
311
+ } else {
312
+ t8 = $[23];
313
+ }
314
+ let t9;
315
+ if ($[24] !== t8) {
316
+ t9 = /* @__PURE__ */ jsxDEV("ul", {
317
+ className: "flex flex-col gap-1",
318
+ "data-testid": "db-staged-list",
319
+ children: t8
320
+ }, void 0, false);
321
+ $[24] = t8;
322
+ $[25] = t9;
323
+ } else {
324
+ t9 = $[25];
325
+ }
326
+ let t10;
327
+ if ($[26] !== t7 || $[27] !== t9) {
328
+ t10 = /* @__PURE__ */ jsxDEV("div", {
329
+ className: "flex flex-col gap-2 border border-warning/40 bg-warning/5 p-3",
330
+ "data-testid": "db-staged",
331
+ children: [t7, t9]
332
+ }, void 0, true);
333
+ $[26] = t7;
334
+ $[27] = t9;
335
+ $[28] = t10;
336
+ } else {
337
+ t10 = $[28];
338
+ }
339
+ return t10;
340
+ };
341
+ function _temp$1(sum, columns) {
342
+ return sum + Object.keys(columns).length;
343
+ }
344
+ function _temp2(change) {
345
+ return /* @__PURE__ */ jsxDEV("li", {
346
+ className: "flex flex-wrap items-center gap-2 font-mono text-xs",
347
+ children: [/* @__PURE__ */ jsxDEV("span", {
348
+ className: "text-muted-foreground",
349
+ children: [change.rowId, ".", change.column]
350
+ }, void 0, true), /* @__PURE__ */ jsxDEV("span", {
351
+ className: "text-destructive line-through",
352
+ children: formatCell(change.oldValue)
353
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
354
+ "aria-hidden": "true",
355
+ className: "text-muted-foreground",
356
+ children: "→"
357
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
358
+ className: "text-foreground",
359
+ children: formatCell(change.newValue)
360
+ }, void 0, false)]
361
+ }, `${change.rowId}:${change.column}`, true);
362
+ }
363
+
364
+ const SCROLL_HEIGHT = 400;
365
+ const ROW_HEIGHT = 36;
366
+ const SCROLL_STYLE = {
367
+ flex: "1 1 0%",
368
+ minHeight: 0,
369
+ overflow: "auto",
370
+ position: "relative"
371
+ };
372
+ const ROWS_STYLE = {
373
+ width: "100%"
374
+ };
375
+ const ROW_BASE_STYLE = {
376
+ alignItems: "center",
377
+ display: "flex",
378
+ left: 0,
379
+ position: "absolute",
380
+ top: 0,
381
+ width: "100%"
382
+ };
383
+ const HEAD_ROW_STYLE = {
384
+ display: "flex",
385
+ width: "100%"
386
+ };
387
+ const ACTION_CELL_STYLE = {
388
+ flex: "0 0 8.5rem",
389
+ padding: "0.375rem 0.75rem"
390
+ };
391
+ const PINNED_DATA_LEFT = "2.5rem";
392
+ const SELECT_CELL_STYLE = {
393
+ alignItems: "center",
394
+ display: "flex",
395
+ flex: "0 0 2.5rem",
396
+ justifyContent: "center",
397
+ left: 0,
398
+ padding: "0.375rem 0",
399
+ position: "sticky",
400
+ zIndex: 2
401
+ };
402
+ const sizedCellStyle = (width) => {
403
+ return {
404
+ flex: "0 0 auto",
405
+ overflow: "hidden",
406
+ padding: "0.375rem 0.75rem",
407
+ position: "relative",
408
+ textOverflow: "ellipsis",
409
+ whiteSpace: "nowrap",
410
+ width: `${width.toString()}px`
411
+ };
412
+ };
413
+ const pinnedDataCellStyle = (width) => {
414
+ return {
415
+ ...sizedCellStyle(width),
416
+ left: PINNED_DATA_LEFT,
417
+ position: "sticky",
418
+ zIndex: 2
419
+ };
420
+ };
421
+ const ROW_BTN = "rounded-md px-2 py-0.5 text-xs font-medium text-muted-foreground outline-none transition-colors hover:bg-accent hover:text-foreground focus-visible:bg-accent disabled:pointer-events-none disabled:opacity-50";
422
+ const rowId = (row) => {
423
+ for (const key of ["id", "__id__", "_id"]) {
424
+ const value = row[key];
425
+ if (typeof value === "string" || typeof value === "number") {
426
+ return String(value);
427
+ }
428
+ }
429
+ return null;
430
+ };
431
+ const rowKey = (row, index) => rowId(row) ?? `row-${index.toString()}`;
432
+ const PREVIEW_FIELD_LIMIT = 8;
433
+ const RefPreviewCard = (t0) => {
434
+ const $ = c(16);
435
+ const {
436
+ anchor,
437
+ state
438
+ } = t0;
439
+ const t = useT();
440
+ let t1;
441
+ if ($[0] !== anchor.left || $[1] !== anchor.top) {
442
+ t1 = {
443
+ left: anchor.left,
444
+ position: "fixed",
445
+ top: anchor.top,
446
+ zIndex: 50
447
+ };
448
+ $[0] = anchor.left;
449
+ $[1] = anchor.top;
450
+ $[2] = t1;
451
+ } else {
452
+ t1 = $[2];
453
+ }
454
+ const style = t1;
455
+ let body;
456
+ if (state === "loading") {
457
+ let t22;
458
+ if ($[3] !== t) {
459
+ t22 = t("Loading…");
460
+ $[3] = t;
461
+ $[4] = t22;
462
+ } else {
463
+ t22 = $[4];
464
+ }
465
+ let t3;
466
+ if ($[5] !== t22) {
467
+ t3 = /* @__PURE__ */ jsxDEV("p", {
468
+ className: "px-3 py-2 text-xs text-muted-foreground",
469
+ children: t22
470
+ }, void 0, false);
471
+ $[5] = t22;
472
+ $[6] = t3;
473
+ } else {
474
+ t3 = $[6];
475
+ }
476
+ body = t3;
477
+ } else {
478
+ if (state.row === null) {
479
+ let t22;
480
+ if ($[7] !== t) {
481
+ t22 = t("No matching row.");
482
+ $[7] = t;
483
+ $[8] = t22;
484
+ } else {
485
+ t22 = $[8];
486
+ }
487
+ let t3;
488
+ if ($[9] !== t22) {
489
+ t3 = /* @__PURE__ */ jsxDEV("p", {
490
+ className: "px-3 py-2 text-xs text-muted-foreground",
491
+ children: t22
492
+ }, void 0, false);
493
+ $[9] = t22;
494
+ $[10] = t3;
495
+ } else {
496
+ t3 = $[10];
497
+ }
498
+ body = t3;
499
+ } else {
500
+ let t22;
501
+ if ($[11] !== state.row) {
502
+ const entries = Object.entries(state.row).slice(0, PREVIEW_FIELD_LIMIT);
503
+ t22 = /* @__PURE__ */ jsxDEV("dl", {
504
+ className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 px-3 py-2",
505
+ children: entries.map(_temp)
506
+ }, void 0, false);
507
+ $[11] = state.row;
508
+ $[12] = t22;
509
+ } else {
510
+ t22 = $[12];
511
+ }
512
+ body = t22;
513
+ }
514
+ }
515
+ let t2;
516
+ if ($[13] !== body || $[14] !== style) {
517
+ t2 = /* @__PURE__ */ jsxDEV("div", {
518
+ className: "pointer-events-none w-72 overflow-hidden rounded-md border border-border bg-popover text-popover-foreground",
519
+ "data-testid": "db-ref-preview",
520
+ role: "tooltip",
521
+ style,
522
+ children: body
523
+ }, void 0, false);
524
+ $[13] = body;
525
+ $[14] = style;
526
+ $[15] = t2;
527
+ } else {
528
+ t2 = $[15];
529
+ }
530
+ return t2;
531
+ };
532
+ const RefCell = (t0) => {
533
+ const $ = c(22);
534
+ const {
535
+ column,
536
+ id,
537
+ onNavigate,
538
+ onPreview,
539
+ target
540
+ } = t0;
541
+ const [anchor, setAnchor] = useState(null);
542
+ const [preview, setPreview] = useState("idle");
543
+ let t1;
544
+ if ($[0] !== id || $[1] !== onNavigate || $[2] !== target) {
545
+ t1 = () => {
546
+ onNavigate(target, id);
547
+ };
548
+ $[0] = id;
549
+ $[1] = onNavigate;
550
+ $[2] = target;
551
+ $[3] = t1;
552
+ } else {
553
+ t1 = $[3];
554
+ }
555
+ const onClick = t1;
556
+ let t2;
557
+ if ($[4] !== id || $[5] !== onPreview || $[6] !== preview || $[7] !== target) {
558
+ t2 = (event) => {
559
+ const rect = event.currentTarget.getBoundingClientRect();
560
+ setAnchor({
561
+ left: rect.left,
562
+ top: rect.bottom + 4
563
+ });
564
+ if (preview !== "idle") {
565
+ return;
566
+ }
567
+ setPreview("loading");
568
+ const load = async () => {
569
+ try {
570
+ setPreview({
571
+ row: await onPreview(target, id)
572
+ });
573
+ } catch {
574
+ setPreview({
575
+ row: null
576
+ });
577
+ }
578
+ };
579
+ fireAndForget(load());
580
+ };
581
+ $[4] = id;
582
+ $[5] = onPreview;
583
+ $[6] = preview;
584
+ $[7] = target;
585
+ $[8] = t2;
586
+ } else {
587
+ t2 = $[8];
588
+ }
589
+ const onOpen = t2;
590
+ let t3;
591
+ if ($[9] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
592
+ t3 = () => {
593
+ setAnchor(null);
594
+ };
595
+ $[9] = t3;
596
+ } else {
597
+ t3 = $[9];
598
+ }
599
+ const onCloseHover = t3;
600
+ const t4 = `db-ref-${column}`;
601
+ const t5 = `Open ${target} ${id}`;
602
+ let t6;
603
+ if ($[10] !== id || $[11] !== onClick || $[12] !== onOpen || $[13] !== t4 || $[14] !== t5) {
604
+ t6 = /* @__PURE__ */ jsxDEV("button", {
605
+ "data-testid": t4,
606
+ onBlur: onCloseHover,
607
+ onClick,
608
+ onFocus: onOpen,
609
+ onMouseEnter: onOpen,
610
+ onMouseLeave: onCloseHover,
611
+ title: t5,
612
+ type: "button",
613
+ children: [id, " ↗"]
614
+ }, void 0, true);
615
+ $[10] = id;
616
+ $[11] = onClick;
617
+ $[12] = onOpen;
618
+ $[13] = t4;
619
+ $[14] = t5;
620
+ $[15] = t6;
621
+ } else {
622
+ t6 = $[15];
623
+ }
624
+ let t7;
625
+ if ($[16] !== anchor || $[17] !== preview) {
626
+ t7 = anchor !== null && preview !== "idle" && /* @__PURE__ */ jsxDEV(RefPreviewCard, {
627
+ anchor,
628
+ state: preview
629
+ }, void 0, false);
630
+ $[16] = anchor;
631
+ $[17] = preview;
632
+ $[18] = t7;
633
+ } else {
634
+ t7 = $[18];
635
+ }
636
+ let t8;
637
+ if ($[19] !== t6 || $[20] !== t7) {
638
+ t8 = /* @__PURE__ */ jsxDEV(Fragment, {
639
+ children: [t6, t7]
640
+ }, void 0, true);
641
+ $[19] = t6;
642
+ $[20] = t7;
643
+ $[21] = t8;
644
+ } else {
645
+ t8 = $[21];
646
+ }
647
+ return t8;
648
+ };
649
+ const sortIndicator = (sorted) => {
650
+ if (sorted === "asc") {
651
+ return " ▲";
652
+ }
653
+ if (sorted === "desc") {
654
+ return " ▼";
655
+ }
656
+ return "";
657
+ };
658
+ const EXPAND_BTN = "absolute end-1 top-1/2 hidden -translate-y-1/2 items-center justify-center rounded text-muted-foreground outline-none group-hover/cell:flex hover:text-foreground focus-visible:flex";
659
+ const CellExpandButton = (t0) => {
660
+ const $ = c(8);
661
+ const {
662
+ column,
663
+ onExpand,
664
+ value
665
+ } = t0;
666
+ let t1;
667
+ if ($[0] !== column || $[1] !== onExpand || $[2] !== value) {
668
+ t1 = () => {
669
+ onExpand(column, value);
670
+ };
671
+ $[0] = column;
672
+ $[1] = onExpand;
673
+ $[2] = value;
674
+ $[3] = t1;
675
+ } else {
676
+ t1 = $[3];
677
+ }
678
+ const onClick = t1;
679
+ const t2 = `db-expand-${column}`;
680
+ let t3;
681
+ if ($[4] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
682
+ t3 = /* @__PURE__ */ jsxDEV("svg", {
683
+ "aria-hidden": "true",
684
+ className: "size-3",
685
+ fill: "none",
686
+ stroke: "currentColor",
687
+ strokeLinecap: "round",
688
+ strokeLinejoin: "round",
689
+ strokeWidth: 1.8,
690
+ viewBox: "0 0 24 24",
691
+ children: /* @__PURE__ */ jsxDEV("path", {
692
+ d: "M9 21H5a2 2 0 0 1-2-2v-4m18 0v4a2 2 0 0 1-2 2h-4M3 9V5a2 2 0 0 1 2-2h4m6 0h4a2 2 0 0 1 2 2v4"
693
+ }, void 0, false)
694
+ }, void 0, false);
695
+ $[4] = t3;
696
+ } else {
697
+ t3 = $[4];
698
+ }
699
+ let t4;
700
+ if ($[5] !== onClick || $[6] !== t2) {
701
+ t4 = /* @__PURE__ */ jsxDEV("button", {
702
+ "aria-label": "Expand cell",
703
+ className: EXPAND_BTN,
704
+ "data-testid": t2,
705
+ onClick,
706
+ type: "button",
707
+ children: t3
708
+ }, void 0, false);
709
+ $[5] = onClick;
710
+ $[6] = t2;
711
+ $[7] = t4;
712
+ } else {
713
+ t4 = $[7];
714
+ }
715
+ return t4;
716
+ };
717
+ const CellEditor = (t0) => {
718
+ const $ = c(14);
719
+ const {
720
+ column,
721
+ initial,
722
+ onCancel,
723
+ onCommit,
724
+ recordId
725
+ } = t0;
726
+ const ref = useRef(null);
727
+ let t1;
728
+ let t2;
729
+ if ($[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
730
+ t1 = () => {
731
+ ref.current?.select();
732
+ };
733
+ t2 = [];
734
+ $[0] = t1;
735
+ $[1] = t2;
736
+ } else {
737
+ t1 = $[0];
738
+ t2 = $[1];
739
+ }
740
+ useEffect(t1, t2);
741
+ let t3;
742
+ if ($[2] !== onCancel || $[3] !== onCommit) {
743
+ t3 = (event) => {
744
+ if (event.key === "Enter") {
745
+ event.preventDefault();
746
+ onCommit(event.currentTarget.value);
747
+ } else {
748
+ if (event.key === "Escape") {
749
+ event.preventDefault();
750
+ onCancel();
751
+ }
752
+ }
753
+ };
754
+ $[2] = onCancel;
755
+ $[3] = onCommit;
756
+ $[4] = t3;
757
+ } else {
758
+ t3 = $[4];
759
+ }
760
+ const onKeyDown = t3;
761
+ let t4;
762
+ if ($[5] !== onCommit) {
763
+ t4 = (event_0) => {
764
+ onCommit(event_0.currentTarget.value);
765
+ };
766
+ $[5] = onCommit;
767
+ $[6] = t4;
768
+ } else {
769
+ t4 = $[6];
770
+ }
771
+ const onBlur = t4;
772
+ const t5 = `db-cell-input-${recordId}-${column}`;
773
+ let t6;
774
+ if ($[7] !== initial) {
775
+ t6 = formatCell(initial);
776
+ $[7] = initial;
777
+ $[8] = t6;
778
+ } else {
779
+ t6 = $[8];
780
+ }
781
+ let t7;
782
+ if ($[9] !== onBlur || $[10] !== onKeyDown || $[11] !== t5 || $[12] !== t6) {
783
+ t7 = /* @__PURE__ */ jsxDEV("input", {
784
+ className: "w-full rounded border border-ring bg-background px-1 py-0.5 font-mono text-xs outline-none",
785
+ "data-testid": t5,
786
+ defaultValue: t6,
787
+ onBlur,
788
+ onKeyDown,
789
+ ref
790
+ }, void 0, false);
791
+ $[9] = onBlur;
792
+ $[10] = onKeyDown;
793
+ $[11] = t5;
794
+ $[12] = t6;
795
+ $[13] = t7;
796
+ } else {
797
+ t7 = $[13];
798
+ }
799
+ return t7;
800
+ };
801
+ const EditableCell = (t0) => {
802
+ const $ = c(63);
803
+ const {
804
+ cell,
805
+ edit,
806
+ mask,
807
+ refs
808
+ } = t0;
809
+ const column = cell.column.id;
810
+ let id;
811
+ let rawValue;
812
+ let t1;
813
+ let t2;
814
+ if ($[0] !== cell || $[1] !== column || $[2] !== edit || $[3] !== mask || $[4] !== refs.columns || $[5] !== refs.onNavigate || $[6] !== refs.onPreview) {
815
+ t2 = /* @__PURE__ */ Symbol.for("react.early_return_sentinel");
816
+ bb0: {
817
+ rawValue = cell.getValue();
818
+ id = rowId(cell.row.original);
819
+ const target = refs.columns?.[column];
820
+ if (mask.enabled && mask.columns.has(column)) {
821
+ const t32 = `db-masked-${column}`;
822
+ const t42 = /* @__PURE__ */ jsxDEV(CellValue, {
823
+ value: maskCell(rawValue, column, mask)
824
+ }, void 0, false);
825
+ let t52;
826
+ if ($[11] !== t32 || $[12] !== t42) {
827
+ t52 = /* @__PURE__ */ jsxDEV("span", {
828
+ className: "text-muted-foreground italic",
829
+ "data-testid": t32,
830
+ title: "Masked (preview)",
831
+ children: t42
832
+ }, void 0, false);
833
+ $[11] = t32;
834
+ $[12] = t42;
835
+ $[13] = t52;
836
+ } else {
837
+ t52 = $[13];
838
+ }
839
+ t2 = t52;
840
+ break bb0;
841
+ }
842
+ if (target !== void 0 && (typeof rawValue === "string" || typeof rawValue === "number") && String(rawValue) !== "") {
843
+ const t32 = String(rawValue);
844
+ const t42 = `${target}:${String(rawValue)}`;
845
+ let t52;
846
+ if ($[14] !== column || $[15] !== refs.onNavigate || $[16] !== refs.onPreview || $[17] !== t32 || $[18] !== t42 || $[19] !== target) {
847
+ t52 = /* @__PURE__ */ jsxDEV(RefCell, {
848
+ column,
849
+ id: t32,
850
+ onNavigate: refs.onNavigate,
851
+ onPreview: refs.onPreview,
852
+ target
853
+ }, t42, false);
854
+ $[14] = column;
855
+ $[15] = refs.onNavigate;
856
+ $[16] = refs.onPreview;
857
+ $[17] = t32;
858
+ $[18] = t42;
859
+ $[19] = target;
860
+ $[20] = t52;
861
+ } else {
862
+ t52 = $[20];
863
+ }
864
+ t2 = t52;
865
+ break bb0;
866
+ }
867
+ if (id === null) {
868
+ let t32;
869
+ if ($[21] !== rawValue) {
870
+ t32 = /* @__PURE__ */ jsxDEV(CellValue, {
871
+ value: rawValue
872
+ }, void 0, false);
873
+ $[21] = rawValue;
874
+ $[22] = t32;
875
+ } else {
876
+ t32 = $[22];
877
+ }
878
+ let t42;
879
+ if ($[23] !== column || $[24] !== edit.onExpandCell || $[25] !== rawValue) {
880
+ t42 = /* @__PURE__ */ jsxDEV(CellExpandButton, {
881
+ column,
882
+ onExpand: edit.onExpandCell,
883
+ value: rawValue
884
+ }, void 0, false);
885
+ $[23] = column;
886
+ $[24] = edit.onExpandCell;
887
+ $[25] = rawValue;
888
+ $[26] = t42;
889
+ } else {
890
+ t42 = $[26];
891
+ }
892
+ let t52;
893
+ if ($[27] !== t32 || $[28] !== t42) {
894
+ t52 = /* @__PURE__ */ jsxDEV(Fragment, {
895
+ children: [t32, t42]
896
+ }, void 0, true);
897
+ $[27] = t32;
898
+ $[28] = t42;
899
+ $[29] = t52;
900
+ } else {
901
+ t52 = $[29];
902
+ }
903
+ t2 = t52;
904
+ break bb0;
905
+ }
906
+ t1 = edit.stagedValue(id, column);
907
+ }
908
+ $[0] = cell;
909
+ $[1] = column;
910
+ $[2] = edit;
911
+ $[3] = mask;
912
+ $[4] = refs.columns;
913
+ $[5] = refs.onNavigate;
914
+ $[6] = refs.onPreview;
915
+ $[7] = id;
916
+ $[8] = rawValue;
917
+ $[9] = t1;
918
+ $[10] = t2;
919
+ } else {
920
+ id = $[7];
921
+ rawValue = $[8];
922
+ t1 = $[9];
923
+ t2 = $[10];
924
+ }
925
+ if (t2 !== /* @__PURE__ */ Symbol.for("react.early_return_sentinel")) {
926
+ return t2;
927
+ }
928
+ const staged = t1;
929
+ const display = staged === void 0 ? rawValue : staged.value;
930
+ let t3;
931
+ if ($[30] !== column || $[31] !== edit) {
932
+ t3 = edit.editable && edit.editableColumn(column);
933
+ $[30] = column;
934
+ $[31] = edit;
935
+ $[32] = t3;
936
+ } else {
937
+ t3 = $[32];
938
+ }
939
+ const canEdit = t3;
940
+ const isEditing = edit.editingCell !== null && edit.editingCell.rowId === id && edit.editingCell.column === column;
941
+ if (isEditing) {
942
+ let t42;
943
+ if ($[33] !== column || $[34] !== edit || $[35] !== id || $[36] !== rawValue) {
944
+ t42 = (raw) => {
945
+ edit.stage(id, column, coerceCellValue(raw, rawValue));
946
+ edit.cancelEdit();
947
+ };
948
+ $[33] = column;
949
+ $[34] = edit;
950
+ $[35] = id;
951
+ $[36] = rawValue;
952
+ $[37] = t42;
953
+ } else {
954
+ t42 = $[37];
955
+ }
956
+ let t52;
957
+ if ($[38] !== column || $[39] !== display || $[40] !== edit.cancelEdit || $[41] !== id || $[42] !== t42) {
958
+ t52 = /* @__PURE__ */ jsxDEV(CellEditor, {
959
+ column,
960
+ initial: display,
961
+ onCancel: edit.cancelEdit,
962
+ onCommit: t42,
963
+ recordId: id
964
+ }, void 0, false);
965
+ $[38] = column;
966
+ $[39] = display;
967
+ $[40] = edit.cancelEdit;
968
+ $[41] = id;
969
+ $[42] = t42;
970
+ $[43] = t52;
971
+ } else {
972
+ t52 = $[43];
973
+ }
974
+ return t52;
975
+ }
976
+ let cellClass;
977
+ if (staged !== void 0) {
978
+ cellClass = "rounded bg-warning/15 px-1";
979
+ } else {
980
+ if (canEdit) {
981
+ cellClass = "cursor-text";
982
+ }
983
+ }
984
+ let t4;
985
+ if ($[44] !== canEdit || $[45] !== column || $[46] !== edit || $[47] !== id) {
986
+ t4 = canEdit ? () => {
987
+ edit.startEdit(id, column);
988
+ } : void 0;
989
+ $[44] = canEdit;
990
+ $[45] = column;
991
+ $[46] = edit;
992
+ $[47] = id;
993
+ $[48] = t4;
994
+ } else {
995
+ t4 = $[48];
996
+ }
997
+ const onDoubleClick = t4;
998
+ const t5 = `db-cell-${id}-${column}`;
999
+ let t6;
1000
+ if ($[49] !== display) {
1001
+ t6 = /* @__PURE__ */ jsxDEV(CellValue, {
1002
+ value: display
1003
+ }, void 0, false);
1004
+ $[49] = display;
1005
+ $[50] = t6;
1006
+ } else {
1007
+ t6 = $[50];
1008
+ }
1009
+ let t7;
1010
+ if ($[51] !== cellClass || $[52] !== onDoubleClick || $[53] !== t5 || $[54] !== t6) {
1011
+ t7 = /* @__PURE__ */ jsxDEV("span", {
1012
+ className: cellClass,
1013
+ "data-testid": t5,
1014
+ onDoubleClick,
1015
+ children: t6
1016
+ }, void 0, false);
1017
+ $[51] = cellClass;
1018
+ $[52] = onDoubleClick;
1019
+ $[53] = t5;
1020
+ $[54] = t6;
1021
+ $[55] = t7;
1022
+ } else {
1023
+ t7 = $[55];
1024
+ }
1025
+ let t8;
1026
+ if ($[56] !== column || $[57] !== display || $[58] !== edit.onExpandCell) {
1027
+ t8 = /* @__PURE__ */ jsxDEV(CellExpandButton, {
1028
+ column,
1029
+ onExpand: edit.onExpandCell,
1030
+ value: display
1031
+ }, void 0, false);
1032
+ $[56] = column;
1033
+ $[57] = display;
1034
+ $[58] = edit.onExpandCell;
1035
+ $[59] = t8;
1036
+ } else {
1037
+ t8 = $[59];
1038
+ }
1039
+ let t9;
1040
+ if ($[60] !== t7 || $[61] !== t8) {
1041
+ t9 = /* @__PURE__ */ jsxDEV(Fragment, {
1042
+ children: [t7, t8]
1043
+ }, void 0, true);
1044
+ $[60] = t7;
1045
+ $[61] = t8;
1046
+ $[62] = t9;
1047
+ } else {
1048
+ t9 = $[62];
1049
+ }
1050
+ return t9;
1051
+ };
1052
+ const GridHeaderCell = ({
1053
+ draggedRef,
1054
+ header,
1055
+ masked = false,
1056
+ pinned = false,
1057
+ table
1058
+ }) => {
1059
+ const onDragStart = () => {
1060
+ draggedRef.current = header.column.id;
1061
+ };
1062
+ const onDragOver = (event) => {
1063
+ event.preventDefault();
1064
+ };
1065
+ const onDrop = () => {
1066
+ const from = draggedRef.current;
1067
+ const to = header.column.id;
1068
+ draggedRef.current = null;
1069
+ if (from === null || from === to) {
1070
+ return;
1071
+ }
1072
+ const current = table.getState().columnOrder;
1073
+ const base = current.length > 0 ? current : table.getAllLeafColumns().map((column) => column.id);
1074
+ const order = base.filter((id) => id !== from);
1075
+ const insertAt = order.indexOf(to);
1076
+ order.splice(insertAt === -1 ? order.length : insertAt, 0, from);
1077
+ table.setColumnOrder(order);
1078
+ };
1079
+ return /* @__PURE__ */ jsxDEV("th", {
1080
+ className: cn("text-start text-xs font-medium text-muted-foreground", pinned && "border-e border-border bg-muted"),
1081
+ draggable: true,
1082
+ onDragOver,
1083
+ onDragStart,
1084
+ onDrop,
1085
+ style: pinned ? pinnedDataCellStyle(header.getSize()) : sizedCellStyle(header.getSize()),
1086
+ children: [/* @__PURE__ */ jsxDEV("button", {
1087
+ className: "inline-flex max-w-full cursor-grab items-center gap-1 truncate outline-none hover:text-foreground",
1088
+ "data-testid": `db-sort-${header.column.id}`,
1089
+ onClick: header.column.getToggleSortingHandler(),
1090
+ type: "button",
1091
+ children: [flexRender(header.column.columnDef.header, header.getContext()), sortIndicator(header.column.getIsSorted())]
1092
+ }, void 0, true), masked && /* @__PURE__ */ jsxDEV("span", {
1093
+ className: "ms-1 inline-flex items-center rounded-sm bg-warning/15 px-1 text-[0.625rem] font-medium uppercase text-warning",
1094
+ "data-testid": `db-mask-chip-${header.column.id}`,
1095
+ title: "This column is masked by a mask() policy",
1096
+ children: "masked"
1097
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
1098
+ "aria-hidden": "true",
1099
+ className: "absolute inset-y-0 end-0 w-1 cursor-col-resize touch-none select-none hover:bg-ring/60 data-[resizing=true]:bg-ring",
1100
+ "data-resizing": header.column.getIsResizing(),
1101
+ "data-testid": `db-resize-${header.column.id}`,
1102
+ onMouseDown: header.getResizeHandler(),
1103
+ onTouchStart: header.getResizeHandler()
1104
+ }, void 0, false)]
1105
+ }, void 0, true);
1106
+ };
1107
+ const SelectAllHeaderCell = (t0) => {
1108
+ const $ = c(13);
1109
+ const {
1110
+ table
1111
+ } = t0;
1112
+ const t = useT();
1113
+ let t1;
1114
+ if ($[0] !== table) {
1115
+ t1 = (checked) => {
1116
+ table.toggleAllRowsSelected(checked);
1117
+ };
1118
+ $[0] = table;
1119
+ $[1] = t1;
1120
+ } else {
1121
+ t1 = $[1];
1122
+ }
1123
+ const onCheckedChange = t1;
1124
+ let t2;
1125
+ if ($[2] !== t) {
1126
+ t2 = t("Select all rows");
1127
+ $[2] = t;
1128
+ $[3] = t2;
1129
+ } else {
1130
+ t2 = $[3];
1131
+ }
1132
+ let t3;
1133
+ if ($[4] !== table) {
1134
+ t3 = table.getIsAllRowsSelected();
1135
+ $[4] = table;
1136
+ $[5] = t3;
1137
+ } else {
1138
+ t3 = $[5];
1139
+ }
1140
+ let t4;
1141
+ if ($[6] !== table) {
1142
+ t4 = table.getIsSomeRowsSelected() && !table.getIsAllRowsSelected();
1143
+ $[6] = table;
1144
+ $[7] = t4;
1145
+ } else {
1146
+ t4 = $[7];
1147
+ }
1148
+ let t5;
1149
+ if ($[8] !== onCheckedChange || $[9] !== t2 || $[10] !== t3 || $[11] !== t4) {
1150
+ t5 = /* @__PURE__ */ jsxDEV("th", {
1151
+ className: "bg-muted",
1152
+ style: SELECT_CELL_STYLE,
1153
+ children: /* @__PURE__ */ jsxDEV(Checkbox, {
1154
+ "aria-label": t2,
1155
+ checked: t3,
1156
+ "data-testid": "db-select-all",
1157
+ indeterminate: t4,
1158
+ onCheckedChange
1159
+ }, void 0, false)
1160
+ }, void 0, false);
1161
+ $[8] = onCheckedChange;
1162
+ $[9] = t2;
1163
+ $[10] = t3;
1164
+ $[11] = t4;
1165
+ $[12] = t5;
1166
+ } else {
1167
+ t5 = $[12];
1168
+ }
1169
+ return t5;
1170
+ };
1171
+ const RowSelectCell = (t0) => {
1172
+ const $ = c(17);
1173
+ const {
1174
+ row
1175
+ } = t0;
1176
+ const t = useT();
1177
+ let t1;
1178
+ if ($[0] !== row.original) {
1179
+ t1 = rowId(row.original);
1180
+ $[0] = row.original;
1181
+ $[1] = t1;
1182
+ } else {
1183
+ t1 = $[1];
1184
+ }
1185
+ const id = t1;
1186
+ let t2;
1187
+ if ($[2] !== row) {
1188
+ t2 = (checked) => {
1189
+ row.toggleSelected(checked);
1190
+ };
1191
+ $[2] = row;
1192
+ $[3] = t2;
1193
+ } else {
1194
+ t2 = $[3];
1195
+ }
1196
+ const onCheckedChange = t2;
1197
+ let t3;
1198
+ if ($[4] !== t) {
1199
+ t3 = t("Select row");
1200
+ $[4] = t;
1201
+ $[5] = t3;
1202
+ } else {
1203
+ t3 = $[5];
1204
+ }
1205
+ let t4;
1206
+ if ($[6] !== row) {
1207
+ t4 = row.getIsSelected();
1208
+ $[6] = row;
1209
+ $[7] = t4;
1210
+ } else {
1211
+ t4 = $[7];
1212
+ }
1213
+ let t5;
1214
+ if ($[8] !== row.index || $[9] !== row.original) {
1215
+ t5 = rowKey(row.original, row.index);
1216
+ $[8] = row.index;
1217
+ $[9] = row.original;
1218
+ $[10] = t5;
1219
+ } else {
1220
+ t5 = $[10];
1221
+ }
1222
+ const t6 = `db-select-${t5}`;
1223
+ const t7 = id === null;
1224
+ let t8;
1225
+ if ($[11] !== onCheckedChange || $[12] !== t3 || $[13] !== t4 || $[14] !== t6 || $[15] !== t7) {
1226
+ t8 = /* @__PURE__ */ jsxDEV("td", {
1227
+ className: "bg-background",
1228
+ style: SELECT_CELL_STYLE,
1229
+ children: /* @__PURE__ */ jsxDEV(Checkbox, {
1230
+ "aria-label": t3,
1231
+ checked: t4,
1232
+ "data-testid": t6,
1233
+ disabled: t7,
1234
+ onCheckedChange
1235
+ }, void 0, false)
1236
+ }, void 0, false);
1237
+ $[11] = onCheckedChange;
1238
+ $[12] = t3;
1239
+ $[13] = t4;
1240
+ $[14] = t6;
1241
+ $[15] = t7;
1242
+ $[16] = t8;
1243
+ } else {
1244
+ t8 = $[16];
1245
+ }
1246
+ return t8;
1247
+ };
1248
+ const DataBrowserTableView = (t0) => {
1249
+ const $ = c(46);
1250
+ const {
1251
+ edit,
1252
+ editable,
1253
+ mask,
1254
+ onDelete,
1255
+ onEdit,
1256
+ onInspect,
1257
+ refs,
1258
+ scrollRef,
1259
+ scrollToIndex,
1260
+ table,
1261
+ tableRows,
1262
+ tbodyStyle,
1263
+ virtualRows
1264
+ } = t0;
1265
+ const draggedColumn = useRef(null);
1266
+ const [active, setActive] = useState(null);
1267
+ let t1;
1268
+ if ($[0] !== table) {
1269
+ t1 = table.getVisibleLeafColumns();
1270
+ $[0] = table;
1271
+ $[1] = t1;
1272
+ } else {
1273
+ t1 = $[1];
1274
+ }
1275
+ const columnCount = t1.length;
1276
+ let t2;
1277
+ if ($[2] !== active || $[3] !== columnCount || $[4] !== edit || $[5] !== table || $[6] !== tableRows) {
1278
+ t2 = (event) => {
1279
+ if (!["ArrowDown", "ArrowLeft", "ArrowRight", "ArrowUp", "Enter"].includes(event.key)) {
1280
+ return;
1281
+ }
1282
+ event.preventDefault();
1283
+ const current = active ?? {
1284
+ col: 0,
1285
+ row: 0
1286
+ };
1287
+ if (event.key === "Enter") {
1288
+ const row = tableRows[current.row];
1289
+ const column = table.getVisibleLeafColumns()[current.col];
1290
+ if (row !== void 0 && column !== void 0) {
1291
+ const id = rowId(row.original);
1292
+ if (id !== null && edit.editableColumn(column.id)) {
1293
+ edit.startEdit(id, column.id);
1294
+ }
1295
+ }
1296
+ setActive(current);
1297
+ return;
1298
+ }
1299
+ let {
1300
+ col,
1301
+ row: row_0
1302
+ } = current;
1303
+ bb24: switch (event.key) {
1304
+ case "ArrowDown": {
1305
+ row_0 = Math.min(row_0 + 1, tableRows.length - 1);
1306
+ break bb24;
1307
+ }
1308
+ case "ArrowRight": {
1309
+ col = Math.min(col + 1, columnCount - 1);
1310
+ break bb24;
1311
+ }
1312
+ case "ArrowUp": {
1313
+ row_0 = Math.max(row_0 - 1, 0);
1314
+ break bb24;
1315
+ }
1316
+ default: {
1317
+ col = Math.max(col - 1, 0);
1318
+ }
1319
+ }
1320
+ setActive({
1321
+ col,
1322
+ row: row_0
1323
+ });
1324
+ };
1325
+ $[2] = active;
1326
+ $[3] = columnCount;
1327
+ $[4] = edit;
1328
+ $[5] = table;
1329
+ $[6] = tableRows;
1330
+ $[7] = t2;
1331
+ } else {
1332
+ t2 = $[7];
1333
+ }
1334
+ const onGridKeyDown = t2;
1335
+ let t3;
1336
+ let t4;
1337
+ if ($[8] !== active || $[9] !== scrollToIndex) {
1338
+ t3 = () => {
1339
+ if (active !== null) {
1340
+ scrollToIndex(active.row);
1341
+ }
1342
+ };
1343
+ t4 = [active, scrollToIndex];
1344
+ $[8] = active;
1345
+ $[9] = scrollToIndex;
1346
+ $[10] = t3;
1347
+ $[11] = t4;
1348
+ } else {
1349
+ t3 = $[10];
1350
+ t4 = $[11];
1351
+ }
1352
+ useEffect(t3, t4);
1353
+ let t5;
1354
+ if ($[12] !== active || $[13] !== edit || $[14] !== editable || $[15] !== mask || $[16] !== onDelete || $[17] !== onEdit || $[18] !== onInspect || $[19] !== refs || $[20] !== tableRows) {
1355
+ t5 = (virtualRow) => {
1356
+ const tableRow = tableRows[virtualRow.index];
1357
+ const {
1358
+ original
1359
+ } = tableRow;
1360
+ const id_0 = rowId(original);
1361
+ const key = rowKey(original, virtualRow.index);
1362
+ const rowStyle = {
1363
+ ...ROW_BASE_STYLE,
1364
+ height: `${virtualRow.size.toString()}px`,
1365
+ transform: `translateY(${virtualRow.start.toString()}px)`
1366
+ };
1367
+ return /* @__PURE__ */ jsxDEV("tr", {
1368
+ className: "border-b border-border text-xs transition-colors hover:bg-muted/50",
1369
+ "data-testid": "db-row",
1370
+ style: rowStyle,
1371
+ children: [/* @__PURE__ */ jsxDEV(RowSelectCell, {
1372
+ row: tableRow
1373
+ }, void 0, false), tableRow.getVisibleCells().map((cell, colIndex) => {
1374
+ const pinned = colIndex === 0;
1375
+ const ring = active !== null && active.row === virtualRow.index && active.col === colIndex ? " ring-1 ring-ring ring-inset" : "";
1376
+ return /* @__PURE__ */ jsxDEV("td", {
1377
+ className: cn("group/cell truncate font-mono text-muted-foreground", pinned && "border-e border-border bg-background", ring),
1378
+ style: pinned ? pinnedDataCellStyle(cell.column.getSize()) : sizedCellStyle(cell.column.getSize()),
1379
+ children: /* @__PURE__ */ jsxDEV(EditableCell, {
1380
+ cell,
1381
+ edit,
1382
+ mask,
1383
+ refs
1384
+ }, void 0, false)
1385
+ }, cell.id, false);
1386
+ }), /* @__PURE__ */ jsxDEV("td", {
1387
+ className: "flex items-center gap-1",
1388
+ style: ACTION_CELL_STYLE,
1389
+ children: [/* @__PURE__ */ jsxDEV("button", {
1390
+ className: ROW_BTN,
1391
+ "data-testid": `db-inspect-${key}`,
1392
+ onClick: () => {
1393
+ onInspect(original);
1394
+ },
1395
+ type: "button",
1396
+ children: "Details"
1397
+ }, void 0, false), editable && /* @__PURE__ */ jsxDEV(Fragment, {
1398
+ children: [/* @__PURE__ */ jsxDEV("button", {
1399
+ className: ROW_BTN,
1400
+ "data-testid": `db-edit-${key}`,
1401
+ disabled: id_0 === null,
1402
+ onClick: () => {
1403
+ onEdit(id_0, original);
1404
+ },
1405
+ type: "button",
1406
+ children: "Edit"
1407
+ }, void 0, false), /* @__PURE__ */ jsxDEV(ConfirmButton, {
1408
+ confirmLabel: "Delete?",
1409
+ disabled: id_0 === null,
1410
+ onConfirm: () => {
1411
+ onDelete(id_0);
1412
+ },
1413
+ testId: `db-delete-${key}`,
1414
+ children: "Delete"
1415
+ }, void 0, false)]
1416
+ }, void 0, true)]
1417
+ }, void 0, true)]
1418
+ }, tableRow.id, true);
1419
+ };
1420
+ $[12] = active;
1421
+ $[13] = edit;
1422
+ $[14] = editable;
1423
+ $[15] = mask;
1424
+ $[16] = onDelete;
1425
+ $[17] = onEdit;
1426
+ $[18] = onInspect;
1427
+ $[19] = refs;
1428
+ $[20] = tableRows;
1429
+ $[21] = t5;
1430
+ } else {
1431
+ t5 = $[21];
1432
+ }
1433
+ const renderRow = t5;
1434
+ let t6;
1435
+ if ($[22] !== table) {
1436
+ t6 = /* @__PURE__ */ jsxDEV(SelectAllHeaderCell, {
1437
+ table
1438
+ }, void 0, false);
1439
+ $[22] = table;
1440
+ $[23] = t6;
1441
+ } else {
1442
+ t6 = $[23];
1443
+ }
1444
+ let t7;
1445
+ if ($[24] !== mask || $[25] !== table) {
1446
+ t7 = table.getFlatHeaders().map((header, index) => /* @__PURE__ */ jsxDEV(GridHeaderCell, {
1447
+ draggedRef: draggedColumn,
1448
+ header,
1449
+ masked: mask.columns.has(header.column.id),
1450
+ pinned: index === 0,
1451
+ table
1452
+ }, header.id, false));
1453
+ $[24] = mask;
1454
+ $[25] = table;
1455
+ $[26] = t7;
1456
+ } else {
1457
+ t7 = $[26];
1458
+ }
1459
+ let t8;
1460
+ if ($[27] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
1461
+ t8 = /* @__PURE__ */ jsxDEV("th", {
1462
+ "aria-label": "Row actions",
1463
+ style: ACTION_CELL_STYLE
1464
+ }, void 0, false);
1465
+ $[27] = t8;
1466
+ } else {
1467
+ t8 = $[27];
1468
+ }
1469
+ let t9;
1470
+ if ($[28] !== t6 || $[29] !== t7) {
1471
+ t9 = /* @__PURE__ */ jsxDEV("thead", {
1472
+ className: "bg-muted/50",
1473
+ children: /* @__PURE__ */ jsxDEV("tr", {
1474
+ className: "border-b border-border",
1475
+ style: HEAD_ROW_STYLE,
1476
+ children: [t6, t7, t8]
1477
+ }, void 0, true)
1478
+ }, void 0, false);
1479
+ $[28] = t6;
1480
+ $[29] = t7;
1481
+ $[30] = t9;
1482
+ } else {
1483
+ t9 = $[30];
1484
+ }
1485
+ let t10;
1486
+ if ($[31] !== renderRow || $[32] !== virtualRows) {
1487
+ let t112;
1488
+ if ($[34] !== renderRow) {
1489
+ t112 = (virtualRow_0) => renderRow(virtualRow_0);
1490
+ $[34] = renderRow;
1491
+ $[35] = t112;
1492
+ } else {
1493
+ t112 = $[35];
1494
+ }
1495
+ t10 = virtualRows.map(t112);
1496
+ $[31] = renderRow;
1497
+ $[32] = virtualRows;
1498
+ $[33] = t10;
1499
+ } else {
1500
+ t10 = $[33];
1501
+ }
1502
+ let t11;
1503
+ if ($[36] !== t10 || $[37] !== tbodyStyle) {
1504
+ t11 = /* @__PURE__ */ jsxDEV("tbody", {
1505
+ style: tbodyStyle,
1506
+ children: t10
1507
+ }, void 0, false);
1508
+ $[36] = t10;
1509
+ $[37] = tbodyStyle;
1510
+ $[38] = t11;
1511
+ } else {
1512
+ t11 = $[38];
1513
+ }
1514
+ let t12;
1515
+ if ($[39] !== t11 || $[40] !== t9) {
1516
+ t12 = /* @__PURE__ */ jsxDEV("table", {
1517
+ className: "w-full text-xs",
1518
+ "data-testid": "db-rows",
1519
+ style: ROWS_STYLE,
1520
+ children: [t9, t11]
1521
+ }, void 0, true);
1522
+ $[39] = t11;
1523
+ $[40] = t9;
1524
+ $[41] = t12;
1525
+ } else {
1526
+ t12 = $[41];
1527
+ }
1528
+ let t13;
1529
+ if ($[42] !== onGridKeyDown || $[43] !== scrollRef || $[44] !== t12) {
1530
+ t13 = /* @__PURE__ */ jsxDEV(GridContainer, {
1531
+ layout: "fill",
1532
+ children: /* @__PURE__ */ jsxDEV("div", {
1533
+ "data-testid": "db-scroll",
1534
+ onKeyDown: onGridKeyDown,
1535
+ ref: scrollRef,
1536
+ role: "grid",
1537
+ style: SCROLL_STYLE,
1538
+ tabIndex: 0,
1539
+ children: t12
1540
+ }, void 0, false)
1541
+ }, void 0, false);
1542
+ $[42] = onGridKeyDown;
1543
+ $[43] = scrollRef;
1544
+ $[44] = t12;
1545
+ $[45] = t13;
1546
+ } else {
1547
+ t13 = $[45];
1548
+ }
1549
+ return t13;
1550
+ };
1551
+ const useDataBrowserTable = (page, sorting, onSortingChange) => {
1552
+ const columns = page?.columns;
1553
+ const rows = page?.rows;
1554
+ const references = page?.refs;
1555
+ const columnDefs = useMemo(() => {
1556
+ if (columns === void 0) {
1557
+ return [];
1558
+ }
1559
+ return columns.map((column) => {
1560
+ return {
1561
+ accessorFn: (row) => row[column],
1562
+ header: references?.[column] === void 0 ? column : `${column} →`,
1563
+ id: column
1564
+ };
1565
+ });
1566
+ }, [columns, references]);
1567
+ const data = rows ?? [];
1568
+ const [rowSelection, setRowSelection] = useState({});
1569
+ const [columnVisibility, setColumnVisibility] = useState({});
1570
+ const table = useReactTable({
1571
+ columnResizeMode: "onChange",
1572
+ columns: columnDefs,
1573
+ data,
1574
+ defaultColumn: {
1575
+ minSize: 80,
1576
+ size: 200
1577
+ },
1578
+ enableColumnResizing: true,
1579
+ enableRowSelection: (row_0) => rowId(row_0.original) !== null,
1580
+ getCoreRowModel: getCoreRowModel(),
1581
+ getRowId: (row_1, index) => rowId(row_1) ?? `row-${index.toString()}`,
1582
+ getSortedRowModel: getSortedRowModel(),
1583
+ // Sorting is server-side: the page arrives already ordered, so the table
1584
+ // must not re-sort it. The header still toggles `sorting`, which the data
1585
+ // browser forwards to `readTablePage` as `orderBy`.
1586
+ manualSorting: true,
1587
+ onColumnVisibilityChange: setColumnVisibility,
1588
+ onRowSelectionChange: setRowSelection,
1589
+ onSortingChange,
1590
+ state: {
1591
+ columnVisibility,
1592
+ rowSelection,
1593
+ sorting
1594
+ }
1595
+ });
1596
+ const tableRows = table.getRowModel().rows;
1597
+ const scrollRef = useRef(null);
1598
+ const virtualizer = useVirtualizer({
1599
+ count: tableRows.length,
1600
+ estimateSize: () => ROW_HEIGHT,
1601
+ getScrollElement: () => scrollRef.current,
1602
+ initialRect: {
1603
+ height: SCROLL_HEIGHT,
1604
+ width: 0
1605
+ },
1606
+ observeElementRect: (instance, callback) => flooredRectObserver(instance, callback, SCROLL_HEIGHT),
1607
+ overscan: 8
1608
+ });
1609
+ const scrollToIndex = useCallback((index_0) => {
1610
+ virtualizer.scrollToIndex(index_0);
1611
+ }, [virtualizer]);
1612
+ const virtualRows = virtualizer.getVirtualItems();
1613
+ const totalSize = virtualizer.getTotalSize();
1614
+ const tbodyStyle = {
1615
+ display: "block",
1616
+ height: `${totalSize.toString()}px`,
1617
+ position: "relative"
1618
+ };
1619
+ return {
1620
+ scrollRef,
1621
+ scrollToIndex,
1622
+ table,
1623
+ tableRows,
1624
+ tbodyStyle,
1625
+ virtualRows
1626
+ };
1627
+ };
1628
+ function _temp(t0) {
1629
+ const [key, value] = t0;
1630
+ return /* @__PURE__ */ jsxDEV("div", {
1631
+ className: "contents",
1632
+ children: [/* @__PURE__ */ jsxDEV("dt", {
1633
+ className: "truncate font-mono text-[11px] text-muted-foreground",
1634
+ children: key
1635
+ }, void 0, false), /* @__PURE__ */ jsxDEV("dd", {
1636
+ className: "truncate font-mono text-[11px] text-foreground",
1637
+ title: formatCell(value),
1638
+ children: formatCell(value)
1639
+ }, void 0, false)]
1640
+ }, key, true);
1641
+ }
1642
+
1643
+ const CONTROL_BTN$2 = "inline-flex items-center gap-1 rounded-md border border-border px-2.5 py-1 text-xs font-medium text-foreground outline-none transition-colors hover:bg-accent focus-visible:bg-accent disabled:pointer-events-none disabled:opacity-50";
1644
+ const SaveQueryInput = (t0) => {
1645
+ const $ = c(22);
1646
+ const {
1647
+ onCommit
1648
+ } = t0;
1649
+ const t = useT();
1650
+ const [draft, setDraft] = useState("");
1651
+ const ref = useRef(null);
1652
+ let t1;
1653
+ let t2;
1654
+ if ($[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
1655
+ t1 = () => {
1656
+ ref.current?.focus();
1657
+ };
1658
+ t2 = [];
1659
+ $[0] = t1;
1660
+ $[1] = t2;
1661
+ } else {
1662
+ t1 = $[0];
1663
+ t2 = $[1];
1664
+ }
1665
+ useEffect(t1, t2);
1666
+ let t3;
1667
+ if ($[2] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
1668
+ t3 = (event) => {
1669
+ setDraft(event.target.value);
1670
+ };
1671
+ $[2] = t3;
1672
+ } else {
1673
+ t3 = $[2];
1674
+ }
1675
+ const onChange = t3;
1676
+ let t4;
1677
+ if ($[3] !== draft || $[4] !== onCommit) {
1678
+ t4 = () => {
1679
+ const name = draft.trim();
1680
+ if (name !== "") {
1681
+ onCommit(name);
1682
+ }
1683
+ };
1684
+ $[3] = draft;
1685
+ $[4] = onCommit;
1686
+ $[5] = t4;
1687
+ } else {
1688
+ t4 = $[5];
1689
+ }
1690
+ const commit = t4;
1691
+ let t5;
1692
+ if ($[6] !== t) {
1693
+ t5 = t("Query name");
1694
+ $[6] = t;
1695
+ $[7] = t5;
1696
+ } else {
1697
+ t5 = $[7];
1698
+ }
1699
+ let t6;
1700
+ if ($[8] !== t) {
1701
+ t6 = t("Query name");
1702
+ $[8] = t;
1703
+ $[9] = t6;
1704
+ } else {
1705
+ t6 = $[9];
1706
+ }
1707
+ let t7;
1708
+ if ($[10] !== draft || $[11] !== t5 || $[12] !== t6) {
1709
+ t7 = /* @__PURE__ */ jsxDEV("input", {
1710
+ "aria-label": t5,
1711
+ className: "h-7 rounded-md border border-border bg-background px-2 text-xs outline-none focus-visible:border-ring",
1712
+ "data-testid": "db-save-query-name",
1713
+ onChange,
1714
+ placeholder: t6,
1715
+ ref,
1716
+ value: draft
1717
+ }, void 0, false);
1718
+ $[10] = draft;
1719
+ $[11] = t5;
1720
+ $[12] = t6;
1721
+ $[13] = t7;
1722
+ } else {
1723
+ t7 = $[13];
1724
+ }
1725
+ let t8;
1726
+ if ($[14] !== t) {
1727
+ t8 = t("Save");
1728
+ $[14] = t;
1729
+ $[15] = t8;
1730
+ } else {
1731
+ t8 = $[15];
1732
+ }
1733
+ let t9;
1734
+ if ($[16] !== commit || $[17] !== t8) {
1735
+ t9 = /* @__PURE__ */ jsxDEV("button", {
1736
+ className: CONTROL_BTN$2,
1737
+ "data-testid": "db-save-query-confirm",
1738
+ onClick: commit,
1739
+ type: "button",
1740
+ children: t8
1741
+ }, void 0, false);
1742
+ $[16] = commit;
1743
+ $[17] = t8;
1744
+ $[18] = t9;
1745
+ } else {
1746
+ t9 = $[18];
1747
+ }
1748
+ let t10;
1749
+ if ($[19] !== t7 || $[20] !== t9) {
1750
+ t10 = /* @__PURE__ */ jsxDEV("span", {
1751
+ className: "inline-flex items-center gap-1",
1752
+ children: [t7, t9]
1753
+ }, void 0, true);
1754
+ $[19] = t7;
1755
+ $[20] = t9;
1756
+ $[21] = t10;
1757
+ } else {
1758
+ t10 = $[21];
1759
+ }
1760
+ return t10;
1761
+ };
1762
+ const DataQueryBar = (t0) => {
1763
+ const $ = c(27);
1764
+ const {
1765
+ onApply,
1766
+ onCopyLink,
1767
+ onDelete,
1768
+ onSave,
1769
+ saved
1770
+ } = t0;
1771
+ const t = useT();
1772
+ const [naming, setNaming] = useState(false);
1773
+ let t1;
1774
+ if ($[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
1775
+ t1 = () => {
1776
+ setNaming(true);
1777
+ };
1778
+ $[0] = t1;
1779
+ } else {
1780
+ t1 = $[0];
1781
+ }
1782
+ const openNaming = t1;
1783
+ let t2;
1784
+ if ($[1] !== onSave) {
1785
+ t2 = (name) => {
1786
+ onSave(name);
1787
+ setNaming(false);
1788
+ };
1789
+ $[1] = onSave;
1790
+ $[2] = t2;
1791
+ } else {
1792
+ t2 = $[2];
1793
+ }
1794
+ const confirmSave = t2;
1795
+ let t3;
1796
+ if ($[3] !== onApply || $[4] !== saved) {
1797
+ t3 = (event) => {
1798
+ const query = saved[Number(event.currentTarget.dataset.index)];
1799
+ if (query !== void 0) {
1800
+ onApply(query);
1801
+ }
1802
+ };
1803
+ $[3] = onApply;
1804
+ $[4] = saved;
1805
+ $[5] = t3;
1806
+ } else {
1807
+ t3 = $[5];
1808
+ }
1809
+ const applyByIndex = t3;
1810
+ let t4;
1811
+ if ($[6] !== onDelete || $[7] !== saved) {
1812
+ t4 = (event_0) => {
1813
+ const query_0 = saved[Number(event_0.currentTarget.dataset.index)];
1814
+ if (query_0 !== void 0) {
1815
+ onDelete(query_0.name);
1816
+ }
1817
+ };
1818
+ $[6] = onDelete;
1819
+ $[7] = saved;
1820
+ $[8] = t4;
1821
+ } else {
1822
+ t4 = $[8];
1823
+ }
1824
+ const deleteByIndex = t4;
1825
+ let t5;
1826
+ if ($[9] !== t) {
1827
+ t5 = t("Copy link");
1828
+ $[9] = t;
1829
+ $[10] = t5;
1830
+ } else {
1831
+ t5 = $[10];
1832
+ }
1833
+ let t6;
1834
+ if ($[11] !== onCopyLink || $[12] !== t5) {
1835
+ t6 = /* @__PURE__ */ jsxDEV("button", {
1836
+ className: CONTROL_BTN$2,
1837
+ "data-testid": "db-copy-link",
1838
+ onClick: onCopyLink,
1839
+ type: "button",
1840
+ children: t5
1841
+ }, void 0, false);
1842
+ $[11] = onCopyLink;
1843
+ $[12] = t5;
1844
+ $[13] = t6;
1845
+ } else {
1846
+ t6 = $[13];
1847
+ }
1848
+ let t7;
1849
+ if ($[14] !== confirmSave || $[15] !== naming || $[16] !== t) {
1850
+ t7 = naming ? /* @__PURE__ */ jsxDEV(SaveQueryInput, {
1851
+ onCommit: confirmSave
1852
+ }, void 0, false) : /* @__PURE__ */ jsxDEV("button", {
1853
+ className: CONTROL_BTN$2,
1854
+ "data-testid": "db-save-query",
1855
+ onClick: openNaming,
1856
+ type: "button",
1857
+ children: t("Save query")
1858
+ }, void 0, false);
1859
+ $[14] = confirmSave;
1860
+ $[15] = naming;
1861
+ $[16] = t;
1862
+ $[17] = t7;
1863
+ } else {
1864
+ t7 = $[17];
1865
+ }
1866
+ let t8;
1867
+ if ($[18] !== applyByIndex || $[19] !== deleteByIndex || $[20] !== saved || $[21] !== t) {
1868
+ t8 = saved.length > 0 && /* @__PURE__ */ jsxDEV("div", {
1869
+ className: "flex flex-wrap items-center gap-1",
1870
+ "data-testid": "db-saved-queries",
1871
+ children: [/* @__PURE__ */ jsxDEV("span", {
1872
+ className: "font-mono text-[11px] tracking-wide uppercase text-muted-foreground",
1873
+ children: t("Saved")
1874
+ }, void 0, false), saved.map((query_1, index) => /* @__PURE__ */ jsxDEV("span", {
1875
+ className: "inline-flex items-center overflow-hidden rounded-md border border-border",
1876
+ children: [/* @__PURE__ */ jsxDEV("button", {
1877
+ className: "px-2 py-0.5 text-xs text-foreground transition-colors hover:bg-accent",
1878
+ "data-index": index,
1879
+ "data-testid": `db-saved-query-${query_1.name}`,
1880
+ onClick: applyByIndex,
1881
+ type: "button",
1882
+ children: query_1.name
1883
+ }, void 0, false), /* @__PURE__ */ jsxDEV("button", {
1884
+ "aria-label": t("Delete saved query {name}", {
1885
+ name: query_1.name
1886
+ }),
1887
+ className: "border-l border-border px-1 py-0.5 text-xs text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive",
1888
+ "data-index": index,
1889
+ "data-testid": `db-saved-query-delete-${query_1.name}`,
1890
+ onClick: deleteByIndex,
1891
+ type: "button",
1892
+ children: "✕"
1893
+ }, void 0, false)]
1894
+ }, query_1.name, true))]
1895
+ }, void 0, true);
1896
+ $[18] = applyByIndex;
1897
+ $[19] = deleteByIndex;
1898
+ $[20] = saved;
1899
+ $[21] = t;
1900
+ $[22] = t8;
1901
+ } else {
1902
+ t8 = $[22];
1903
+ }
1904
+ let t9;
1905
+ if ($[23] !== t6 || $[24] !== t7 || $[25] !== t8) {
1906
+ t9 = /* @__PURE__ */ jsxDEV("div", {
1907
+ className: "flex flex-wrap items-center gap-1.5",
1908
+ "data-testid": "db-query-bar",
1909
+ children: [t6, t7, t8]
1910
+ }, void 0, true);
1911
+ $[23] = t6;
1912
+ $[24] = t7;
1913
+ $[25] = t8;
1914
+ $[26] = t9;
1915
+ } else {
1916
+ t9 = $[26];
1917
+ }
1918
+ return t9;
1919
+ };
1920
+
1921
+ const SEED_ENDPOINT = "/__lunora/seed";
1922
+ const MAX_GENERATE_ROWS = 200;
1923
+ const MAX_FK_SAMPLE = 50;
1924
+ const collectSkippedFkColumns = (columns, fkPools) => {
1925
+ const skipped = [];
1926
+ for (const column of columns) {
1927
+ if (column.pk !== true && column.ref !== void 0 && column.type === "id" && (fkPools[column.ref] ?? []).length === 0) {
1928
+ skipped.push(column.name);
1929
+ }
1930
+ }
1931
+ return skipped;
1932
+ };
1933
+ const requestSeedRows = async (request) => {
1934
+ const response = await fetch(SEED_ENDPOINT, {
1935
+ body: JSON.stringify(request),
1936
+ headers: {
1937
+ "Content-Type": "application/json"
1938
+ },
1939
+ method: "POST"
1940
+ });
1941
+ const body = await response.json();
1942
+ if (response.ok && body.rows !== void 0) {
1943
+ return {
1944
+ kind: "ok",
1945
+ rows: body.rows
1946
+ };
1947
+ }
1948
+ return {
1949
+ kind: "error",
1950
+ message: body.error ?? `seed request failed (${String(response.status)})`
1951
+ };
1952
+ };
1953
+
1954
+ const BTN = "rounded-md border border-border px-3 py-1.5 text-xs font-medium text-foreground outline-none transition-colors hover:bg-accent focus-visible:bg-accent disabled:pointer-events-none disabled:opacity-50";
1955
+ const BTN_DESTRUCTIVE = "rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground outline-none transition-colors hover:bg-primary/90 focus-visible:bg-primary/90 disabled:pointer-events-none disabled:opacity-50";
1956
+ const GenerateRowsDialog = ({
1957
+ columns,
1958
+ fkPools,
1959
+ onClose,
1960
+ onInsertRows,
1961
+ table
1962
+ }) => {
1963
+ const t = useT();
1964
+ const [count, setCount] = useState(10);
1965
+ const [inserting, setInserting] = useState(false);
1966
+ const [error, setError] = useState(void 0);
1967
+ const [inserted, setInserted] = useState(void 0);
1968
+ const onCountChange = (event) => {
1969
+ const next = Number(event.target.value);
1970
+ if (!Number.isNaN(next) && next >= 1) {
1971
+ setCount(Math.min(next, MAX_GENERATE_ROWS));
1972
+ }
1973
+ };
1974
+ const handleGenerate = async () => {
1975
+ setError(void 0);
1976
+ setInserted(void 0);
1977
+ setInserting(true);
1978
+ try {
1979
+ const generated = await requestSeedRows({
1980
+ count,
1981
+ existingIds: fkPools,
1982
+ seed: Date.now(),
1983
+ table
1984
+ });
1985
+ if (generated.kind === "error") {
1986
+ setError(generated.message);
1987
+ return;
1988
+ }
1989
+ const {
1990
+ rows
1991
+ } = generated;
1992
+ if (rows.length === 0) {
1993
+ setError(t("No rows generated — all columns were skipped."));
1994
+ return;
1995
+ }
1996
+ const result = await onInsertRows(rows);
1997
+ if (result !== void 0) {
1998
+ setError(result);
1999
+ return;
2000
+ }
2001
+ setInserted(rows.length);
2002
+ const skippedFkColumns = collectSkippedFkColumns(columns, fkPools);
2003
+ if (skippedFkColumns.length > 0) {
2004
+ setError(t("Inserted {count} rows. Skipped FK columns: {cols}", {
2005
+ cols: skippedFkColumns.join(", "),
2006
+ count: rows.length.toString()
2007
+ }));
2008
+ }
2009
+ } finally {
2010
+ setInserting(false);
2011
+ }
2012
+ };
2013
+ const onGenerate = () => {
2014
+ fireAndForget(handleGenerate());
2015
+ };
2016
+ const editableColumns = columns.filter((column) => column.pk !== true);
2017
+ return /* @__PURE__ */ jsxDEV(ModalShell, {
2018
+ label: t("Generate dummy rows"),
2019
+ onClose,
2020
+ panelTestId: "gen-rows-panel",
2021
+ testId: "gen-rows-overlay",
2022
+ variant: "dialog",
2023
+ children: [/* @__PURE__ */ jsxDEV("div", {
2024
+ className: "flex items-start justify-between",
2025
+ children: [/* @__PURE__ */ jsxDEV("div", {
2026
+ className: "flex flex-col gap-0.5",
2027
+ children: [/* @__PURE__ */ jsxDEV("h3", {
2028
+ className: "text-base text-foreground",
2029
+ "data-testid": "gen-rows-title",
2030
+ children: t("Generate dummy rows")
2031
+ }, void 0, false), /* @__PURE__ */ jsxDEV("p", {
2032
+ className: "text-xs text-muted-foreground",
2033
+ "data-testid": "gen-rows-desc",
2034
+ children: t("Seed {table} with Faker-generated rows. Existing rows are not affected.", {
2035
+ table
2036
+ })
2037
+ }, void 0, false)]
2038
+ }, void 0, true), /* @__PURE__ */ jsxDEV("button", {
2039
+ className: "text-xs text-muted-foreground hover:text-foreground",
2040
+ "data-testid": "gen-rows-close",
2041
+ onClick: onClose,
2042
+ type: "button",
2043
+ children: t("Close")
2044
+ }, void 0, false)]
2045
+ }, void 0, true), /* @__PURE__ */ jsxDEV("div", {
2046
+ className: "flex items-center gap-2",
2047
+ children: [/* @__PURE__ */ jsxDEV("label", {
2048
+ className: "text-xs font-medium text-foreground",
2049
+ htmlFor: "gen-rows-count",
2050
+ children: t("Row count")
2051
+ }, void 0, false), /* @__PURE__ */ jsxDEV("input", {
2052
+ className: "w-20 rounded-md border border-border bg-background px-2 py-1 text-xs outline-none focus-visible:border-ring",
2053
+ "data-testid": "gen-rows-count",
2054
+ id: "gen-rows-count",
2055
+ max: MAX_GENERATE_ROWS,
2056
+ min: 1,
2057
+ onChange: onCountChange,
2058
+ type: "number",
2059
+ value: count
2060
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
2061
+ className: "text-xs text-muted-foreground",
2062
+ children: t("(max {max})", {
2063
+ max: MAX_GENERATE_ROWS.toString()
2064
+ })
2065
+ }, void 0, false)]
2066
+ }, void 0, true), editableColumns.length > 0 && /* @__PURE__ */ jsxDEV("div", {
2067
+ className: "flex flex-col gap-1",
2068
+ children: [/* @__PURE__ */ jsxDEV("p", {
2069
+ className: "font-mono text-[11px] tracking-wide uppercase text-muted-foreground",
2070
+ children: t("Columns to seed")
2071
+ }, void 0, false), /* @__PURE__ */ jsxDEV("ul", {
2072
+ className: "flex flex-col gap-0.5",
2073
+ "data-testid": "gen-rows-columns",
2074
+ children: editableColumns.map((column_0) => {
2075
+ const hasFk = column_0.ref !== void 0 && column_0.type === "id";
2076
+ const fkEmpty = hasFk && (fkPools[column_0.ref ?? ""] ?? []).length === 0;
2077
+ const fkBadgeClass = fkEmpty ? "rounded bg-destructive/10 px-1 text-destructive" : "rounded bg-muted px-1 text-muted-foreground";
2078
+ const fkBadgeTestId = fkEmpty ? `gen-rows-fk-empty-${column_0.name}` : `gen-rows-fk-ok-${column_0.name}`;
2079
+ const fkBadgeText = fkEmpty ? t("FK: no rows in {ref} — will skip", {
2080
+ ref: column_0.ref ?? ""
2081
+ }) : t("→ {ref}", {
2082
+ ref: column_0.ref ?? ""
2083
+ });
2084
+ return /* @__PURE__ */ jsxDEV("li", {
2085
+ className: "flex items-center gap-1.5 font-mono text-xs",
2086
+ children: [/* @__PURE__ */ jsxDEV("span", {
2087
+ className: "text-foreground",
2088
+ children: column_0.name
2089
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
2090
+ className: "text-muted-foreground",
2091
+ children: ["(", column_0.type, ")"]
2092
+ }, void 0, true), column_0.optional && /* @__PURE__ */ jsxDEV("span", {
2093
+ className: "rounded bg-muted px-1 font-mono text-[10px] tracking-wide uppercase",
2094
+ children: "optional"
2095
+ }, void 0, false), hasFk && /* @__PURE__ */ jsxDEV("span", {
2096
+ className: fkBadgeClass,
2097
+ "data-testid": fkBadgeTestId,
2098
+ children: fkBadgeText
2099
+ }, void 0, false)]
2100
+ }, column_0.name, true);
2101
+ })
2102
+ }, void 0, false)]
2103
+ }, void 0, true), error !== void 0 && /* @__PURE__ */ jsxDEV("p", {
2104
+ className: "text-xs text-destructive",
2105
+ "data-testid": "gen-rows-error",
2106
+ role: "alert",
2107
+ children: error
2108
+ }, void 0, false), inserted !== void 0 && error === void 0 && /* @__PURE__ */ jsxDEV("p", {
2109
+ className: "text-xs text-success",
2110
+ "data-testid": "gen-rows-success",
2111
+ children: t("Inserted {count} rows successfully.", {
2112
+ count: inserted.toString()
2113
+ })
2114
+ }, void 0, false), /* @__PURE__ */ jsxDEV("div", {
2115
+ className: "flex justify-end gap-2",
2116
+ children: [/* @__PURE__ */ jsxDEV("button", {
2117
+ className: BTN,
2118
+ "data-testid": "gen-rows-cancel",
2119
+ onClick: onClose,
2120
+ type: "button",
2121
+ children: t("Cancel")
2122
+ }, void 0, false), /* @__PURE__ */ jsxDEV("button", {
2123
+ className: BTN_DESTRUCTIVE,
2124
+ "data-testid": "gen-rows-generate",
2125
+ disabled: inserting,
2126
+ onClick: onGenerate,
2127
+ type: "button",
2128
+ children: inserting ? t("Inserting…") : t("Generate & insert")
2129
+ }, void 0, false)]
2130
+ }, void 0, true)]
2131
+ }, void 0, true);
2132
+ };
2133
+
2134
+ const toOrderBy = (sorting) => {
2135
+ const first = sorting[0];
2136
+ return first === void 0 ? void 0 : {
2137
+ column: first.id,
2138
+ direction: first.desc ? "desc" : "asc"
2139
+ };
2140
+ };
2141
+ const facetValueText = (value) => {
2142
+ if (value === null || value === void 0) {
2143
+ return "";
2144
+ }
2145
+ if (typeof value === "object") {
2146
+ return JSON.stringify(value);
2147
+ }
2148
+ return String(value);
2149
+ };
2150
+ const toEditableFilters = (clauses) => clauses.map((clause) => {
2151
+ return {
2152
+ column: clause.column,
2153
+ operator: clause.operator,
2154
+ value: clause.value === void 0 ? "" : facetValueText(clause.value)
2155
+ };
2156
+ });
2157
+ const fromOrderBy = (orderBy) => orderBy === void 0 ? [] : [{
2158
+ desc: orderBy.direction === "desc",
2159
+ id: orderBy.column
2160
+ }];
2161
+ const MAX_BULK_DELETE_BATCHES = 200;
2162
+ const PREVIEW_CANDIDATES = 20;
2163
+ const READ_TABLE_PAGE$1 = adminRef(ADMIN_FUNCTIONS.readTablePage);
2164
+ const FACET_COLUMN = adminRef(ADMIN_FUNCTIONS.facetColumn);
2165
+ const WRITE_ROW$1 = adminRef(ADMIN_FUNCTIONS.writeRow);
2166
+ const DELETE_ROWS = adminRef(ADMIN_FUNCTIONS.deleteRows);
2167
+ const CLEAR_TABLE = adminRef(ADMIN_FUNCTIONS.clearTable);
2168
+ const NO_ARGS = {};
2169
+ const META_COLUMNS = /* @__PURE__ */ new Set(["__doc__", "__id__", "_creationTime", "_id", "id"]);
2170
+ const rowDocument = (row) => {
2171
+ const raw = row["__doc__"];
2172
+ if (typeof raw === "string") {
2173
+ try {
2174
+ const parsed = JSON.parse(raw);
2175
+ if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
2176
+ return parsed;
2177
+ }
2178
+ } catch {
2179
+ }
2180
+ }
2181
+ const fields = {};
2182
+ for (const [key, value] of Object.entries(row)) {
2183
+ if (!META_COLUMNS.has(key)) {
2184
+ fields[key] = value;
2185
+ }
2186
+ }
2187
+ return fields;
2188
+ };
2189
+ const useDataBrowser = ({
2190
+ initialFilters,
2191
+ initialOrderBy,
2192
+ initialSearch,
2193
+ initialShardKey,
2194
+ onSelectTable,
2195
+ onViewChange,
2196
+ pageSize: initialPageSize,
2197
+ tableParam
2198
+ }) => {
2199
+ const client = useLunora();
2200
+ const [pageSize, setPageSize] = useState(initialPageSize);
2201
+ const [shardKey, setShardKey] = useState(initialShardKey ?? "");
2202
+ const hydrationRef = useRef({
2203
+ filters: initialFilters,
2204
+ orderBy: initialOrderBy,
2205
+ search: initialSearch,
2206
+ table: tableParam
2207
+ });
2208
+ const [selectedTable, setSelectedTable] = useState(null);
2209
+ const [offset, setOffset] = useState(0);
2210
+ const [viewMode, setViewMode] = useState("table");
2211
+ const [sorting, setSorting] = useState(() => fromOrderBy(initialOrderBy));
2212
+ const [filter, setFilter] = useState(initialSearch ?? "");
2213
+ const search = useDebounced(filter.trim(), 300);
2214
+ const debouncedShard = useDebounced(shardKey.trim(), 400);
2215
+ const [filters, setFilters] = useState(() => toEditableFilters(initialFilters ?? []));
2216
+ const filtersRef = useRef(filters);
2217
+ filtersRef.current = filters;
2218
+ const {
2219
+ clearFacets,
2220
+ facets,
2221
+ refetchFacets,
2222
+ toggleFacet: toggleFacetColumn
2223
+ } = useFacets();
2224
+ const [editing, setEditing] = useState(null);
2225
+ const [writeError, setWriteError] = useState(null);
2226
+ const stagedEdits = useStagedEdits();
2227
+ const [editingCell, setEditingCell] = useState(null);
2228
+ const [committing, setCommitting] = useState(false);
2229
+ const tablesQuery = useAdminQuery(ADMIN_FUNCTIONS.listTables, NO_ARGS, {
2230
+ live: true,
2231
+ shardKey: debouncedShard
2232
+ });
2233
+ const tables = tablesQuery.data ?? null;
2234
+ const tablesError = tablesQuery.error;
2235
+ const pageArgs = useMemo(() => {
2236
+ return {
2237
+ filters: toFilterClauses(filters),
2238
+ limit: pageSize,
2239
+ offset,
2240
+ orderBy: toOrderBy(sorting),
2241
+ search,
2242
+ table: selectedTable ?? ""
2243
+ };
2244
+ }, [filters, pageSize, offset, sorting, search, selectedTable]);
2245
+ const pageQuery = useAdminQuery(ADMIN_FUNCTIONS.readTablePage, pageArgs, {
2246
+ enabled: selectedTable !== null,
2247
+ keepPreviousData: false,
2248
+ live: true,
2249
+ shardKey: debouncedShard
2250
+ });
2251
+ const page = pageQuery.data ?? null;
2252
+ const pageError = pageQuery.error;
2253
+ const {
2254
+ liveError
2255
+ } = pageQuery;
2256
+ useEffect(() => {
2257
+ if (tablesQuery.data !== void 0) {
2258
+ recordShard(debouncedShard);
2259
+ }
2260
+ }, [tablesQuery.data, debouncedShard]);
2261
+ const appliedTableRef = useRef(null);
2262
+ const selectTable = useCallback((table) => {
2263
+ const hydration = hydrationRef.current?.table === void 0 || hydrationRef.current.table === table ? hydrationRef.current : null;
2264
+ hydrationRef.current = null;
2265
+ const nextSorting = fromOrderBy(hydration?.orderBy);
2266
+ const nextFilters = toEditableFilters(hydration?.filters ?? []);
2267
+ const nextSearch = hydration?.search ?? "";
2268
+ setSorting(nextSorting);
2269
+ setFilter(nextSearch);
2270
+ setFilters(nextFilters);
2271
+ filtersRef.current = nextFilters;
2272
+ clearFacets();
2273
+ stagedEdits.clear();
2274
+ setEditingCell(null);
2275
+ setOffset(0);
2276
+ setSelectedTable(table);
2277
+ appliedTableRef.current = table;
2278
+ onSelectTable?.(table);
2279
+ }, [clearFacets, onSelectTable, stagedEdits]);
2280
+ const navigateToRef = (targetTable, id) => {
2281
+ setSorting([]);
2282
+ setFilters([]);
2283
+ filtersRef.current = [];
2284
+ clearFacets();
2285
+ setOffset(0);
2286
+ setSelectedTable(targetTable);
2287
+ appliedTableRef.current = targetTable;
2288
+ setFilter(id);
2289
+ onSelectTable?.(targetTable);
2290
+ };
2291
+ const previewRef = async (targetTable_0, id_0) => {
2292
+ try {
2293
+ const result = await client.query(READ_TABLE_PAGE$1, {
2294
+ filters: [],
2295
+ limit: PREVIEW_CANDIDATES,
2296
+ offset: 0,
2297
+ search: id_0,
2298
+ table: targetTable_0
2299
+ }, callOptions(debouncedShard));
2300
+ return result.rows.find((row) => rowId(row) === id_0) ?? null;
2301
+ } catch {
2302
+ return null;
2303
+ }
2304
+ };
2305
+ const facetFetcher = useCallback((shard, table_0, activeFilters, searchQuery) => (column) => client.query(FACET_COLUMN, {
2306
+ column,
2307
+ filters: toFilterClauses(activeFilters),
2308
+ search: searchQuery,
2309
+ table: table_0
2310
+ }, callOptions(shard)), [client]);
2311
+ const toggleFacet = (column_0) => {
2312
+ toggleFacetColumn(column_0, selectedTable === null ? null : facetFetcher(debouncedShard, selectedTable, filtersRef.current, search));
2313
+ };
2314
+ const facetFilter = (column_1, value) => {
2315
+ const text = facetValueText(value);
2316
+ setFilters((current) => [...current.filter((clause) => clause.column !== column_1), {
2317
+ column: column_1,
2318
+ operator: "eq",
2319
+ value: text
2320
+ }]);
2321
+ setOffset(0);
2322
+ };
2323
+ useEffect(() => {
2324
+ if (selectedTable === null) {
2325
+ return;
2326
+ }
2327
+ refetchFacets(facetFetcher(debouncedShard, selectedTable, filters, search));
2328
+ }, [debouncedShard, selectedTable, filters, search, facetFetcher, refetchFacets]);
2329
+ useEffect(() => {
2330
+ if (selectedTable === null || onViewChange === void 0) {
2331
+ return;
2332
+ }
2333
+ onViewChange({
2334
+ filters: toFilterClauses(filters),
2335
+ orderBy: toOrderBy(sorting),
2336
+ search,
2337
+ shard: debouncedShard
2338
+ });
2339
+ }, [selectedTable, filters, sorting, search, debouncedShard, onViewChange]);
2340
+ useEffect(() => {
2341
+ if (tableParam === void 0 || tableParam === "" || tableParam === appliedTableRef.current) {
2342
+ return;
2343
+ }
2344
+ appliedTableRef.current = tableParam;
2345
+ const target = tableParam;
2346
+ queueMicrotask(() => {
2347
+ selectTable(target);
2348
+ });
2349
+ }, [tableParam, selectTable]);
2350
+ const goToPage = (nextOffset) => {
2351
+ if (selectedTable === null) {
2352
+ return;
2353
+ }
2354
+ setOffset(Math.max(0, nextOffset));
2355
+ };
2356
+ const editableColumn = (column_2) => !META_COLUMNS.has(column_2);
2357
+ const startCellEdit = (targetRow, column_3) => {
2358
+ setEditingCell({
2359
+ column: column_3,
2360
+ rowId: targetRow
2361
+ });
2362
+ };
2363
+ const cancelCellEdit = () => {
2364
+ setEditingCell(null);
2365
+ };
2366
+ const commitStaged = async () => {
2367
+ if (selectedTable === null) {
2368
+ return;
2369
+ }
2370
+ setWriteError(null);
2371
+ setCommitting(true);
2372
+ try {
2373
+ for (const [id_1, columns] of Object.entries(stagedEdits.staged)) {
2374
+ await client.query(WRITE_ROW$1, {
2375
+ doc: columns,
2376
+ id: id_1,
2377
+ op: "patch",
2378
+ table: selectedTable
2379
+ }, callOptions(debouncedShard));
2380
+ }
2381
+ stagedEdits.clear();
2382
+ setEditingCell(null);
2383
+ pageQuery.refetch();
2384
+ } catch (error) {
2385
+ setWriteError(error.message);
2386
+ } finally {
2387
+ setCommitting(false);
2388
+ }
2389
+ };
2390
+ const discardStaged = () => {
2391
+ stagedEdits.clear();
2392
+ setEditingCell(null);
2393
+ };
2394
+ const stagedChanges = useMemo(() => {
2395
+ const rowsById = /* @__PURE__ */ new Map();
2396
+ for (const row_0 of page?.rows ?? []) {
2397
+ const id_2 = rowId(row_0);
2398
+ if (id_2 !== null) {
2399
+ rowsById.set(id_2, row_0);
2400
+ }
2401
+ }
2402
+ const changes = [];
2403
+ for (const [id_3, columns_0] of Object.entries(stagedEdits.staged)) {
2404
+ for (const [column_4, newValue] of Object.entries(columns_0)) {
2405
+ changes.push({
2406
+ column: column_4,
2407
+ newValue,
2408
+ oldValue: rowsById.get(id_3)?.[column_4],
2409
+ rowId: id_3
2410
+ });
2411
+ }
2412
+ }
2413
+ return changes;
2414
+ }, [page, stagedEdits.staged]);
2415
+ const writeRow = async (op, id_4, documentText) => {
2416
+ if (selectedTable === null) {
2417
+ return;
2418
+ }
2419
+ setWriteError(null);
2420
+ let parsedDocument;
2421
+ if (op !== "delete") {
2422
+ try {
2423
+ parsedDocument = documentText === void 0 || documentText.trim() === "" ? {} : JSON.parse(documentText);
2424
+ } catch (error_0) {
2425
+ setWriteError(`Invalid JSON: ${error_0.message}`);
2426
+ return;
2427
+ }
2428
+ }
2429
+ try {
2430
+ await client.query(WRITE_ROW$1, {
2431
+ doc: parsedDocument,
2432
+ id: id_4 ?? void 0,
2433
+ op,
2434
+ table: selectedTable
2435
+ }, callOptions(debouncedShard));
2436
+ setEditing(null);
2437
+ pageQuery.refetch();
2438
+ } catch (error_1) {
2439
+ setWriteError(error_1.message);
2440
+ }
2441
+ };
2442
+ const drainBulk = async (ref, args) => {
2443
+ if (selectedTable === null) {
2444
+ return;
2445
+ }
2446
+ setWriteError(null);
2447
+ try {
2448
+ for (let batch = 0; batch < MAX_BULK_DELETE_BATCHES; batch += 1) {
2449
+ const result_0 = await client.query(ref, args, callOptions(debouncedShard));
2450
+ if (!result_0.hasMore) {
2451
+ break;
2452
+ }
2453
+ }
2454
+ setOffset(0);
2455
+ pageQuery.refetch();
2456
+ } catch (error_2) {
2457
+ setWriteError(error_2.message);
2458
+ }
2459
+ };
2460
+ const changeSorting = (updater) => {
2461
+ setSorting(updater);
2462
+ setOffset(0);
2463
+ };
2464
+ const table_1 = useDataBrowserTable(page, sorting, changeSorting);
2465
+ const currentView = {
2466
+ filters: toFilterClauses(filters),
2467
+ orderBy: toOrderBy(sorting),
2468
+ search,
2469
+ shard: shardKey,
2470
+ table: selectedTable ?? void 0
2471
+ };
2472
+ const total = page?.total ?? 0;
2473
+ const hasPrevious = offset > 0;
2474
+ const hasNext = page !== null && offset + page.rows.length < total;
2475
+ const rangeStart = page === null || page.rows.length === 0 ? 0 : offset + 1;
2476
+ const rangeEnd = page === null ? 0 : offset + page.rows.length;
2477
+ const loadTables = () => {
2478
+ tablesQuery.refetch();
2479
+ };
2480
+ const showTable = () => {
2481
+ setViewMode("table");
2482
+ };
2483
+ const showJson = () => {
2484
+ setViewMode("json");
2485
+ };
2486
+ const bulkDelete = () => {
2487
+ fireAndForget(drainBulk(DELETE_ROWS, {
2488
+ filters: toFilterClauses(filtersRef.current),
2489
+ search,
2490
+ table: selectedTable
2491
+ }));
2492
+ };
2493
+ const emptyTable = () => {
2494
+ fireAndForget(drainBulk(CLEAR_TABLE, {
2495
+ table: selectedTable
2496
+ }));
2497
+ };
2498
+ const onFilterChange = (event) => {
2499
+ setFilter(event.target.value);
2500
+ setOffset(0);
2501
+ };
2502
+ const changeFilters = (next) => {
2503
+ setFilters(next);
2504
+ setOffset(0);
2505
+ };
2506
+ const addRow = () => {
2507
+ setWriteError(null);
2508
+ const seed = {};
2509
+ for (const column_5 of page?.columns ?? []) {
2510
+ if (!META_COLUMNS.has(column_5)) {
2511
+ seed[column_5] = "";
2512
+ }
2513
+ }
2514
+ setEditing({
2515
+ docText: JSON.stringify(seed, null, 2),
2516
+ id: ""
2517
+ });
2518
+ };
2519
+ const setEditorDocumentText = (text_0) => {
2520
+ setEditing((current_0) => current_0 === null ? current_0 : {
2521
+ docText: text_0,
2522
+ id: current_0.id
2523
+ });
2524
+ };
2525
+ const saveEdit = () => {
2526
+ if (editing === null) {
2527
+ return;
2528
+ }
2529
+ fireAndForget(writeRow(editing.id === "" ? "insert" : "patch", editing.id === "" ? null : editing.id, editing.docText));
2530
+ };
2531
+ const cancelEdit = () => {
2532
+ setEditing(null);
2533
+ setWriteError(null);
2534
+ };
2535
+ const goPrevious = () => {
2536
+ goToPage(offset - pageSize);
2537
+ };
2538
+ const goNext = () => {
2539
+ goToPage(offset + pageSize);
2540
+ };
2541
+ const jumpToPage = (targetPage) => {
2542
+ goToPage(Math.max(0, (targetPage - 1) * pageSize));
2543
+ };
2544
+ const changePageSize = (size) => {
2545
+ setPageSize(size);
2546
+ setOffset(0);
2547
+ };
2548
+ const onRowEdit = (id_5, original) => {
2549
+ setWriteError(null);
2550
+ setEditing({
2551
+ docText: JSON.stringify(rowDocument(original), null, 2),
2552
+ id: id_5
2553
+ });
2554
+ };
2555
+ const onRowDelete = (id_6) => {
2556
+ fireAndForget(writeRow("delete", id_6));
2557
+ };
2558
+ const deleteSelected = async (ids) => {
2559
+ if (selectedTable === null || ids.length === 0) {
2560
+ return;
2561
+ }
2562
+ setWriteError(null);
2563
+ try {
2564
+ for (const id_7 of ids) {
2565
+ await client.query(WRITE_ROW$1, {
2566
+ id: id_7,
2567
+ op: "delete",
2568
+ table: selectedTable
2569
+ }, callOptions(debouncedShard));
2570
+ }
2571
+ pageQuery.refetch();
2572
+ } catch (error_3) {
2573
+ setWriteError(error_3.message);
2574
+ }
2575
+ };
2576
+ const onBulkDeleteSelected = (ids_0) => {
2577
+ fireAndForget(deleteSelected(ids_0));
2578
+ };
2579
+ const onCommitStaged = () => {
2580
+ fireAndForget(commitStaged());
2581
+ };
2582
+ return {
2583
+ addRow,
2584
+ bulkDelete,
2585
+ cancelCellEdit,
2586
+ cancelEdit,
2587
+ changePageSize,
2588
+ clearTable: emptyTable,
2589
+ columns: page?.columns ?? [],
2590
+ committing,
2591
+ currentView,
2592
+ discardStaged,
2593
+ editableColumn,
2594
+ editing,
2595
+ editingCell,
2596
+ facetFilter,
2597
+ facets,
2598
+ filter,
2599
+ filters,
2600
+ goNext,
2601
+ goPrevious,
2602
+ hasNext,
2603
+ hasPrevious,
2604
+ jumpToPage,
2605
+ liveError,
2606
+ loadTables,
2607
+ navigateToRef,
2608
+ onBulkDeleteSelected,
2609
+ onCommitStaged,
2610
+ onFilterChange,
2611
+ onFiltersChange: changeFilters,
2612
+ onRowDelete,
2613
+ onRowEdit,
2614
+ page,
2615
+ previewRef,
2616
+ pageError,
2617
+ pageSize,
2618
+ rangeEnd,
2619
+ rangeStart,
2620
+ saveEdit,
2621
+ selectedTable,
2622
+ selectTable,
2623
+ setEditorDocumentText,
2624
+ setShardKey,
2625
+ shardKey,
2626
+ showJson,
2627
+ showTable,
2628
+ stage: stagedEdits.stage,
2629
+ stagedChanges,
2630
+ stagedValue: stagedEdits.stagedValue,
2631
+ startCellEdit,
2632
+ table: table_1,
2633
+ tables,
2634
+ tablesError,
2635
+ toggleFacet,
2636
+ total,
2637
+ viewMode,
2638
+ writeError
2639
+ };
2640
+ };
2641
+
2642
+ const DESCRIBE_TABLE = adminRef(ADMIN_FUNCTIONS.describeTable);
2643
+ const READ_TABLE_PAGE = adminRef(ADMIN_FUNCTIONS.readTablePage);
2644
+ const WRITE_ROW = adminRef(ADMIN_FUNCTIONS.writeRow);
2645
+ const extractId = (row) => {
2646
+ const raw = row["_id"] ?? row["id"] ?? row["__id__"] ?? "";
2647
+ if (typeof raw === "string") {
2648
+ return raw;
2649
+ }
2650
+ if (typeof raw === "number") {
2651
+ return String(raw);
2652
+ }
2653
+ return "";
2654
+ };
2655
+ const useGenerateRows = (onRefresh) => {
2656
+ const client = useLunora();
2657
+ const [open, setOpen] = useState(false);
2658
+ const [table, setTable] = useState(void 0);
2659
+ const [shardKey, setShardKey] = useState(void 0);
2660
+ const [columnMeta, setColumnMeta] = useState(void 0);
2661
+ const [fkPools, setFkPools] = useState({});
2662
+ const [loading, setLoading] = useState(false);
2663
+ const [error, setError] = useState(void 0);
2664
+ const openDialogAsync = async (targetTable, targetShard) => {
2665
+ setOpen(true);
2666
+ setTable(targetTable);
2667
+ setShardKey(targetShard);
2668
+ setColumnMeta(void 0);
2669
+ setFkPools({});
2670
+ setError(void 0);
2671
+ setLoading(true);
2672
+ try {
2673
+ const result = await client.query(DESCRIBE_TABLE, {
2674
+ table: targetTable
2675
+ }, callOptions(targetShard));
2676
+ const {
2677
+ columns
2678
+ } = result;
2679
+ setColumnMeta(columns);
2680
+ const pools = {};
2681
+ const fkColumns = columns.filter((column) => column.ref !== void 0 && column.type === "id" && column.pk !== true);
2682
+ for (const fkColumn of fkColumns) {
2683
+ if (fkColumn.ref === void 0) {
2684
+ continue;
2685
+ }
2686
+ const {
2687
+ ref
2688
+ } = fkColumn;
2689
+ if (pools[ref] !== void 0) {
2690
+ continue;
2691
+ }
2692
+ try {
2693
+ const page = await client.query(READ_TABLE_PAGE, {
2694
+ filters: [],
2695
+ limit: MAX_FK_SAMPLE,
2696
+ offset: 0,
2697
+ search: "",
2698
+ table: ref
2699
+ }, callOptions(targetShard));
2700
+ pools[ref] = page.rows.map((row) => extractId(row)).filter(Boolean);
2701
+ } catch {
2702
+ pools[ref] = [];
2703
+ }
2704
+ }
2705
+ setFkPools(pools);
2706
+ } catch (error_) {
2707
+ setError(error_.message);
2708
+ } finally {
2709
+ setLoading(false);
2710
+ }
2711
+ };
2712
+ const openDialog = (targetTable_0, targetShard_0) => {
2713
+ fireAndForget(openDialogAsync(targetTable_0, targetShard_0));
2714
+ };
2715
+ const closeDialog = () => {
2716
+ setOpen(false);
2717
+ setTable(void 0);
2718
+ setShardKey(void 0);
2719
+ setColumnMeta(void 0);
2720
+ setFkPools({});
2721
+ setError(void 0);
2722
+ };
2723
+ const insertBatch = async (rows, onDone) => {
2724
+ if (table === void 0 || shardKey === void 0) {
2725
+ return "No table selected.";
2726
+ }
2727
+ try {
2728
+ for (const rowDocument of rows) {
2729
+ await client.query(WRITE_ROW, {
2730
+ doc: rowDocument,
2731
+ op: "insert",
2732
+ table
2733
+ }, callOptions(shardKey));
2734
+ }
2735
+ onDone();
2736
+ onRefresh();
2737
+ return void 0;
2738
+ } catch (error__0) {
2739
+ return error__0.message;
2740
+ }
2741
+ };
2742
+ return {
2743
+ closeDialog,
2744
+ columnMeta,
2745
+ error,
2746
+ fkPools,
2747
+ insertBatch,
2748
+ loading,
2749
+ open,
2750
+ openDialog,
2751
+ shardKey,
2752
+ table
2753
+ };
2754
+ };
2755
+
2756
+ const NO_COLUMNS = [];
2757
+ const useMaskPolicies = () => {
2758
+ const $ = c(1);
2759
+ let t0;
2760
+ if ($[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
2761
+ t0 = {};
2762
+ $[0] = t0;
2763
+ } else {
2764
+ t0 = $[0];
2765
+ }
2766
+ const {
2767
+ data
2768
+ } = useAdminQuery(ADMIN_FUNCTIONS.maskPolicies, t0);
2769
+ return Array.isArray(data?.columns) ? data.columns : NO_COLUMNS;
2770
+ };
2771
+
2772
+ const TIMESTAMP_RE$1 = /(?:_creationtime|(?:^|[a-z])(?:time|at))$/iu;
2773
+ const looksLikeTimestamp = (column, value) => typeof value === "number" && TIMESTAMP_RE$1.test(column);
2774
+ const FieldValue = (t0) => {
2775
+ const $ = c(26);
2776
+ const {
2777
+ column,
2778
+ onNavigate,
2779
+ target,
2780
+ value
2781
+ } = t0;
2782
+ let t1;
2783
+ if ($[0] !== onNavigate || $[1] !== target || $[2] !== value) {
2784
+ t1 = () => {
2785
+ if (target !== void 0) {
2786
+ onNavigate(target, String(value));
2787
+ }
2788
+ };
2789
+ $[0] = onNavigate;
2790
+ $[1] = target;
2791
+ $[2] = value;
2792
+ $[3] = t1;
2793
+ } else {
2794
+ t1 = $[3];
2795
+ }
2796
+ const onClick = t1;
2797
+ if (value === null || value === void 0) {
2798
+ let t22;
2799
+ if ($[4] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
2800
+ t22 = /* @__PURE__ */ jsxDEV("span", {
2801
+ className: "italic text-muted-foreground",
2802
+ children: "null"
2803
+ }, void 0, false);
2804
+ $[4] = t22;
2805
+ } else {
2806
+ t22 = $[4];
2807
+ }
2808
+ return t22;
2809
+ }
2810
+ if (target !== void 0 && (typeof value === "string" || typeof value === "number") && String(value) !== "") {
2811
+ const t22 = `rd-ref-${column}`;
2812
+ const t32 = `Open ${target} ${String(value)}`;
2813
+ const t4 = String(value);
2814
+ let t5;
2815
+ if ($[5] !== onClick || $[6] !== t22 || $[7] !== t32 || $[8] !== t4) {
2816
+ t5 = /* @__PURE__ */ jsxDEV("button", {
2817
+ "data-testid": t22,
2818
+ onClick,
2819
+ title: t32,
2820
+ type: "button",
2821
+ children: [t4, " ↗"]
2822
+ }, void 0, true);
2823
+ $[5] = onClick;
2824
+ $[6] = t22;
2825
+ $[7] = t32;
2826
+ $[8] = t4;
2827
+ $[9] = t5;
2828
+ } else {
2829
+ t5 = $[9];
2830
+ }
2831
+ return t5;
2832
+ }
2833
+ if (looksLikeTimestamp(column, value)) {
2834
+ const t22 = `rd-ts-${column}`;
2835
+ let t32;
2836
+ if ($[10] !== value) {
2837
+ t32 = value.toString();
2838
+ $[10] = value;
2839
+ $[11] = t32;
2840
+ } else {
2841
+ t32 = $[11];
2842
+ }
2843
+ let t4;
2844
+ if ($[12] !== value) {
2845
+ t4 = formatTimestamp(value);
2846
+ $[12] = value;
2847
+ $[13] = t4;
2848
+ } else {
2849
+ t4 = $[13];
2850
+ }
2851
+ let t5;
2852
+ if ($[14] !== t22 || $[15] !== t32 || $[16] !== t4) {
2853
+ t5 = /* @__PURE__ */ jsxDEV("span", {
2854
+ "data-testid": t22,
2855
+ title: t32,
2856
+ children: t4
2857
+ }, void 0, false);
2858
+ $[14] = t22;
2859
+ $[15] = t32;
2860
+ $[16] = t4;
2861
+ $[17] = t5;
2862
+ } else {
2863
+ t5 = $[17];
2864
+ }
2865
+ return t5;
2866
+ }
2867
+ if (typeof value === "object") {
2868
+ let t22;
2869
+ if ($[18] !== value) {
2870
+ t22 = JSON.stringify(value, null, 2);
2871
+ $[18] = value;
2872
+ $[19] = t22;
2873
+ } else {
2874
+ t22 = $[19];
2875
+ }
2876
+ let t32;
2877
+ if ($[20] !== t22) {
2878
+ t32 = /* @__PURE__ */ jsxDEV("pre", {
2879
+ className: "m-0 overflow-auto rounded-md bg-muted/50 p-2 text-xs",
2880
+ children: t22
2881
+ }, void 0, false);
2882
+ $[20] = t22;
2883
+ $[21] = t32;
2884
+ } else {
2885
+ t32 = $[21];
2886
+ }
2887
+ return t32;
2888
+ }
2889
+ let t2;
2890
+ if ($[22] !== value) {
2891
+ t2 = formatCell(value);
2892
+ $[22] = value;
2893
+ $[23] = t2;
2894
+ } else {
2895
+ t2 = $[23];
2896
+ }
2897
+ let t3;
2898
+ if ($[24] !== t2) {
2899
+ t3 = /* @__PURE__ */ jsxDEV("span", {
2900
+ children: t2
2901
+ }, void 0, false);
2902
+ $[24] = t2;
2903
+ $[25] = t3;
2904
+ } else {
2905
+ t3 = $[25];
2906
+ }
2907
+ return t3;
2908
+ };
2909
+ const RowDetailDrawer = (t0) => {
2910
+ const $ = c(21);
2911
+ const {
2912
+ columns,
2913
+ onClose,
2914
+ onNavigate,
2915
+ refs,
2916
+ row
2917
+ } = t0;
2918
+ let t1;
2919
+ if ($[0] !== onClose || $[1] !== onNavigate) {
2920
+ t1 = (target, id) => {
2921
+ onNavigate(target, id);
2922
+ onClose();
2923
+ };
2924
+ $[0] = onClose;
2925
+ $[1] = onNavigate;
2926
+ $[2] = t1;
2927
+ } else {
2928
+ t1 = $[2];
2929
+ }
2930
+ const navigateAndClose = t1;
2931
+ let t2;
2932
+ if ($[3] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
2933
+ t2 = /* @__PURE__ */ jsxDEV("h3", {
2934
+ className: "m-0 text-base text-foreground",
2935
+ children: "Row detail"
2936
+ }, void 0, false);
2937
+ $[3] = t2;
2938
+ } else {
2939
+ t2 = $[3];
2940
+ }
2941
+ let t3;
2942
+ if ($[4] !== onClose) {
2943
+ t3 = /* @__PURE__ */ jsxDEV("div", {
2944
+ className: "mb-3 flex items-center justify-between",
2945
+ children: [t2, /* @__PURE__ */ jsxDEV("button", {
2946
+ "data-testid": "rd-close",
2947
+ onClick: onClose,
2948
+ type: "button",
2949
+ children: "Close"
2950
+ }, void 0, false)]
2951
+ }, void 0, true);
2952
+ $[4] = onClose;
2953
+ $[5] = t3;
2954
+ } else {
2955
+ t3 = $[5];
2956
+ }
2957
+ let t4;
2958
+ if ($[6] !== columns || $[7] !== navigateAndClose || $[8] !== refs || $[9] !== row) {
2959
+ let t52;
2960
+ if ($[11] !== navigateAndClose || $[12] !== refs || $[13] !== row) {
2961
+ t52 = (column) => /* @__PURE__ */ jsxDEV("div", {
2962
+ className: "border-t border-border py-2 first:border-t-0",
2963
+ "data-testid": `rd-field-${column}`,
2964
+ children: [/* @__PURE__ */ jsxDEV("dt", {
2965
+ className: "mb-0.5 text-xs font-semibold text-muted-foreground",
2966
+ children: column
2967
+ }, void 0, false), /* @__PURE__ */ jsxDEV("dd", {
2968
+ className: "m-0",
2969
+ children: /* @__PURE__ */ jsxDEV(FieldValue, {
2970
+ column,
2971
+ onNavigate: navigateAndClose,
2972
+ target: refs?.[column],
2973
+ value: row[column]
2974
+ }, void 0, false)
2975
+ }, void 0, false)]
2976
+ }, column, true);
2977
+ $[11] = navigateAndClose;
2978
+ $[12] = refs;
2979
+ $[13] = row;
2980
+ $[14] = t52;
2981
+ } else {
2982
+ t52 = $[14];
2983
+ }
2984
+ t4 = columns.map(t52);
2985
+ $[6] = columns;
2986
+ $[7] = navigateAndClose;
2987
+ $[8] = refs;
2988
+ $[9] = row;
2989
+ $[10] = t4;
2990
+ } else {
2991
+ t4 = $[10];
2992
+ }
2993
+ let t5;
2994
+ if ($[15] !== t4) {
2995
+ t5 = /* @__PURE__ */ jsxDEV("dl", {
2996
+ "data-testid": "rd-fields",
2997
+ children: t4
2998
+ }, void 0, false);
2999
+ $[15] = t4;
3000
+ $[16] = t5;
3001
+ } else {
3002
+ t5 = $[16];
3003
+ }
3004
+ let t6;
3005
+ if ($[17] !== onClose || $[18] !== t3 || $[19] !== t5) {
3006
+ t6 = /* @__PURE__ */ jsxDEV(ModalShell, {
3007
+ label: "Row detail",
3008
+ onClose,
3009
+ panelTestId: "rd-panel",
3010
+ testId: "rd-overlay",
3011
+ variant: "drawer",
3012
+ children: [t3, t5]
3013
+ }, void 0, true);
3014
+ $[17] = onClose;
3015
+ $[18] = t3;
3016
+ $[19] = t5;
3017
+ $[20] = t6;
3018
+ } else {
3019
+ t6 = $[20];
3020
+ }
3021
+ return t6;
3022
+ };
3023
+
3024
+ const CONTROL_BTN$1 = "inline-flex items-center gap-1 rounded-md border border-border px-2.5 py-1 text-xs font-medium text-foreground outline-none transition-colors hover:bg-accent focus-visible:bg-accent aria-pressed:bg-accent aria-pressed:text-accent-foreground disabled:pointer-events-none disabled:opacity-50";
3025
+ const FIELD_INPUT = "w-full rounded-md border border-border bg-background px-2 py-1 font-mono text-xs outline-none focus-visible:border-ring";
3026
+ const TIMESTAMP_RE = /(?:_creationtime|(?:^|[a-z])(?:time|at))$/iu;
3027
+ const inferKind = (column, value) => {
3028
+ if (typeof value === "boolean") {
3029
+ return "boolean";
3030
+ }
3031
+ if (typeof value === "number") {
3032
+ return TIMESTAMP_RE.test(column) ? "date" : "number";
3033
+ }
3034
+ if (value !== null && typeof value === "object") {
3035
+ return "json";
3036
+ }
3037
+ return "text";
3038
+ };
3039
+ const parseDocument = (documentText) => {
3040
+ try {
3041
+ const value = JSON.parse(documentText);
3042
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
3043
+ } catch {
3044
+ return null;
3045
+ }
3046
+ };
3047
+ const toLocalDateTime = (ms) => {
3048
+ const date = new Date(ms);
3049
+ const pad = (n) => String(n).padStart(2, "0");
3050
+ return `${date.getFullYear().toString()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`;
3051
+ };
3052
+ const BooleanField = (t0) => {
3053
+ const $ = c(8);
3054
+ const {
3055
+ column,
3056
+ onChange,
3057
+ value
3058
+ } = t0;
3059
+ let t1;
3060
+ if ($[0] !== column || $[1] !== onChange) {
3061
+ t1 = (checked) => {
3062
+ onChange(column, checked);
3063
+ };
3064
+ $[0] = column;
3065
+ $[1] = onChange;
3066
+ $[2] = t1;
3067
+ } else {
3068
+ t1 = $[2];
3069
+ }
3070
+ const onCheckedChange = t1;
3071
+ const t2 = value === true;
3072
+ const t3 = `db-field-${column}`;
3073
+ let t4;
3074
+ if ($[3] !== column || $[4] !== onCheckedChange || $[5] !== t2 || $[6] !== t3) {
3075
+ t4 = /* @__PURE__ */ jsxDEV(Checkbox, {
3076
+ "aria-label": column,
3077
+ checked: t2,
3078
+ "data-testid": t3,
3079
+ onCheckedChange
3080
+ }, void 0, false);
3081
+ $[3] = column;
3082
+ $[4] = onCheckedChange;
3083
+ $[5] = t2;
3084
+ $[6] = t3;
3085
+ $[7] = t4;
3086
+ } else {
3087
+ t4 = $[7];
3088
+ }
3089
+ return t4;
3090
+ };
3091
+ const NumberField = (t0) => {
3092
+ const $ = c(7);
3093
+ const {
3094
+ column,
3095
+ onChange,
3096
+ value
3097
+ } = t0;
3098
+ let t1;
3099
+ if ($[0] !== column || $[1] !== onChange) {
3100
+ t1 = (event) => {
3101
+ const next = Number(event.target.value);
3102
+ if (event.target.value !== "" && !Number.isNaN(next)) {
3103
+ onChange(column, next);
3104
+ }
3105
+ };
3106
+ $[0] = column;
3107
+ $[1] = onChange;
3108
+ $[2] = t1;
3109
+ } else {
3110
+ t1 = $[2];
3111
+ }
3112
+ const onInput = t1;
3113
+ const t2 = `db-field-${column}`;
3114
+ const t3 = typeof value === "number" ? value : "";
3115
+ let t4;
3116
+ if ($[3] !== onInput || $[4] !== t2 || $[5] !== t3) {
3117
+ t4 = /* @__PURE__ */ jsxDEV("input", {
3118
+ className: FIELD_INPUT,
3119
+ "data-testid": t2,
3120
+ onChange: onInput,
3121
+ type: "number",
3122
+ value: t3
3123
+ }, void 0, false);
3124
+ $[3] = onInput;
3125
+ $[4] = t2;
3126
+ $[5] = t3;
3127
+ $[6] = t4;
3128
+ } else {
3129
+ t4 = $[6];
3130
+ }
3131
+ return t4;
3132
+ };
3133
+ const DateField = (t0) => {
3134
+ const $ = c(9);
3135
+ const {
3136
+ column,
3137
+ onChange,
3138
+ value
3139
+ } = t0;
3140
+ let t1;
3141
+ if ($[0] !== column || $[1] !== onChange) {
3142
+ t1 = (event) => {
3143
+ const ms = new Date(event.target.value).getTime();
3144
+ if (!Number.isNaN(ms)) {
3145
+ onChange(column, ms);
3146
+ }
3147
+ };
3148
+ $[0] = column;
3149
+ $[1] = onChange;
3150
+ $[2] = t1;
3151
+ } else {
3152
+ t1 = $[2];
3153
+ }
3154
+ const onInput = t1;
3155
+ const t2 = `db-field-${column}`;
3156
+ let t3;
3157
+ if ($[3] !== value) {
3158
+ t3 = typeof value === "number" ? toLocalDateTime(value) : "";
3159
+ $[3] = value;
3160
+ $[4] = t3;
3161
+ } else {
3162
+ t3 = $[4];
3163
+ }
3164
+ let t4;
3165
+ if ($[5] !== onInput || $[6] !== t2 || $[7] !== t3) {
3166
+ t4 = /* @__PURE__ */ jsxDEV("input", {
3167
+ className: FIELD_INPUT,
3168
+ "data-testid": t2,
3169
+ onChange: onInput,
3170
+ type: "datetime-local",
3171
+ value: t3
3172
+ }, void 0, false);
3173
+ $[5] = onInput;
3174
+ $[6] = t2;
3175
+ $[7] = t3;
3176
+ $[8] = t4;
3177
+ } else {
3178
+ t4 = $[8];
3179
+ }
3180
+ return t4;
3181
+ };
3182
+ const TextField = (t0) => {
3183
+ const $ = c(7);
3184
+ const {
3185
+ column,
3186
+ onChange,
3187
+ value
3188
+ } = t0;
3189
+ let t1;
3190
+ if ($[0] !== column || $[1] !== onChange) {
3191
+ t1 = (event) => {
3192
+ onChange(column, event.target.value);
3193
+ };
3194
+ $[0] = column;
3195
+ $[1] = onChange;
3196
+ $[2] = t1;
3197
+ } else {
3198
+ t1 = $[2];
3199
+ }
3200
+ const onInput = t1;
3201
+ const t2 = `db-field-${column}`;
3202
+ const t3 = typeof value === "string" ? value : "";
3203
+ let t4;
3204
+ if ($[3] !== onInput || $[4] !== t2 || $[5] !== t3) {
3205
+ t4 = /* @__PURE__ */ jsxDEV("input", {
3206
+ className: FIELD_INPUT,
3207
+ "data-testid": t2,
3208
+ onChange: onInput,
3209
+ type: "text",
3210
+ value: t3
3211
+ }, void 0, false);
3212
+ $[3] = onInput;
3213
+ $[4] = t2;
3214
+ $[5] = t3;
3215
+ $[6] = t4;
3216
+ } else {
3217
+ t4 = $[6];
3218
+ }
3219
+ return t4;
3220
+ };
3221
+ const JsonField = (t0) => {
3222
+ const $ = c(19);
3223
+ const {
3224
+ column,
3225
+ onChange,
3226
+ value
3227
+ } = t0;
3228
+ const t = useT();
3229
+ let t1;
3230
+ if ($[0] !== value) {
3231
+ t1 = () => JSON.stringify(value, null, 2);
3232
+ $[0] = value;
3233
+ $[1] = t1;
3234
+ } else {
3235
+ t1 = $[1];
3236
+ }
3237
+ const [text, setText] = useState(t1);
3238
+ const [error, setError] = useState(false);
3239
+ let t2;
3240
+ if ($[2] !== column || $[3] !== onChange) {
3241
+ t2 = (event) => {
3242
+ const next = event.target.value;
3243
+ setText(next);
3244
+ try {
3245
+ onChange(column, JSON.parse(next));
3246
+ setError(false);
3247
+ } catch {
3248
+ setError(true);
3249
+ }
3250
+ };
3251
+ $[2] = column;
3252
+ $[3] = onChange;
3253
+ $[4] = t2;
3254
+ } else {
3255
+ t2 = $[4];
3256
+ }
3257
+ const onInput = t2;
3258
+ const t3 = error && "border-destructive";
3259
+ let t4;
3260
+ if ($[5] !== t3) {
3261
+ t4 = cn(FIELD_INPUT, "min-h-16", t3);
3262
+ $[5] = t3;
3263
+ $[6] = t4;
3264
+ } else {
3265
+ t4 = $[6];
3266
+ }
3267
+ const t5 = `db-field-${column}`;
3268
+ let t6;
3269
+ if ($[7] !== onInput || $[8] !== t4 || $[9] !== t5 || $[10] !== text) {
3270
+ t6 = /* @__PURE__ */ jsxDEV("textarea", {
3271
+ className: t4,
3272
+ "data-testid": t5,
3273
+ onChange: onInput,
3274
+ value: text
3275
+ }, void 0, false);
3276
+ $[7] = onInput;
3277
+ $[8] = t4;
3278
+ $[9] = t5;
3279
+ $[10] = text;
3280
+ $[11] = t6;
3281
+ } else {
3282
+ t6 = $[11];
3283
+ }
3284
+ let t7;
3285
+ if ($[12] !== column || $[13] !== error || $[14] !== t) {
3286
+ t7 = error && /* @__PURE__ */ jsxDEV("span", {
3287
+ className: "text-xs text-destructive",
3288
+ "data-testid": `db-field-error-${column}`,
3289
+ children: t("Invalid JSON")
3290
+ }, void 0, false);
3291
+ $[12] = column;
3292
+ $[13] = error;
3293
+ $[14] = t;
3294
+ $[15] = t7;
3295
+ } else {
3296
+ t7 = $[15];
3297
+ }
3298
+ let t8;
3299
+ if ($[16] !== t6 || $[17] !== t7) {
3300
+ t8 = /* @__PURE__ */ jsxDEV("div", {
3301
+ className: "flex flex-col gap-1",
3302
+ children: [t6, t7]
3303
+ }, void 0, true);
3304
+ $[16] = t6;
3305
+ $[17] = t7;
3306
+ $[18] = t8;
3307
+ } else {
3308
+ t8 = $[18];
3309
+ }
3310
+ return t8;
3311
+ };
3312
+ const FieldRow = (t0) => {
3313
+ const $ = c(43);
3314
+ const {
3315
+ column,
3316
+ onChange,
3317
+ target,
3318
+ value
3319
+ } = t0;
3320
+ let t1;
3321
+ if ($[0] !== column || $[1] !== value) {
3322
+ t1 = inferKind(column, value);
3323
+ $[0] = column;
3324
+ $[1] = value;
3325
+ $[2] = t1;
3326
+ } else {
3327
+ t1 = $[2];
3328
+ }
3329
+ const kind = t1;
3330
+ const t2 = `db-field-${column}`;
3331
+ let t3;
3332
+ if ($[3] !== column) {
3333
+ t3 = /* @__PURE__ */ jsxDEV("span", {
3334
+ className: "font-mono",
3335
+ children: column
3336
+ }, void 0, false);
3337
+ $[3] = column;
3338
+ $[4] = t3;
3339
+ } else {
3340
+ t3 = $[4];
3341
+ }
3342
+ let t4;
3343
+ if ($[5] !== target) {
3344
+ t4 = target !== void 0 && /* @__PURE__ */ jsxDEV("span", {
3345
+ className: "rounded bg-muted px-1 font-mono text-[10px] tracking-wide uppercase",
3346
+ children: ["→ ", target]
3347
+ }, void 0, true);
3348
+ $[5] = target;
3349
+ $[6] = t4;
3350
+ } else {
3351
+ t4 = $[6];
3352
+ }
3353
+ let t5;
3354
+ if ($[7] !== t3 || $[8] !== t4) {
3355
+ t5 = /* @__PURE__ */ jsxDEV("span", {
3356
+ className: "flex items-center gap-1.5 font-medium text-muted-foreground",
3357
+ children: [t3, t4]
3358
+ }, void 0, true);
3359
+ $[7] = t3;
3360
+ $[8] = t4;
3361
+ $[9] = t5;
3362
+ } else {
3363
+ t5 = $[9];
3364
+ }
3365
+ let t6;
3366
+ if ($[10] !== column || $[11] !== kind || $[12] !== onChange || $[13] !== value) {
3367
+ t6 = kind === "boolean" && /* @__PURE__ */ jsxDEV(BooleanField, {
3368
+ column,
3369
+ onChange,
3370
+ value
3371
+ }, void 0, false);
3372
+ $[10] = column;
3373
+ $[11] = kind;
3374
+ $[12] = onChange;
3375
+ $[13] = value;
3376
+ $[14] = t6;
3377
+ } else {
3378
+ t6 = $[14];
3379
+ }
3380
+ let t7;
3381
+ if ($[15] !== column || $[16] !== kind || $[17] !== onChange || $[18] !== value) {
3382
+ t7 = kind === "number" && /* @__PURE__ */ jsxDEV(NumberField, {
3383
+ column,
3384
+ onChange,
3385
+ value
3386
+ }, void 0, false);
3387
+ $[15] = column;
3388
+ $[16] = kind;
3389
+ $[17] = onChange;
3390
+ $[18] = value;
3391
+ $[19] = t7;
3392
+ } else {
3393
+ t7 = $[19];
3394
+ }
3395
+ let t8;
3396
+ if ($[20] !== column || $[21] !== kind || $[22] !== onChange || $[23] !== value) {
3397
+ t8 = kind === "date" && /* @__PURE__ */ jsxDEV(DateField, {
3398
+ column,
3399
+ onChange,
3400
+ value
3401
+ }, void 0, false);
3402
+ $[20] = column;
3403
+ $[21] = kind;
3404
+ $[22] = onChange;
3405
+ $[23] = value;
3406
+ $[24] = t8;
3407
+ } else {
3408
+ t8 = $[24];
3409
+ }
3410
+ let t9;
3411
+ if ($[25] !== column || $[26] !== kind || $[27] !== onChange || $[28] !== value) {
3412
+ t9 = kind === "json" && /* @__PURE__ */ jsxDEV(JsonField, {
3413
+ column,
3414
+ onChange,
3415
+ value
3416
+ }, void 0, false);
3417
+ $[25] = column;
3418
+ $[26] = kind;
3419
+ $[27] = onChange;
3420
+ $[28] = value;
3421
+ $[29] = t9;
3422
+ } else {
3423
+ t9 = $[29];
3424
+ }
3425
+ let t10;
3426
+ if ($[30] !== column || $[31] !== kind || $[32] !== onChange || $[33] !== value) {
3427
+ t10 = kind === "text" && /* @__PURE__ */ jsxDEV(TextField, {
3428
+ column,
3429
+ onChange,
3430
+ value
3431
+ }, void 0, false);
3432
+ $[30] = column;
3433
+ $[31] = kind;
3434
+ $[32] = onChange;
3435
+ $[33] = value;
3436
+ $[34] = t10;
3437
+ } else {
3438
+ t10 = $[34];
3439
+ }
3440
+ let t11;
3441
+ if ($[35] !== t10 || $[36] !== t2 || $[37] !== t5 || $[38] !== t6 || $[39] !== t7 || $[40] !== t8 || $[41] !== t9) {
3442
+ t11 = /* @__PURE__ */ jsxDEV("label", {
3443
+ className: "flex flex-col gap-1 text-xs",
3444
+ htmlFor: t2,
3445
+ children: [t5, t6, t7, t8, t9, t10]
3446
+ }, void 0, true);
3447
+ $[35] = t10;
3448
+ $[36] = t2;
3449
+ $[37] = t5;
3450
+ $[38] = t6;
3451
+ $[39] = t7;
3452
+ $[40] = t8;
3453
+ $[41] = t9;
3454
+ $[42] = t11;
3455
+ } else {
3456
+ t11 = $[42];
3457
+ }
3458
+ return t11;
3459
+ };
3460
+ const RowFormEditor = (t0) => {
3461
+ const $ = c(48);
3462
+ const {
3463
+ documentText,
3464
+ onCancel,
3465
+ onDocumentTextChange,
3466
+ onSave,
3467
+ refs
3468
+ } = t0;
3469
+ const t = useT();
3470
+ let t1;
3471
+ if ($[0] !== documentText) {
3472
+ t1 = parseDocument(documentText);
3473
+ $[0] = documentText;
3474
+ $[1] = t1;
3475
+ } else {
3476
+ t1 = $[1];
3477
+ }
3478
+ const fields = t1;
3479
+ const [rawMode, setRawMode] = useState(false);
3480
+ const showForm = !rawMode && fields !== null;
3481
+ let t2;
3482
+ if ($[2] !== fields || $[3] !== onDocumentTextChange) {
3483
+ t2 = (column, value) => {
3484
+ onDocumentTextChange(JSON.stringify({
3485
+ ...fields,
3486
+ [column]: value
3487
+ }, null, 2));
3488
+ };
3489
+ $[2] = fields;
3490
+ $[3] = onDocumentTextChange;
3491
+ $[4] = t2;
3492
+ } else {
3493
+ t2 = $[4];
3494
+ }
3495
+ const onField = t2;
3496
+ let t3;
3497
+ if ($[5] !== onDocumentTextChange) {
3498
+ t3 = (event) => {
3499
+ onDocumentTextChange(event.target.value);
3500
+ };
3501
+ $[5] = onDocumentTextChange;
3502
+ $[6] = t3;
3503
+ } else {
3504
+ t3 = $[6];
3505
+ }
3506
+ const onTextarea = t3;
3507
+ let t4;
3508
+ if ($[7] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
3509
+ t4 = () => {
3510
+ setRawMode(false);
3511
+ };
3512
+ $[7] = t4;
3513
+ } else {
3514
+ t4 = $[7];
3515
+ }
3516
+ const showFormMode = t4;
3517
+ let t5;
3518
+ if ($[8] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
3519
+ t5 = () => {
3520
+ setRawMode(true);
3521
+ };
3522
+ $[8] = t5;
3523
+ } else {
3524
+ t5 = $[8];
3525
+ }
3526
+ const showJsonMode = t5;
3527
+ const t6 = fields === null;
3528
+ let t7;
3529
+ if ($[9] !== t) {
3530
+ t7 = t("Form");
3531
+ $[9] = t;
3532
+ $[10] = t7;
3533
+ } else {
3534
+ t7 = $[10];
3535
+ }
3536
+ let t8;
3537
+ if ($[11] !== showForm || $[12] !== t6 || $[13] !== t7) {
3538
+ t8 = /* @__PURE__ */ jsxDEV("button", {
3539
+ "aria-pressed": showForm,
3540
+ className: CONTROL_BTN$1,
3541
+ "data-testid": "db-editor-form",
3542
+ disabled: t6,
3543
+ onClick: showFormMode,
3544
+ type: "button",
3545
+ children: t7
3546
+ }, void 0, false);
3547
+ $[11] = showForm;
3548
+ $[12] = t6;
3549
+ $[13] = t7;
3550
+ $[14] = t8;
3551
+ } else {
3552
+ t8 = $[14];
3553
+ }
3554
+ const t9 = !showForm;
3555
+ let t10;
3556
+ if ($[15] !== t) {
3557
+ t10 = t("JSON");
3558
+ $[15] = t;
3559
+ $[16] = t10;
3560
+ } else {
3561
+ t10 = $[16];
3562
+ }
3563
+ let t11;
3564
+ if ($[17] !== t10 || $[18] !== t9) {
3565
+ t11 = /* @__PURE__ */ jsxDEV("button", {
3566
+ "aria-pressed": t9,
3567
+ className: CONTROL_BTN$1,
3568
+ "data-testid": "db-editor-json",
3569
+ onClick: showJsonMode,
3570
+ type: "button",
3571
+ children: t10
3572
+ }, void 0, false);
3573
+ $[17] = t10;
3574
+ $[18] = t9;
3575
+ $[19] = t11;
3576
+ } else {
3577
+ t11 = $[19];
3578
+ }
3579
+ let t12;
3580
+ if ($[20] !== t11 || $[21] !== t8) {
3581
+ t12 = /* @__PURE__ */ jsxDEV("div", {
3582
+ className: "flex items-center gap-1.5",
3583
+ children: [t8, t11]
3584
+ }, void 0, true);
3585
+ $[20] = t11;
3586
+ $[21] = t8;
3587
+ $[22] = t12;
3588
+ } else {
3589
+ t12 = $[22];
3590
+ }
3591
+ let t13;
3592
+ if ($[23] !== documentText || $[24] !== fields || $[25] !== onField || $[26] !== onTextarea || $[27] !== refs || $[28] !== showForm || $[29] !== t) {
3593
+ t13 = showForm ? /* @__PURE__ */ jsxDEV("div", {
3594
+ className: "flex flex-col gap-3",
3595
+ "data-testid": "db-editor-fields",
3596
+ children: Object.entries(fields).map((t142) => {
3597
+ const [column_0, value_0] = t142;
3598
+ return /* @__PURE__ */ jsxDEV(FieldRow, {
3599
+ column: column_0,
3600
+ onChange: onField,
3601
+ target: refs?.[column_0],
3602
+ value: value_0
3603
+ }, column_0, false);
3604
+ })
3605
+ }, void 0, false) : /* @__PURE__ */ jsxDEV("textarea", {
3606
+ "aria-label": t("Row document JSON"),
3607
+ className: "min-h-28 w-full rounded-md border border-border bg-background px-2 py-1.5 font-mono text-xs outline-none focus-visible:border-ring",
3608
+ "data-testid": "db-editor-doc",
3609
+ onChange: onTextarea,
3610
+ value: documentText
3611
+ }, void 0, false);
3612
+ $[23] = documentText;
3613
+ $[24] = fields;
3614
+ $[25] = onField;
3615
+ $[26] = onTextarea;
3616
+ $[27] = refs;
3617
+ $[28] = showForm;
3618
+ $[29] = t;
3619
+ $[30] = t13;
3620
+ } else {
3621
+ t13 = $[30];
3622
+ }
3623
+ let t14;
3624
+ if ($[31] !== t) {
3625
+ t14 = t("Save");
3626
+ $[31] = t;
3627
+ $[32] = t14;
3628
+ } else {
3629
+ t14 = $[32];
3630
+ }
3631
+ let t15;
3632
+ if ($[33] !== onSave || $[34] !== t14) {
3633
+ t15 = /* @__PURE__ */ jsxDEV("button", {
3634
+ className: CONTROL_BTN$1,
3635
+ "data-testid": "db-editor-save",
3636
+ onClick: onSave,
3637
+ type: "button",
3638
+ children: t14
3639
+ }, void 0, false);
3640
+ $[33] = onSave;
3641
+ $[34] = t14;
3642
+ $[35] = t15;
3643
+ } else {
3644
+ t15 = $[35];
3645
+ }
3646
+ let t16;
3647
+ if ($[36] !== t) {
3648
+ t16 = t("Cancel");
3649
+ $[36] = t;
3650
+ $[37] = t16;
3651
+ } else {
3652
+ t16 = $[37];
3653
+ }
3654
+ let t17;
3655
+ if ($[38] !== onCancel || $[39] !== t16) {
3656
+ t17 = /* @__PURE__ */ jsxDEV("button", {
3657
+ className: CONTROL_BTN$1,
3658
+ "data-testid": "db-editor-cancel",
3659
+ onClick: onCancel,
3660
+ type: "button",
3661
+ children: t16
3662
+ }, void 0, false);
3663
+ $[38] = onCancel;
3664
+ $[39] = t16;
3665
+ $[40] = t17;
3666
+ } else {
3667
+ t17 = $[40];
3668
+ }
3669
+ let t18;
3670
+ if ($[41] !== t15 || $[42] !== t17) {
3671
+ t18 = /* @__PURE__ */ jsxDEV("div", {
3672
+ className: "flex items-center gap-1.5",
3673
+ children: [t15, t17]
3674
+ }, void 0, true);
3675
+ $[41] = t15;
3676
+ $[42] = t17;
3677
+ $[43] = t18;
3678
+ } else {
3679
+ t18 = $[43];
3680
+ }
3681
+ let t19;
3682
+ if ($[44] !== t12 || $[45] !== t13 || $[46] !== t18) {
3683
+ t19 = /* @__PURE__ */ jsxDEV("div", {
3684
+ className: "flex flex-col gap-2 border border-border bg-card p-3",
3685
+ "data-testid": "db-editor",
3686
+ children: [t12, t13, t18]
3687
+ }, void 0, true);
3688
+ $[44] = t12;
3689
+ $[45] = t13;
3690
+ $[46] = t18;
3691
+ $[47] = t19;
3692
+ } else {
3693
+ t19 = $[47];
3694
+ }
3695
+ return t19;
3696
+ };
3697
+
3698
+ const MAX_SUMMARY_TABLES = 50;
3699
+ const ShardButton = (t0) => {
3700
+ const $ = c(8);
3701
+ const {
3702
+ active,
3703
+ onPick,
3704
+ shard
3705
+ } = t0;
3706
+ let t1;
3707
+ if ($[0] !== onPick || $[1] !== shard) {
3708
+ t1 = () => {
3709
+ onPick(shard);
3710
+ };
3711
+ $[0] = onPick;
3712
+ $[1] = shard;
3713
+ $[2] = t1;
3714
+ } else {
3715
+ t1 = $[2];
3716
+ }
3717
+ const handleClick = t1;
3718
+ const t2 = `w-full rounded px-2 py-0.5 text-left text-xs transition-colors hover:bg-accent ${active ? "bg-accent font-medium" : ""}`;
3719
+ const t3 = `shard-explorer-item-${shard}`;
3720
+ let t4;
3721
+ if ($[3] !== handleClick || $[4] !== shard || $[5] !== t2 || $[6] !== t3) {
3722
+ t4 = /* @__PURE__ */ jsxDEV("button", {
3723
+ className: t2,
3724
+ "data-testid": t3,
3725
+ onClick: handleClick,
3726
+ type: "button",
3727
+ children: shard
3728
+ }, void 0, false);
3729
+ $[3] = handleClick;
3730
+ $[4] = shard;
3731
+ $[5] = t2;
3732
+ $[6] = t3;
3733
+ $[7] = t4;
3734
+ } else {
3735
+ t4 = $[7];
3736
+ }
3737
+ return t4;
3738
+ };
3739
+ const ShardExplorer = ({
3740
+ onFetchTables,
3741
+ onSelect
3742
+ }) => {
3743
+ const t = useT();
3744
+ const [recents] = useState(() => loadRecentShards());
3745
+ const [open, setOpen] = useState(false);
3746
+ const [activeShard, setActiveShard] = useState(void 0);
3747
+ const [tables, setTables] = useState(void 0);
3748
+ const [loading, setLoading] = useState(false);
3749
+ const [error, setError] = useState(void 0);
3750
+ const requestIdRef = useRef(0);
3751
+ const toggleOpen = () => {
3752
+ setOpen((current) => !current);
3753
+ };
3754
+ const pickShardAsync = async (shardKey) => {
3755
+ onSelect(shardKey);
3756
+ setActiveShard(shardKey);
3757
+ setTables(void 0);
3758
+ setError(void 0);
3759
+ setLoading(true);
3760
+ requestIdRef.current += 1;
3761
+ const myRequestId = requestIdRef.current;
3762
+ try {
3763
+ const result = await onFetchTables(shardKey);
3764
+ if (requestIdRef.current === myRequestId) {
3765
+ setTables(result?.slice(0, MAX_SUMMARY_TABLES));
3766
+ }
3767
+ } catch (error_) {
3768
+ if (requestIdRef.current === myRequestId) {
3769
+ setError(error_.message);
3770
+ }
3771
+ } finally {
3772
+ if (requestIdRef.current === myRequestId) {
3773
+ setLoading(false);
3774
+ }
3775
+ }
3776
+ };
3777
+ const pickShard = (shardKey_0) => {
3778
+ fireAndForget(pickShardAsync(shardKey_0));
3779
+ };
3780
+ if (recents.length === 0) {
3781
+ return null;
3782
+ }
3783
+ return /* @__PURE__ */ jsxDEV("div", {
3784
+ "data-testid": "shard-explorer",
3785
+ children: [/* @__PURE__ */ jsxDEV("button", {
3786
+ "aria-controls": "shard-explorer-panel",
3787
+ "aria-expanded": open,
3788
+ className: "inline-flex items-center gap-1 rounded-md border border-border px-2 py-1 text-xs font-medium text-foreground outline-none transition-colors hover:bg-accent focus-visible:bg-accent",
3789
+ "data-testid": "shard-explorer-toggle",
3790
+ onClick: toggleOpen,
3791
+ type: "button",
3792
+ children: [t("Shards seen"), /* @__PURE__ */ jsxDEV("span", {
3793
+ "aria-hidden": "true",
3794
+ className: `ml-0.5 transition-transform ${open ? "rotate-180" : ""}`,
3795
+ children: "▾"
3796
+ }, void 0, false)]
3797
+ }, void 0, true), open && /* @__PURE__ */ jsxDEV("div", {
3798
+ className: "mt-1 flex flex-col gap-1 rounded-md border border-border bg-popover p-2",
3799
+ "data-testid": "shard-explorer-panel",
3800
+ id: "shard-explorer-panel",
3801
+ children: [/* @__PURE__ */ jsxDEV("p", {
3802
+ className: "text-xs text-muted-foreground",
3803
+ "data-testid": "shard-explorer-hint",
3804
+ children: t("Recently visited shards — click to switch")
3805
+ }, void 0, false), /* @__PURE__ */ jsxDEV("ul", {
3806
+ className: "flex flex-col gap-0.5",
3807
+ "data-testid": "shard-explorer-list",
3808
+ children: recents.map((shard) => /* @__PURE__ */ jsxDEV("li", {
3809
+ children: /* @__PURE__ */ jsxDEV(ShardButton, {
3810
+ active: activeShard === shard,
3811
+ onPick: pickShard,
3812
+ shard
3813
+ }, void 0, false)
3814
+ }, shard, false))
3815
+ }, void 0, false), activeShard !== void 0 && /* @__PURE__ */ jsxDEV("div", {
3816
+ className: "mt-1 border-t border-border pt-1",
3817
+ "data-testid": "shard-explorer-summary",
3818
+ children: [/* @__PURE__ */ jsxDEV("p", {
3819
+ className: "mb-1 text-xs font-medium text-foreground",
3820
+ "data-testid": "shard-explorer-summary-title",
3821
+ children: t("{shard} tables", {
3822
+ shard: activeShard
3823
+ })
3824
+ }, void 0, false), loading && /* @__PURE__ */ jsxDEV("p", {
3825
+ className: "text-xs text-muted-foreground",
3826
+ "data-testid": "shard-explorer-loading",
3827
+ children: t("Loading…")
3828
+ }, void 0, false), error !== void 0 && /* @__PURE__ */ jsxDEV("p", {
3829
+ className: "text-xs text-destructive",
3830
+ "data-testid": "shard-explorer-error",
3831
+ role: "alert",
3832
+ children: error
3833
+ }, void 0, false), !loading && error === void 0 && tables?.length === 0 && /* @__PURE__ */ jsxDEV("p", {
3834
+ className: "text-xs text-muted-foreground",
3835
+ "data-testid": "shard-explorer-empty",
3836
+ children: t("No tables in this shard.")
3837
+ }, void 0, false), !loading && error === void 0 && tables !== void 0 && tables.length > 0 && /* @__PURE__ */ jsxDEV("ul", {
3838
+ className: "flex flex-col gap-0.5",
3839
+ "data-testid": "shard-explorer-tables",
3840
+ children: tables.map((tableInfo) => /* @__PURE__ */ jsxDEV("li", {
3841
+ className: "flex items-center justify-between text-xs",
3842
+ children: [/* @__PURE__ */ jsxDEV("span", {
3843
+ "data-testid": `shard-explorer-table-${tableInfo.name}`,
3844
+ children: tableInfo.name
3845
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
3846
+ className: "text-muted-foreground",
3847
+ "data-testid": `shard-explorer-rowcount-${tableInfo.name}`,
3848
+ children: tableInfo.rowCount
3849
+ }, void 0, false)]
3850
+ }, tableInfo.name, true))
3851
+ }, void 0, false)]
3852
+ }, void 0, true)]
3853
+ }, void 0, true)]
3854
+ }, void 0, true);
3855
+ };
3856
+
3857
+ const DEFAULT_PAGE_SIZE = 50;
3858
+ const NO_TABLES = [];
3859
+ const CONTROL_BTN = "inline-flex items-center gap-1 rounded-md border border-border px-2.5 py-1 text-xs font-medium text-foreground outline-none transition-colors hover:bg-accent focus-visible:bg-accent disabled:pointer-events-none disabled:opacity-50 aria-pressed:bg-accent aria-pressed:text-accent-foreground";
3860
+ const LIST_TABLES = adminRef(ADMIN_FUNCTIONS.listTables);
3861
+ const DataBrowserSidebarHeader = (t0) => {
3862
+ const $ = c(10);
3863
+ const {
3864
+ onFetchShardTables,
3865
+ onShardChange,
3866
+ schemaSwitch,
3867
+ shardKey
3868
+ } = t0;
3869
+ let t1;
3870
+ if ($[0] !== onShardChange || $[1] !== shardKey) {
3871
+ t1 = /* @__PURE__ */ jsxDEV(ShardInput, {
3872
+ onChange: onShardChange,
3873
+ testId: "db-shard-input",
3874
+ value: shardKey
3875
+ }, void 0, false);
3876
+ $[0] = onShardChange;
3877
+ $[1] = shardKey;
3878
+ $[2] = t1;
3879
+ } else {
3880
+ t1 = $[2];
3881
+ }
3882
+ let t2;
3883
+ if ($[3] !== onFetchShardTables || $[4] !== onShardChange) {
3884
+ t2 = /* @__PURE__ */ jsxDEV(ShardExplorer, {
3885
+ onFetchTables: onFetchShardTables,
3886
+ onSelect: onShardChange
3887
+ }, void 0, false);
3888
+ $[3] = onFetchShardTables;
3889
+ $[4] = onShardChange;
3890
+ $[5] = t2;
3891
+ } else {
3892
+ t2 = $[5];
3893
+ }
3894
+ let t3;
3895
+ if ($[6] !== schemaSwitch || $[7] !== t1 || $[8] !== t2) {
3896
+ t3 = /* @__PURE__ */ jsxDEV("div", {
3897
+ className: "flex shrink-0 flex-col items-stretch gap-2 border-b border-border p-3",
3898
+ children: [schemaSwitch, t1, t2]
3899
+ }, void 0, true);
3900
+ $[6] = schemaSwitch;
3901
+ $[7] = t1;
3902
+ $[8] = t2;
3903
+ $[9] = t3;
3904
+ } else {
3905
+ t3 = $[9];
3906
+ }
3907
+ return t3;
3908
+ };
3909
+ const DataBrowserViewControls = (t0) => {
3910
+ const $ = c(60);
3911
+ const {
3912
+ columns,
3913
+ editable,
3914
+ filter,
3915
+ filters,
3916
+ hasMaskedColumns,
3917
+ liveError,
3918
+ maskOn,
3919
+ onAddRow,
3920
+ onBulkDelete,
3921
+ onClearTable,
3922
+ onFilterChange,
3923
+ onFiltersChange,
3924
+ onGenerateRows,
3925
+ onShowJson,
3926
+ onShowTable,
3927
+ onToggleMask,
3928
+ total,
3929
+ viewMode
3930
+ } = t0;
3931
+ const t = useT();
3932
+ const t1 = viewMode === "table";
3933
+ let t2;
3934
+ if ($[0] !== onShowTable || $[1] !== t1) {
3935
+ t2 = /* @__PURE__ */ jsxDEV("button", {
3936
+ "aria-pressed": t1,
3937
+ className: CONTROL_BTN,
3938
+ "data-testid": "db-view-table",
3939
+ onClick: onShowTable,
3940
+ type: "button",
3941
+ children: "Table"
3942
+ }, void 0, false);
3943
+ $[0] = onShowTable;
3944
+ $[1] = t1;
3945
+ $[2] = t2;
3946
+ } else {
3947
+ t2 = $[2];
3948
+ }
3949
+ const t3 = viewMode === "json";
3950
+ let t4;
3951
+ if ($[3] !== onShowJson || $[4] !== t3) {
3952
+ t4 = /* @__PURE__ */ jsxDEV("button", {
3953
+ "aria-pressed": t3,
3954
+ className: CONTROL_BTN,
3955
+ "data-testid": "db-view-json",
3956
+ onClick: onShowJson,
3957
+ type: "button",
3958
+ children: "JSON"
3959
+ }, void 0, false);
3960
+ $[3] = onShowJson;
3961
+ $[4] = t3;
3962
+ $[5] = t4;
3963
+ } else {
3964
+ t4 = $[5];
3965
+ }
3966
+ let t5;
3967
+ if ($[6] !== liveError || $[7] !== t) {
3968
+ t5 = liveError === void 0 ? t("Live — changes stream in automatically") : t("Live unavailable: {liveError}", {
3969
+ liveError
3970
+ });
3971
+ $[6] = liveError;
3972
+ $[7] = t;
3973
+ $[8] = t5;
3974
+ } else {
3975
+ t5 = $[8];
3976
+ }
3977
+ const t6 = `size-1.5 rounded-full ${liveError === void 0 ? "bg-success" : "bg-muted-foreground/50"}`;
3978
+ let t7;
3979
+ if ($[9] !== t6) {
3980
+ t7 = /* @__PURE__ */ jsxDEV("span", {
3981
+ "aria-hidden": "true",
3982
+ className: t6
3983
+ }, void 0, false);
3984
+ $[9] = t6;
3985
+ $[10] = t7;
3986
+ } else {
3987
+ t7 = $[10];
3988
+ }
3989
+ let t8;
3990
+ if ($[11] !== liveError || $[12] !== t) {
3991
+ t8 = liveError === void 0 ? t("Live") : t("Live unavailable");
3992
+ $[11] = liveError;
3993
+ $[12] = t;
3994
+ $[13] = t8;
3995
+ } else {
3996
+ t8 = $[13];
3997
+ }
3998
+ let t9;
3999
+ if ($[14] !== t5 || $[15] !== t7 || $[16] !== t8) {
4000
+ t9 = /* @__PURE__ */ jsxDEV("span", {
4001
+ className: "inline-flex items-center gap-1.5 px-1 text-xs font-medium text-muted-foreground",
4002
+ "data-testid": "db-live-indicator",
4003
+ role: "status",
4004
+ title: t5,
4005
+ children: [t7, t8]
4006
+ }, void 0, true);
4007
+ $[14] = t5;
4008
+ $[15] = t7;
4009
+ $[16] = t8;
4010
+ $[17] = t9;
4011
+ } else {
4012
+ t9 = $[17];
4013
+ }
4014
+ let t10;
4015
+ if ($[18] !== hasMaskedColumns || $[19] !== maskOn || $[20] !== onToggleMask || $[21] !== t) {
4016
+ t10 = hasMaskedColumns && /* @__PURE__ */ jsxDEV("button", {
4017
+ "aria-pressed": maskOn,
4018
+ className: CONTROL_BTN,
4019
+ "data-testid": "db-mask-toggle",
4020
+ onClick: onToggleMask,
4021
+ type: "button",
4022
+ children: t("Mask sensitive columns")
4023
+ }, void 0, false);
4024
+ $[18] = hasMaskedColumns;
4025
+ $[19] = maskOn;
4026
+ $[20] = onToggleMask;
4027
+ $[21] = t;
4028
+ $[22] = t10;
4029
+ } else {
4030
+ t10 = $[22];
4031
+ }
4032
+ let t11;
4033
+ if ($[23] !== editable || $[24] !== onAddRow) {
4034
+ t11 = editable && /* @__PURE__ */ jsxDEV("button", {
4035
+ className: CONTROL_BTN,
4036
+ "data-testid": "db-add-row",
4037
+ onClick: onAddRow,
4038
+ type: "button",
4039
+ children: "Add row"
4040
+ }, void 0, false);
4041
+ $[23] = editable;
4042
+ $[24] = onAddRow;
4043
+ $[25] = t11;
4044
+ } else {
4045
+ t11 = $[25];
4046
+ }
4047
+ let t12;
4048
+ if ($[26] !== editable || $[27] !== onGenerateRows || $[28] !== t) {
4049
+ t12 = editable && /* @__PURE__ */ jsxDEV("button", {
4050
+ className: CONTROL_BTN,
4051
+ "data-testid": "db-generate-rows",
4052
+ onClick: onGenerateRows,
4053
+ type: "button",
4054
+ children: t("Generate rows")
4055
+ }, void 0, false);
4056
+ $[26] = editable;
4057
+ $[27] = onGenerateRows;
4058
+ $[28] = t;
4059
+ $[29] = t12;
4060
+ } else {
4061
+ t12 = $[29];
4062
+ }
4063
+ let t13;
4064
+ if ($[30] !== editable || $[31] !== filter || $[32] !== filters || $[33] !== onBulkDelete || $[34] !== total) {
4065
+ t13 = editable && total > 0 && (filter !== "" || filters.length > 0) && /* @__PURE__ */ jsxDEV(ConfirmButton, {
4066
+ confirmLabel: `Delete ${total.toString()} matching?`,
4067
+ onConfirm: onBulkDelete,
4068
+ testId: "db-bulk-delete",
4069
+ children: `Delete ${total.toString()} matching`
4070
+ }, void 0, false);
4071
+ $[30] = editable;
4072
+ $[31] = filter;
4073
+ $[32] = filters;
4074
+ $[33] = onBulkDelete;
4075
+ $[34] = total;
4076
+ $[35] = t13;
4077
+ } else {
4078
+ t13 = $[35];
4079
+ }
4080
+ let t14;
4081
+ if ($[36] !== editable || $[37] !== filter || $[38] !== filters || $[39] !== onClearTable || $[40] !== total) {
4082
+ t14 = editable && total > 0 && filter === "" && filters.length === 0 && /* @__PURE__ */ jsxDEV(ConfirmButton, {
4083
+ confirmLabel: `Clear all ${total.toString()} rows?`,
4084
+ onConfirm: onClearTable,
4085
+ testId: "db-clear-table",
4086
+ children: `Clear table (${total.toString()})`
4087
+ }, void 0, false);
4088
+ $[36] = editable;
4089
+ $[37] = filter;
4090
+ $[38] = filters;
4091
+ $[39] = onClearTable;
4092
+ $[40] = total;
4093
+ $[41] = t14;
4094
+ } else {
4095
+ t14 = $[41];
4096
+ }
4097
+ let t15;
4098
+ if ($[42] !== t10 || $[43] !== t11 || $[44] !== t12 || $[45] !== t13 || $[46] !== t14 || $[47] !== t2 || $[48] !== t4 || $[49] !== t9) {
4099
+ t15 = /* @__PURE__ */ jsxDEV("div", {
4100
+ className: "flex flex-wrap items-center gap-1.5",
4101
+ children: [t2, t4, t9, t10, t11, t12, t13, t14]
4102
+ }, void 0, true);
4103
+ $[42] = t10;
4104
+ $[43] = t11;
4105
+ $[44] = t12;
4106
+ $[45] = t13;
4107
+ $[46] = t14;
4108
+ $[47] = t2;
4109
+ $[48] = t4;
4110
+ $[49] = t9;
4111
+ $[50] = t15;
4112
+ } else {
4113
+ t15 = $[50];
4114
+ }
4115
+ let t16;
4116
+ if ($[51] !== columns || $[52] !== filter || $[53] !== filters || $[54] !== onFilterChange || $[55] !== onFiltersChange) {
4117
+ t16 = /* @__PURE__ */ jsxDEV(DataFilters, {
4118
+ columns,
4119
+ filters,
4120
+ onFiltersChange,
4121
+ onSearchChange: onFilterChange,
4122
+ search: filter
4123
+ }, void 0, false);
4124
+ $[51] = columns;
4125
+ $[52] = filter;
4126
+ $[53] = filters;
4127
+ $[54] = onFilterChange;
4128
+ $[55] = onFiltersChange;
4129
+ $[56] = t16;
4130
+ } else {
4131
+ t16 = $[56];
4132
+ }
4133
+ let t17;
4134
+ if ($[57] !== t15 || $[58] !== t16) {
4135
+ t17 = /* @__PURE__ */ jsxDEV("div", {
4136
+ className: "flex flex-col gap-2",
4137
+ "data-testid": "db-view-toggle",
4138
+ children: [t15, t16]
4139
+ }, void 0, true);
4140
+ $[57] = t15;
4141
+ $[58] = t16;
4142
+ $[59] = t17;
4143
+ } else {
4144
+ t17 = $[59];
4145
+ }
4146
+ return t17;
4147
+ };
4148
+ const DataBrowser = ({
4149
+ editable = false,
4150
+ globalTableNames,
4151
+ initialFilters,
4152
+ initialOrderBy,
4153
+ initialSearch,
4154
+ initialShardKey,
4155
+ onNavigateToGlobal,
4156
+ onSelectTable,
4157
+ onViewChange,
4158
+ pageSize: initialPageSize = DEFAULT_PAGE_SIZE,
4159
+ queryBar,
4160
+ schemaSwitch,
4161
+ tableParam
4162
+ }) => {
4163
+ const {
4164
+ addRow,
4165
+ bulkDelete,
4166
+ cancelCellEdit,
4167
+ cancelEdit,
4168
+ changePageSize,
4169
+ clearTable,
4170
+ columns,
4171
+ committing,
4172
+ currentView,
4173
+ discardStaged,
4174
+ editableColumn,
4175
+ editing,
4176
+ editingCell,
4177
+ facetFilter,
4178
+ facets,
4179
+ filter,
4180
+ filters,
4181
+ goNext,
4182
+ goPrevious,
4183
+ hasNext,
4184
+ hasPrevious,
4185
+ jumpToPage,
4186
+ liveError,
4187
+ loadTables,
4188
+ navigateToRef,
4189
+ onBulkDeleteSelected,
4190
+ onCommitStaged,
4191
+ onFilterChange,
4192
+ onFiltersChange,
4193
+ onRowDelete,
4194
+ onRowEdit,
4195
+ page,
4196
+ pageError,
4197
+ previewRef,
4198
+ pageSize,
4199
+ rangeEnd,
4200
+ rangeStart,
4201
+ saveEdit,
4202
+ selectedTable,
4203
+ selectTable,
4204
+ setEditorDocumentText,
4205
+ setShardKey,
4206
+ shardKey,
4207
+ showJson,
4208
+ showTable,
4209
+ stage,
4210
+ stagedChanges,
4211
+ stagedValue,
4212
+ startCellEdit,
4213
+ table,
4214
+ tables,
4215
+ tablesError,
4216
+ toggleFacet,
4217
+ total,
4218
+ viewMode,
4219
+ writeError
4220
+ } = useDataBrowser({
4221
+ initialFilters,
4222
+ initialOrderBy,
4223
+ initialSearch,
4224
+ initialShardKey,
4225
+ onSelectTable,
4226
+ onViewChange,
4227
+ pageSize: initialPageSize,
4228
+ tableParam
4229
+ });
4230
+ const client = useLunora();
4231
+ const onFetchShardTables = async (targetShard) => {
4232
+ const result = await client.query(LIST_TABLES, {}, callOptions(targetShard));
4233
+ return result;
4234
+ };
4235
+ const onRefreshAfterGenerate = () => {
4236
+ if (selectedTable !== null) {
4237
+ selectTable(selectedTable);
4238
+ }
4239
+ };
4240
+ const {
4241
+ closeDialog: closeGenerateDialog,
4242
+ columnMeta,
4243
+ fkPools,
4244
+ insertBatch,
4245
+ open: generateOpen,
4246
+ openDialog: openGenerateDialog
4247
+ } = useGenerateRows(onRefreshAfterGenerate);
4248
+ const onOpenGenerateRows = () => {
4249
+ if (selectedTable !== null) {
4250
+ openGenerateDialog(selectedTable, shardKey);
4251
+ }
4252
+ };
4253
+ const onInsertGeneratedRows = (rows) => insertBatch(rows, closeGenerateDialog);
4254
+ const [inspecting, setInspecting] = useState(null);
4255
+ const closeInspect = () => {
4256
+ setInspecting(null);
4257
+ };
4258
+ const [transposed, setTransposed] = useState(false);
4259
+ const onToggleTranspose = () => {
4260
+ setTransposed((current) => !current);
4261
+ };
4262
+ const maskPolicies = useMaskPolicies();
4263
+ const [maskOn, setMaskOn] = useState(true);
4264
+ const onToggleMask = () => {
4265
+ setMaskOn((current_0) => !current_0);
4266
+ };
4267
+ const explicitMaskColumns = maskColumnsForTable(maskPolicies, selectedTable ?? "");
4268
+ const maskColumns = mergeSensitiveColumns(explicitMaskColumns, columns);
4269
+ const maskView = {
4270
+ columns: maskColumns,
4271
+ enabled: maskOn
4272
+ };
4273
+ const [expandedCell, setExpandedCell] = useState(null);
4274
+ const onExpandCell = (column, value) => {
4275
+ setExpandedCell({
4276
+ column,
4277
+ value
4278
+ });
4279
+ };
4280
+ const closeExpandedCell = () => {
4281
+ setExpandedCell(null);
4282
+ };
4283
+ const handleNavigateRef = (target, id) => {
4284
+ if (onNavigateToGlobal !== void 0 && globalTableNames?.has(target) === true) {
4285
+ onNavigateToGlobal(target, id);
4286
+ return;
4287
+ }
4288
+ navigateToRef(target, id);
4289
+ };
4290
+ const onSaveQuery = queryBar?.onSaveQuery;
4291
+ const saveCurrentQuery = (name) => {
4292
+ onSaveQuery?.(name, currentView);
4293
+ };
4294
+ const edit = {
4295
+ cancelEdit: cancelCellEdit,
4296
+ editable,
4297
+ editableColumn,
4298
+ editingCell,
4299
+ onExpandCell,
4300
+ stage,
4301
+ stagedValue,
4302
+ startEdit: startCellEdit
4303
+ };
4304
+ const references = {
4305
+ columns: page?.refs,
4306
+ onNavigate: handleNavigateRef,
4307
+ onPreview: previewRef
4308
+ };
4309
+ return /* @__PURE__ */ jsxDEV("div", {
4310
+ className: "flex h-full min-w-0",
4311
+ "data-testid": "lunora-data-browser",
4312
+ children: [/* @__PURE__ */ jsxDEV(TableListSidebar, {
4313
+ header: /* @__PURE__ */ jsxDEV(DataBrowserSidebarHeader, {
4314
+ onFetchShardTables,
4315
+ onShardChange: setShardKey,
4316
+ schemaSwitch,
4317
+ shardKey
4318
+ }, void 0, false),
4319
+ onReload: loadTables,
4320
+ onSelect: selectTable,
4321
+ prefix: "db",
4322
+ selected: selectedTable,
4323
+ tables: tables ?? NO_TABLES
4324
+ }, void 0, false), /* @__PURE__ */ jsxDEV("div", {
4325
+ className: "flex min-w-0 flex-1 flex-col overflow-hidden",
4326
+ children: [tablesError !== null && /* @__PURE__ */ jsxDEV("p", {
4327
+ className: "shrink-0 border-b border-border px-4 py-2 text-sm text-destructive",
4328
+ "data-testid": "db-tables-error",
4329
+ role: "alert",
4330
+ children: tablesError
4331
+ }, void 0, false), page === null && pageError === null && /* @__PURE__ */ jsxDEV("div", {
4332
+ className: "flex flex-1 items-center justify-center p-6",
4333
+ children: /* @__PURE__ */ jsxDEV("p", {
4334
+ className: "text-sm text-muted-foreground",
4335
+ children: "Select a table to browse its rows."
4336
+ }, void 0, false)
4337
+ }, void 0, false), pageError !== null && /* @__PURE__ */ jsxDEV("p", {
4338
+ className: "shrink-0 border-b border-border px-4 py-2 text-sm text-destructive",
4339
+ "data-testid": "db-page-error",
4340
+ role: "alert",
4341
+ children: pageError
4342
+ }, void 0, false), page !== null && /* @__PURE__ */ jsxDEV("div", {
4343
+ className: "flex min-h-0 flex-1 flex-col",
4344
+ "data-testid": "db-page",
4345
+ children: [/* @__PURE__ */ jsxDEV("div", {
4346
+ className: "flex shrink-0 flex-col gap-2 border-b border-border px-4 py-3",
4347
+ children: [/* @__PURE__ */ jsxDEV(DataBrowserViewControls, {
4348
+ columns,
4349
+ editable,
4350
+ filter,
4351
+ filters,
4352
+ hasMaskedColumns: maskColumns.size > 0,
4353
+ liveError,
4354
+ maskOn,
4355
+ onAddRow: addRow,
4356
+ onBulkDelete: bulkDelete,
4357
+ onClearTable: clearTable,
4358
+ onFilterChange,
4359
+ onFiltersChange,
4360
+ onGenerateRows: onOpenGenerateRows,
4361
+ onShowJson: showJson,
4362
+ onShowTable: showTable,
4363
+ onToggleMask,
4364
+ total,
4365
+ viewMode
4366
+ }, void 0, false), queryBar !== void 0 && /* @__PURE__ */ jsxDEV(DataQueryBar, {
4367
+ onApply: queryBar.onApplyQuery,
4368
+ onCopyLink: queryBar.onCopyLink,
4369
+ onDelete: queryBar.onDeleteQuery,
4370
+ onSave: saveCurrentQuery,
4371
+ saved: queryBar.saved
4372
+ }, void 0, false), viewMode === "table" && page.rows.length > 0 && /* @__PURE__ */ jsxDEV(GridActionsBar, {
4373
+ columns: page.columns,
4374
+ editable,
4375
+ name: selectedTable ?? "export",
4376
+ onBulkDelete: onBulkDeleteSelected,
4377
+ onToggleTranspose,
4378
+ rows: page.rows,
4379
+ table: table.table,
4380
+ transposed
4381
+ }, void 0, false), editable && editing !== null && /* @__PURE__ */ jsxDEV(RowFormEditor, {
4382
+ documentText: editing.docText,
4383
+ onCancel: cancelEdit,
4384
+ onDocumentTextChange: setEditorDocumentText,
4385
+ onSave: saveEdit,
4386
+ refs: page.refs
4387
+ }, void 0, false), editable && stagedChanges.length > 0 && /* @__PURE__ */ jsxDEV(StagedDiffPanel, {
4388
+ changes: stagedChanges,
4389
+ committing,
4390
+ onCommit: onCommitStaged,
4391
+ onDiscard: discardStaged
4392
+ }, void 0, false), writeError !== null && /* @__PURE__ */ jsxDEV("p", {
4393
+ className: "text-sm text-destructive",
4394
+ "data-testid": "db-write-error",
4395
+ role: "alert",
4396
+ children: writeError
4397
+ }, void 0, false)]
4398
+ }, void 0, true), viewMode === "table" && page.rows.length === 0 && /* @__PURE__ */ jsxDEV("div", {
4399
+ className: "flex flex-1 items-center justify-center p-6",
4400
+ children: /* @__PURE__ */ jsxDEV(EmptyState, {
4401
+ description: "Rows you insert into this table will show up here.",
4402
+ icon: /* @__PURE__ */ jsxDEV("svg", {
4403
+ "aria-hidden": "true",
4404
+ fill: "none",
4405
+ stroke: "currentColor",
4406
+ strokeLinecap: "round",
4407
+ strokeLinejoin: "round",
4408
+ strokeWidth: 1.6,
4409
+ viewBox: "0 0 24 24",
4410
+ children: /* @__PURE__ */ jsxDEV("path", {
4411
+ d: "M4 5h16v14H4V5Zm0 5h16M10 10v9M4 14.5h16"
4412
+ }, void 0, false)
4413
+ }, void 0, false),
4414
+ testId: "db-empty-rows",
4415
+ title: "This table is empty."
4416
+ }, void 0, false)
4417
+ }, void 0, false), viewMode === "table" && page.rows.length > 0 && transposed && /* @__PURE__ */ jsxDEV(TransposedTable, {
4418
+ columns: page.columns,
4419
+ rows: maskRows(page.rows, maskView)
4420
+ }, void 0, false), viewMode === "table" && page.rows.length > 0 && !transposed && /* @__PURE__ */ jsxDEV(DataBrowserTableView, {
4421
+ edit,
4422
+ editable,
4423
+ mask: maskView,
4424
+ onDelete: onRowDelete,
4425
+ onEdit: onRowEdit,
4426
+ onInspect: setInspecting,
4427
+ refs: references,
4428
+ scrollRef: table.scrollRef,
4429
+ scrollToIndex: table.scrollToIndex,
4430
+ table: table.table,
4431
+ tableRows: table.tableRows,
4432
+ tbodyStyle: table.tbodyStyle,
4433
+ virtualRows: table.virtualRows
4434
+ }, void 0, false), viewMode === "json" && /* @__PURE__ */ jsxDEV("pre", {
4435
+ className: "min-h-0 flex-1 overflow-auto border-t border-border bg-muted/30 p-3 text-xs",
4436
+ "data-testid": "db-json",
4437
+ children: JSON.stringify(maskRows(page.rows, maskView), null, 2)
4438
+ }, void 0, false), /* @__PURE__ */ jsxDEV("div", {
4439
+ className: "flex shrink-0 items-center border-t border-border px-4 py-2",
4440
+ children: /* @__PURE__ */ jsxDEV(GridPagination, {
4441
+ hasNext,
4442
+ hasPrevious,
4443
+ onJumpToPage: jumpToPage,
4444
+ onNext: goNext,
4445
+ onPageSizeChange: changePageSize,
4446
+ onPrevious: goPrevious,
4447
+ pageSize,
4448
+ prefix: "db",
4449
+ rangeEnd,
4450
+ rangeStart,
4451
+ total
4452
+ }, void 0, false)
4453
+ }, void 0, false)]
4454
+ }, void 0, true)]
4455
+ }, void 0, true), page !== null && /* @__PURE__ */ jsxDEV(DataFacets, {
4456
+ columns,
4457
+ facets,
4458
+ onFacetFilter: facetFilter,
4459
+ onToggleFacet: toggleFacet
4460
+ }, void 0, false), inspecting !== null && page !== null && /* @__PURE__ */ jsxDEV(RowDetailDrawer, {
4461
+ columns: page.columns,
4462
+ onClose: closeInspect,
4463
+ onNavigate: handleNavigateRef,
4464
+ refs: page.refs,
4465
+ row: inspecting
4466
+ }, void 0, false), expandedCell !== null && /* @__PURE__ */ jsxDEV(CellDetailDialog, {
4467
+ column: expandedCell.column,
4468
+ onClose: closeExpandedCell,
4469
+ value: expandedCell.value
4470
+ }, void 0, false), generateOpen && selectedTable !== null && columnMeta !== void 0 && /* @__PURE__ */ jsxDEV(GenerateRowsDialog, {
4471
+ columns: columnMeta,
4472
+ fkPools,
4473
+ onClose: closeGenerateDialog,
4474
+ onInsertRows: onInsertGeneratedRows,
4475
+ table: selectedTable
4476
+ }, void 0, false)]
4477
+ }, void 0, true);
4478
+ };
4479
+
4480
+ export { DataBrowser };