@lunora/studio 0.0.0 → 1.0.0-alpha.1

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 (81) 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 +1402 -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_FUNCTION_PREFIX-DmBqMZ-z.js +45 -0
  9. package/dist/packem_shared/ApiDocsPanel-DpRjJhG5.js +842 -0
  10. package/dist/packem_shared/ApiReferencePanel-DMIUp-kK.js +229 -0
  11. package/dist/packem_shared/ApiTab-DURGU15e.js +251 -0
  12. package/dist/packem_shared/AuditPanel-BC59Nhst.js +212 -0
  13. package/dist/packem_shared/CommandPalette-Dx_CoB9i.js +373 -0
  14. package/dist/packem_shared/ConfirmButton-WQVUoGFb.js +59 -0
  15. package/dist/packem_shared/ConnectionBadge-Bxagrip8.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/DataBrowser-Coz6jJE6.js +4542 -0
  19. package/dist/packem_shared/DataFilters-FNquMaiu.js +249 -0
  20. package/dist/packem_shared/ErrorBoundary-BzAApI7J.js +66 -0
  21. package/dist/packem_shared/ExportImportPanel-WO34fJxy.js +193 -0
  22. package/dist/packem_shared/FileBrowser-Zcr-Qgxo.js +2932 -0
  23. package/dist/packem_shared/FunctionRunner-j0Rd5m9t.js +343 -0
  24. package/dist/packem_shared/FunctionStatsPanel-DboBl-XL.js +432 -0
  25. package/dist/packem_shared/GlobalDataBrowser-9MhPEfgN.js +318 -0
  26. package/dist/packem_shared/HealthPanel-DOIgbUtx.js +640 -0
  27. package/dist/packem_shared/HomePanel-bdOCNA-p.js +1273 -0
  28. package/dist/packem_shared/InsightsPanel-DaZPnSgt.js +423 -0
  29. package/dist/packem_shared/LogsPanel-CWdqAGpQ.js +839 -0
  30. package/dist/packem_shared/MailPanel-D_EGtDnS.js +447 -0
  31. package/dist/packem_shared/MetricsPanel-E4Gv6wTO.js +1625 -0
  32. package/dist/packem_shared/MigrationsPanel-DQdPY9io.js +246 -0
  33. package/dist/packem_shared/OpenRpcReferencePanel-j2p3HB0s.js +191 -0
  34. package/dist/packem_shared/PitrPanel-BbBkQR6t.js +252 -0
  35. package/dist/packem_shared/STUDIO_ROOT_CLASS-D12gX2dV.js +3 -0
  36. package/dist/packem_shared/ScheduledJobs-Ok1CYYwI.js +159 -0
  37. package/dist/packem_shared/SchemaViewer-D8XGnp-X.js +2512 -0
  38. package/dist/packem_shared/SecurityAdvisorPanel-Cdm2IxLW.js +79 -0
  39. package/dist/packem_shared/SettingsPanel-D3WF2mBU.js +176 -0
  40. package/dist/packem_shared/ShardInput-DNCsT1KW.js +107 -0
  41. package/dist/packem_shared/SqlEditorPanel-BuQ7f2Hs.js +13 -0
  42. package/dist/packem_shared/Studio-D36od9Oz.js +33 -0
  43. package/dist/packem_shared/StudioApp-dvywkJ8I.js +383 -0
  44. package/dist/packem_shared/StudioI18nProvider-Dcajsznk.js +48 -0
  45. package/dist/packem_shared/TableEditor-DIVDk3vT.js +371 -0
  46. package/dist/packem_shared/advisor-view-DBlzJi6C.js +159 -0
  47. package/dist/packem_shared/aggregateMetrics-D4nUHEKU.js +108 -0
  48. package/dist/packem_shared/app.d-CCmwDEVs.d.ts +300 -0
  49. package/dist/packem_shared/badge-B2PKA1-5.js +49 -0
  50. package/dist/packem_shared/bar-chart-CzJAgqkp.js +3245 -0
  51. package/dist/packem_shared/button-BhsN2uZH.js +49 -0
  52. package/dist/packem_shared/card-DURq3ElK.js +175 -0
  53. package/dist/packem_shared/cf-links-BZfRdxSE.js +8 -0
  54. package/dist/packem_shared/checkbox-UNkzAxl-.js +63 -0
  55. package/dist/packem_shared/createStudioI18n-CgvlmDkN.js +27 -0
  56. package/dist/packem_shared/data-grid-CCh2Couo.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-DTjG6Sex.js +840 -0
  60. package/dist/packem_shared/input-XH4r1Pt1.js +53 -0
  61. package/dist/packem_shared/internal-BBZYexre.js +68 -0
  62. package/dist/packem_shared/label-D8ykjn5J.js +46 -0
  63. package/dist/packem_shared/live-status-bPff1O7Y.js +44 -0
  64. package/dist/packem_shared/reference-view-BCKIoai7.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-CW2y2x9h.js +2562 -0
  68. package/dist/packem_shared/storage-tier-CL98eOvn.js +85 -0
  69. package/dist/packem_shared/studio-BDVd7rIV.js +10303 -0
  70. package/dist/packem_shared/table-_RzNvy3R.js +246 -0
  71. package/dist/packem_shared/table-list-sidebar-aZHLq70w.js +832 -0
  72. package/dist/packem_shared/textarea-D3gaCU_-.js +46 -0
  73. package/dist/packem_shared/use-live-admin-D1h1Fzsd.js +73 -0
  74. package/dist/packem_shared/use-live-shard-seed-B74RYcOy.js +76 -0
  75. package/dist/packem_shared/useDebounced-Dxncpg6z.js +32 -0
  76. package/dist/packem_shared/utils-B05Dmz_H.js +8 -0
  77. package/dist/packem_shared/virtual-rect-CVMUskSm.js +10 -0
  78. package/dist/standalone/studio.js +356 -0
  79. package/dist/styles.css +2 -0
  80. package/package.json +77 -17
  81. package/src/theme.css +59 -0
@@ -0,0 +1,4542 @@
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-WQVUoGFb.js';
5
+ import { ShardInput } from './ShardInput-DNCsT1KW.js';
6
+ import { E as EmptyState } from './empty-state-DY_oe0k6.js';
7
+ import { useT } from './createStudioI18n-CgvlmDkN.js';
8
+ import { ADMIN_FUNCTIONS } from './ADMIN_FUNCTION_PREFIX-DmBqMZ-z.js';
9
+ import { h as formatCell, f as fireAndForget, c as callOptions, a as adminRef, d as formatTimestamp } from './internal-BBZYexre.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-CCh2Couo.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-aZHLq70w.js';
18
+ import { toFilterClauses, DataFilters } from './DataFilters-FNquMaiu.js';
19
+ import { M as ModalShell, G as GridActionsBar, C as CellDetailDialog } from './grid-features-DTjG6Sex.js';
20
+ import useDebounced from './useDebounced-Dxncpg6z.js';
21
+ import { u as useLiveAdmin } from './use-live-admin-D1h1Fzsd.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 LIST_TABLES$1 = adminRef(ADMIN_FUNCTIONS.listTables);
2164
+ const READ_TABLE_PAGE$1 = adminRef(ADMIN_FUNCTIONS.readTablePage);
2165
+ const FACET_COLUMN = adminRef(ADMIN_FUNCTIONS.facetColumn);
2166
+ const WRITE_ROW$1 = adminRef(ADMIN_FUNCTIONS.writeRow);
2167
+ const DELETE_ROWS = adminRef(ADMIN_FUNCTIONS.deleteRows);
2168
+ const CLEAR_TABLE = adminRef(ADMIN_FUNCTIONS.clearTable);
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 [tables, setTables] = useState(null);
2209
+ const [tablesError, setTablesError] = useState(null);
2210
+ const [selectedTable, setSelectedTable] = useState(null);
2211
+ const [offset, setOffset] = useState(0);
2212
+ const [page, setPage] = useState(null);
2213
+ const [pageError, setPageError] = useState(null);
2214
+ const [viewMode, setViewMode] = useState("table");
2215
+ const [sorting, setSorting] = useState(() => fromOrderBy(initialOrderBy));
2216
+ const [filter, setFilter] = useState(initialSearch ?? "");
2217
+ const search = useDebounced(filter.trim(), 300);
2218
+ const debouncedShard = useDebounced(shardKey.trim(), 400);
2219
+ const [filters, setFilters] = useState(() => toEditableFilters(initialFilters ?? []));
2220
+ const filtersRef = useRef(filters);
2221
+ filtersRef.current = filters;
2222
+ const {
2223
+ clearFacets,
2224
+ facets,
2225
+ refetchFacets,
2226
+ toggleFacet: toggleFacetColumn
2227
+ } = useFacets();
2228
+ const sortingRef = useRef(sorting);
2229
+ sortingRef.current = sorting;
2230
+ const [editing, setEditing] = useState(null);
2231
+ const [writeError, setWriteError] = useState(null);
2232
+ const stagedEdits = useStagedEdits();
2233
+ const [editingCell, setEditingCell] = useState(null);
2234
+ const [committing, setCommitting] = useState(false);
2235
+ const [liveError, setLiveError] = useState(void 0);
2236
+ const [loaded, setLoaded] = useState(null);
2237
+ const fetchTables = useCallback(async (shard) => {
2238
+ setTablesError(null);
2239
+ try {
2240
+ const result = await client.query(LIST_TABLES$1, {}, callOptions(shard));
2241
+ recordShard(shard);
2242
+ setTables(result);
2243
+ } catch (error) {
2244
+ setTables(null);
2245
+ setTablesError(error.message);
2246
+ }
2247
+ }, [client]);
2248
+ const fetchSeqRef = useRef(0);
2249
+ const fetchPage = useCallback(async (shard_0, table, nextOffset, searchQuery) => {
2250
+ fetchSeqRef.current += 1;
2251
+ const seq = fetchSeqRef.current;
2252
+ setPageError(null);
2253
+ const activeFilters = filtersRef.current;
2254
+ const activeSort = sortingRef.current;
2255
+ try {
2256
+ const result_0 = await client.query(READ_TABLE_PAGE$1, {
2257
+ filters: toFilterClauses(activeFilters),
2258
+ limit: pageSize,
2259
+ offset: nextOffset,
2260
+ orderBy: toOrderBy(activeSort),
2261
+ search: searchQuery,
2262
+ table
2263
+ }, callOptions(shard_0));
2264
+ if (fetchSeqRef.current !== seq) {
2265
+ return;
2266
+ }
2267
+ setPage(result_0);
2268
+ setOffset(nextOffset);
2269
+ setLoaded({
2270
+ filters: activeFilters,
2271
+ offset: nextOffset,
2272
+ pageSize,
2273
+ search: searchQuery,
2274
+ shard: shard_0,
2275
+ sort: activeSort,
2276
+ table
2277
+ });
2278
+ } catch (error_0) {
2279
+ if (fetchSeqRef.current !== seq) {
2280
+ return;
2281
+ }
2282
+ setPage(null);
2283
+ setPageError(error_0.message);
2284
+ }
2285
+ }, [client, pageSize]);
2286
+ useEffect(() => {
2287
+ fireAndForget(fetchTables(debouncedShard));
2288
+ }, [fetchTables, debouncedShard]);
2289
+ useLiveAdmin(ADMIN_FUNCTIONS.readTablePage, {
2290
+ filters: toFilterClauses(loaded?.filters ?? []),
2291
+ limit: pageSize,
2292
+ offset: loaded?.offset ?? 0,
2293
+ orderBy: toOrderBy(loaded?.sort ?? []),
2294
+ search: loaded?.search ?? "",
2295
+ table: loaded?.table ?? ""
2296
+ }, loaded?.shard ?? "", (result_1) => {
2297
+ setPageError(null);
2298
+ setLiveError(void 0);
2299
+ setPage(result_1);
2300
+ }, loaded !== null, setLiveError);
2301
+ useLiveAdmin(ADMIN_FUNCTIONS.listTables, {}, loaded?.shard ?? "", (result_2) => {
2302
+ setTablesError(null);
2303
+ setLiveError(void 0);
2304
+ setTables(result_2);
2305
+ }, loaded !== null, setLiveError);
2306
+ const appliedTableRef = useRef(null);
2307
+ const selectTable = useCallback((table_0) => {
2308
+ const hydration = hydrationRef.current?.table === void 0 || hydrationRef.current.table === table_0 ? hydrationRef.current : null;
2309
+ hydrationRef.current = null;
2310
+ const nextSorting = fromOrderBy(hydration?.orderBy);
2311
+ const nextFilters = toEditableFilters(hydration?.filters ?? []);
2312
+ const nextSearch = hydration?.search ?? "";
2313
+ setSorting(nextSorting);
2314
+ setFilter(nextSearch);
2315
+ setFilters(nextFilters);
2316
+ filtersRef.current = nextFilters;
2317
+ sortingRef.current = nextSorting;
2318
+ clearFacets();
2319
+ stagedEdits.clear();
2320
+ setEditingCell(null);
2321
+ setSelectedTable(table_0);
2322
+ appliedTableRef.current = table_0;
2323
+ fireAndForget(fetchPage(shardKey, table_0, 0, nextSearch));
2324
+ onSelectTable?.(table_0);
2325
+ }, [clearFacets, fetchPage, onSelectTable, shardKey, stagedEdits]);
2326
+ const navigateToRef = (targetTable, id) => {
2327
+ setSorting([]);
2328
+ setFilters([]);
2329
+ filtersRef.current = [];
2330
+ clearFacets();
2331
+ setSelectedTable(targetTable);
2332
+ appliedTableRef.current = targetTable;
2333
+ setFilter(id);
2334
+ fireAndForget(fetchPage(shardKey, targetTable, 0, id));
2335
+ onSelectTable?.(targetTable);
2336
+ };
2337
+ const previewRef = async (targetTable_0, id_0) => {
2338
+ try {
2339
+ const result_3 = await client.query(READ_TABLE_PAGE$1, {
2340
+ filters: [],
2341
+ limit: PREVIEW_CANDIDATES,
2342
+ offset: 0,
2343
+ search: id_0,
2344
+ table: targetTable_0
2345
+ }, callOptions(shardKey));
2346
+ return result_3.rows.find((row) => rowId(row) === id_0) ?? null;
2347
+ } catch {
2348
+ return null;
2349
+ }
2350
+ };
2351
+ const facetFetcher = useCallback((shard_1, table_1, activeFilters_0, searchQuery_0) => (column) => client.query(FACET_COLUMN, {
2352
+ column,
2353
+ filters: toFilterClauses(activeFilters_0),
2354
+ search: searchQuery_0,
2355
+ table: table_1
2356
+ }, callOptions(shard_1)), [client]);
2357
+ const toggleFacet = (column_0) => {
2358
+ toggleFacetColumn(column_0, selectedTable === null ? null : facetFetcher(shardKey, selectedTable, filtersRef.current, search));
2359
+ };
2360
+ const facetFilter = (column_1, value) => {
2361
+ const text = facetValueText(value);
2362
+ setFilters((current) => [...current.filter((clause) => clause.column !== column_1), {
2363
+ column: column_1,
2364
+ operator: "eq",
2365
+ value: text
2366
+ }]);
2367
+ };
2368
+ useEffect(() => {
2369
+ if (loaded === null) {
2370
+ return;
2371
+ }
2372
+ refetchFacets(facetFetcher(loaded.shard, loaded.table, loaded.filters, loaded.search));
2373
+ }, [loaded, facetFetcher, refetchFacets]);
2374
+ useEffect(() => {
2375
+ if (loaded === null || onViewChange === void 0) {
2376
+ return;
2377
+ }
2378
+ onViewChange({
2379
+ filters: toFilterClauses(loaded.filters),
2380
+ orderBy: toOrderBy(loaded.sort),
2381
+ search: loaded.search,
2382
+ shard: loaded.shard
2383
+ });
2384
+ }, [loaded, onViewChange]);
2385
+ useEffect(() => {
2386
+ if (tableParam === void 0 || tableParam === "" || tableParam === appliedTableRef.current) {
2387
+ return;
2388
+ }
2389
+ appliedTableRef.current = tableParam;
2390
+ const target = tableParam;
2391
+ queueMicrotask(() => {
2392
+ selectTable(target);
2393
+ });
2394
+ }, [tableParam, selectTable]);
2395
+ const goToPage = (nextOffset_0) => {
2396
+ if (selectedTable === null) {
2397
+ return;
2398
+ }
2399
+ fireAndForget(fetchPage(shardKey, selectedTable, Math.max(0, nextOffset_0), search));
2400
+ };
2401
+ const editableColumn = (column_2) => !META_COLUMNS.has(column_2);
2402
+ const startCellEdit = (targetRow, column_3) => {
2403
+ setEditingCell({
2404
+ column: column_3,
2405
+ rowId: targetRow
2406
+ });
2407
+ };
2408
+ const cancelCellEdit = () => {
2409
+ setEditingCell(null);
2410
+ };
2411
+ const commitStaged = async () => {
2412
+ if (selectedTable === null) {
2413
+ return;
2414
+ }
2415
+ setWriteError(null);
2416
+ setCommitting(true);
2417
+ try {
2418
+ for (const [id_1, columns] of Object.entries(stagedEdits.staged)) {
2419
+ await client.query(WRITE_ROW$1, {
2420
+ doc: columns,
2421
+ id: id_1,
2422
+ op: "patch",
2423
+ table: selectedTable
2424
+ }, callOptions(shardKey));
2425
+ }
2426
+ stagedEdits.clear();
2427
+ setEditingCell(null);
2428
+ await fetchPage(shardKey, selectedTable, offset, search);
2429
+ } catch (error_1) {
2430
+ setWriteError(error_1.message);
2431
+ } finally {
2432
+ setCommitting(false);
2433
+ }
2434
+ };
2435
+ const discardStaged = () => {
2436
+ stagedEdits.clear();
2437
+ setEditingCell(null);
2438
+ };
2439
+ const stagedChanges = useMemo(() => {
2440
+ const rowsById = /* @__PURE__ */ new Map();
2441
+ for (const row_0 of page?.rows ?? []) {
2442
+ const id_2 = rowId(row_0);
2443
+ if (id_2 !== null) {
2444
+ rowsById.set(id_2, row_0);
2445
+ }
2446
+ }
2447
+ const changes = [];
2448
+ for (const [id_3, columns_0] of Object.entries(stagedEdits.staged)) {
2449
+ for (const [column_4, newValue] of Object.entries(columns_0)) {
2450
+ changes.push({
2451
+ column: column_4,
2452
+ newValue,
2453
+ oldValue: rowsById.get(id_3)?.[column_4],
2454
+ rowId: id_3
2455
+ });
2456
+ }
2457
+ }
2458
+ return changes;
2459
+ }, [page, stagedEdits.staged]);
2460
+ useEffect(() => {
2461
+ if (selectedTable === null || loaded === null || loaded.search === search) {
2462
+ return;
2463
+ }
2464
+ fireAndForget(fetchPage(shardKey, selectedTable, 0, search));
2465
+ }, [search, selectedTable, shardKey, loaded, fetchPage]);
2466
+ useEffect(() => {
2467
+ if (selectedTable === null || loaded === null || loaded.filters === filters) {
2468
+ return;
2469
+ }
2470
+ fireAndForget(fetchPage(shardKey, selectedTable, 0, search));
2471
+ }, [filters, selectedTable, shardKey, loaded, search, fetchPage]);
2472
+ useEffect(() => {
2473
+ if (selectedTable === null || loaded === null || loaded.sort === sorting) {
2474
+ return;
2475
+ }
2476
+ fireAndForget(fetchPage(shardKey, selectedTable, 0, search));
2477
+ }, [sorting, selectedTable, shardKey, loaded, search, fetchPage]);
2478
+ useEffect(() => {
2479
+ if (selectedTable === null || loaded === null || loaded.pageSize === pageSize) {
2480
+ return;
2481
+ }
2482
+ fireAndForget(fetchPage(shardKey, selectedTable, 0, search));
2483
+ }, [pageSize, selectedTable, shardKey, loaded, search, fetchPage]);
2484
+ const writeRow = async (op, id_4, documentText) => {
2485
+ if (selectedTable === null) {
2486
+ return;
2487
+ }
2488
+ setWriteError(null);
2489
+ let parsedDocument;
2490
+ if (op !== "delete") {
2491
+ try {
2492
+ parsedDocument = documentText === void 0 || documentText.trim() === "" ? {} : JSON.parse(documentText);
2493
+ } catch (error_2) {
2494
+ setWriteError(`Invalid JSON: ${error_2.message}`);
2495
+ return;
2496
+ }
2497
+ }
2498
+ try {
2499
+ await client.query(WRITE_ROW$1, {
2500
+ doc: parsedDocument,
2501
+ id: id_4 ?? void 0,
2502
+ op,
2503
+ table: selectedTable
2504
+ }, callOptions(shardKey));
2505
+ setEditing(null);
2506
+ await fetchPage(shardKey, selectedTable, offset, search);
2507
+ } catch (error_3) {
2508
+ setWriteError(error_3.message);
2509
+ }
2510
+ };
2511
+ const drainBulk = async (ref, args) => {
2512
+ if (selectedTable === null) {
2513
+ return;
2514
+ }
2515
+ setWriteError(null);
2516
+ try {
2517
+ for (let batch = 0; batch < MAX_BULK_DELETE_BATCHES; batch += 1) {
2518
+ const result_4 = await client.query(ref, args, callOptions(shardKey));
2519
+ if (!result_4.hasMore) {
2520
+ break;
2521
+ }
2522
+ }
2523
+ await fetchPage(shardKey, selectedTable, 0, search);
2524
+ } catch (error_4) {
2525
+ setWriteError(error_4.message);
2526
+ }
2527
+ };
2528
+ const table_2 = useDataBrowserTable(page, sorting, setSorting);
2529
+ const currentView = {
2530
+ filters: toFilterClauses(filters),
2531
+ orderBy: toOrderBy(sorting),
2532
+ search,
2533
+ shard: shardKey,
2534
+ table: selectedTable ?? void 0
2535
+ };
2536
+ const total = page?.total ?? 0;
2537
+ const hasPrevious = offset > 0;
2538
+ const hasNext = page !== null && offset + page.rows.length < total;
2539
+ const rangeStart = page === null || page.rows.length === 0 ? 0 : offset + 1;
2540
+ const rangeEnd = page === null ? 0 : offset + page.rows.length;
2541
+ const loadTables = () => {
2542
+ fireAndForget(fetchTables(shardKey));
2543
+ };
2544
+ const showTable = () => {
2545
+ setViewMode("table");
2546
+ };
2547
+ const showJson = () => {
2548
+ setViewMode("json");
2549
+ };
2550
+ const bulkDelete = () => {
2551
+ fireAndForget(drainBulk(DELETE_ROWS, {
2552
+ filters: toFilterClauses(filtersRef.current),
2553
+ search,
2554
+ table: selectedTable
2555
+ }));
2556
+ };
2557
+ const emptyTable = () => {
2558
+ fireAndForget(drainBulk(CLEAR_TABLE, {
2559
+ table: selectedTable
2560
+ }));
2561
+ };
2562
+ const onFilterChange = (event) => {
2563
+ setFilter(event.target.value);
2564
+ };
2565
+ const addRow = () => {
2566
+ setWriteError(null);
2567
+ const seed = {};
2568
+ for (const column_5 of page?.columns ?? []) {
2569
+ if (!META_COLUMNS.has(column_5)) {
2570
+ seed[column_5] = "";
2571
+ }
2572
+ }
2573
+ setEditing({
2574
+ docText: JSON.stringify(seed, null, 2),
2575
+ id: ""
2576
+ });
2577
+ };
2578
+ const setEditorDocumentText = (text_0) => {
2579
+ setEditing((current_0) => current_0 === null ? current_0 : {
2580
+ docText: text_0,
2581
+ id: current_0.id
2582
+ });
2583
+ };
2584
+ const saveEdit = () => {
2585
+ if (editing === null) {
2586
+ return;
2587
+ }
2588
+ fireAndForget(writeRow(editing.id === "" ? "insert" : "patch", editing.id === "" ? null : editing.id, editing.docText));
2589
+ };
2590
+ const cancelEdit = () => {
2591
+ setEditing(null);
2592
+ setWriteError(null);
2593
+ };
2594
+ const goPrevious = () => {
2595
+ goToPage(offset - pageSize);
2596
+ };
2597
+ const goNext = () => {
2598
+ goToPage(offset + pageSize);
2599
+ };
2600
+ const jumpToPage = (targetPage) => {
2601
+ goToPage(Math.max(0, (targetPage - 1) * pageSize));
2602
+ };
2603
+ const changePageSize = (size) => {
2604
+ setPageSize(size);
2605
+ setOffset(0);
2606
+ };
2607
+ const onRowEdit = (id_5, original) => {
2608
+ setWriteError(null);
2609
+ setEditing({
2610
+ docText: JSON.stringify(rowDocument(original), null, 2),
2611
+ id: id_5
2612
+ });
2613
+ };
2614
+ const onRowDelete = (id_6) => {
2615
+ fireAndForget(writeRow("delete", id_6));
2616
+ };
2617
+ const deleteSelected = async (ids) => {
2618
+ if (selectedTable === null || ids.length === 0) {
2619
+ return;
2620
+ }
2621
+ setWriteError(null);
2622
+ try {
2623
+ for (const id_7 of ids) {
2624
+ await client.query(WRITE_ROW$1, {
2625
+ id: id_7,
2626
+ op: "delete",
2627
+ table: selectedTable
2628
+ }, callOptions(shardKey));
2629
+ }
2630
+ await fetchPage(shardKey, selectedTable, offset, search);
2631
+ } catch (error_5) {
2632
+ setWriteError(error_5.message);
2633
+ }
2634
+ };
2635
+ const onBulkDeleteSelected = (ids_0) => {
2636
+ fireAndForget(deleteSelected(ids_0));
2637
+ };
2638
+ const onCommitStaged = () => {
2639
+ fireAndForget(commitStaged());
2640
+ };
2641
+ return {
2642
+ addRow,
2643
+ bulkDelete,
2644
+ cancelCellEdit,
2645
+ cancelEdit,
2646
+ changePageSize,
2647
+ clearTable: emptyTable,
2648
+ columns: page?.columns ?? [],
2649
+ committing,
2650
+ currentView,
2651
+ discardStaged,
2652
+ editableColumn,
2653
+ editing,
2654
+ editingCell,
2655
+ facetFilter,
2656
+ facets,
2657
+ filter,
2658
+ filters,
2659
+ goNext,
2660
+ goPrevious,
2661
+ hasNext,
2662
+ hasPrevious,
2663
+ jumpToPage,
2664
+ liveError,
2665
+ loadTables,
2666
+ navigateToRef,
2667
+ onBulkDeleteSelected,
2668
+ onCommitStaged,
2669
+ onFilterChange,
2670
+ onFiltersChange: setFilters,
2671
+ onRowDelete,
2672
+ onRowEdit,
2673
+ page,
2674
+ previewRef,
2675
+ pageError,
2676
+ pageSize,
2677
+ rangeEnd,
2678
+ rangeStart,
2679
+ saveEdit,
2680
+ selectedTable,
2681
+ selectTable,
2682
+ setEditorDocumentText,
2683
+ setShardKey,
2684
+ shardKey,
2685
+ showJson,
2686
+ showTable,
2687
+ stage: stagedEdits.stage,
2688
+ stagedChanges,
2689
+ stagedValue: stagedEdits.stagedValue,
2690
+ startCellEdit,
2691
+ table: table_2,
2692
+ tables,
2693
+ tablesError,
2694
+ toggleFacet,
2695
+ total,
2696
+ viewMode,
2697
+ writeError
2698
+ };
2699
+ };
2700
+
2701
+ const DESCRIBE_TABLE = adminRef(ADMIN_FUNCTIONS.describeTable);
2702
+ const READ_TABLE_PAGE = adminRef(ADMIN_FUNCTIONS.readTablePage);
2703
+ const WRITE_ROW = adminRef(ADMIN_FUNCTIONS.writeRow);
2704
+ const extractId = (row) => {
2705
+ const raw = row["_id"] ?? row["id"] ?? row["__id__"] ?? "";
2706
+ if (typeof raw === "string") {
2707
+ return raw;
2708
+ }
2709
+ if (typeof raw === "number") {
2710
+ return String(raw);
2711
+ }
2712
+ return "";
2713
+ };
2714
+ const useGenerateRows = (onRefresh) => {
2715
+ const client = useLunora();
2716
+ const [open, setOpen] = useState(false);
2717
+ const [table, setTable] = useState(void 0);
2718
+ const [shardKey, setShardKey] = useState(void 0);
2719
+ const [columnMeta, setColumnMeta] = useState(void 0);
2720
+ const [fkPools, setFkPools] = useState({});
2721
+ const [loading, setLoading] = useState(false);
2722
+ const [error, setError] = useState(void 0);
2723
+ const openDialogAsync = async (targetTable, targetShard) => {
2724
+ setOpen(true);
2725
+ setTable(targetTable);
2726
+ setShardKey(targetShard);
2727
+ setColumnMeta(void 0);
2728
+ setFkPools({});
2729
+ setError(void 0);
2730
+ setLoading(true);
2731
+ try {
2732
+ const result = await client.query(DESCRIBE_TABLE, {
2733
+ table: targetTable
2734
+ }, callOptions(targetShard));
2735
+ const {
2736
+ columns
2737
+ } = result;
2738
+ setColumnMeta(columns);
2739
+ const pools = {};
2740
+ const fkColumns = columns.filter((column) => column.ref !== void 0 && column.type === "id" && column.pk !== true);
2741
+ for (const fkColumn of fkColumns) {
2742
+ if (fkColumn.ref === void 0) {
2743
+ continue;
2744
+ }
2745
+ const {
2746
+ ref
2747
+ } = fkColumn;
2748
+ if (pools[ref] !== void 0) {
2749
+ continue;
2750
+ }
2751
+ try {
2752
+ const page = await client.query(READ_TABLE_PAGE, {
2753
+ filters: [],
2754
+ limit: MAX_FK_SAMPLE,
2755
+ offset: 0,
2756
+ search: "",
2757
+ table: ref
2758
+ }, callOptions(targetShard));
2759
+ pools[ref] = page.rows.map((row) => extractId(row)).filter(Boolean);
2760
+ } catch {
2761
+ pools[ref] = [];
2762
+ }
2763
+ }
2764
+ setFkPools(pools);
2765
+ } catch (error_) {
2766
+ setError(error_.message);
2767
+ } finally {
2768
+ setLoading(false);
2769
+ }
2770
+ };
2771
+ const openDialog = (targetTable_0, targetShard_0) => {
2772
+ fireAndForget(openDialogAsync(targetTable_0, targetShard_0));
2773
+ };
2774
+ const closeDialog = () => {
2775
+ setOpen(false);
2776
+ setTable(void 0);
2777
+ setShardKey(void 0);
2778
+ setColumnMeta(void 0);
2779
+ setFkPools({});
2780
+ setError(void 0);
2781
+ };
2782
+ const insertBatch = async (rows, onDone) => {
2783
+ if (table === void 0 || shardKey === void 0) {
2784
+ return "No table selected.";
2785
+ }
2786
+ try {
2787
+ for (const rowDocument of rows) {
2788
+ await client.query(WRITE_ROW, {
2789
+ doc: rowDocument,
2790
+ op: "insert",
2791
+ table
2792
+ }, callOptions(shardKey));
2793
+ }
2794
+ onDone();
2795
+ onRefresh();
2796
+ return void 0;
2797
+ } catch (error__0) {
2798
+ return error__0.message;
2799
+ }
2800
+ };
2801
+ return {
2802
+ closeDialog,
2803
+ columnMeta,
2804
+ error,
2805
+ fkPools,
2806
+ insertBatch,
2807
+ loading,
2808
+ open,
2809
+ openDialog,
2810
+ shardKey,
2811
+ table
2812
+ };
2813
+ };
2814
+
2815
+ const MASK_POLICIES = adminRef(ADMIN_FUNCTIONS.maskPolicies);
2816
+ const NO_COLUMNS = [];
2817
+ const useMaskPolicies = () => {
2818
+ const client = useLunora();
2819
+ const [columns, setColumns] = useState(NO_COLUMNS);
2820
+ const refresh = async () => {
2821
+ try {
2822
+ const result = await client.query(MASK_POLICIES, {}, callOptions(""));
2823
+ setColumns(Array.isArray(result.columns) ? result.columns : NO_COLUMNS);
2824
+ } catch {
2825
+ setColumns(NO_COLUMNS);
2826
+ }
2827
+ };
2828
+ useEffect(() => {
2829
+ fireAndForget(refresh());
2830
+ }, [refresh]);
2831
+ return columns;
2832
+ };
2833
+
2834
+ const TIMESTAMP_RE$1 = /(?:_creationtime|(?:^|[a-z])(?:time|at))$/iu;
2835
+ const looksLikeTimestamp = (column, value) => typeof value === "number" && TIMESTAMP_RE$1.test(column);
2836
+ const FieldValue = (t0) => {
2837
+ const $ = c(26);
2838
+ const {
2839
+ column,
2840
+ onNavigate,
2841
+ target,
2842
+ value
2843
+ } = t0;
2844
+ let t1;
2845
+ if ($[0] !== onNavigate || $[1] !== target || $[2] !== value) {
2846
+ t1 = () => {
2847
+ if (target !== void 0) {
2848
+ onNavigate(target, String(value));
2849
+ }
2850
+ };
2851
+ $[0] = onNavigate;
2852
+ $[1] = target;
2853
+ $[2] = value;
2854
+ $[3] = t1;
2855
+ } else {
2856
+ t1 = $[3];
2857
+ }
2858
+ const onClick = t1;
2859
+ if (value === null || value === void 0) {
2860
+ let t22;
2861
+ if ($[4] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
2862
+ t22 = /* @__PURE__ */ jsxDEV("span", {
2863
+ className: "italic text-muted-foreground",
2864
+ children: "null"
2865
+ }, void 0, false);
2866
+ $[4] = t22;
2867
+ } else {
2868
+ t22 = $[4];
2869
+ }
2870
+ return t22;
2871
+ }
2872
+ if (target !== void 0 && (typeof value === "string" || typeof value === "number") && String(value) !== "") {
2873
+ const t22 = `rd-ref-${column}`;
2874
+ const t32 = `Open ${target} ${String(value)}`;
2875
+ const t4 = String(value);
2876
+ let t5;
2877
+ if ($[5] !== onClick || $[6] !== t22 || $[7] !== t32 || $[8] !== t4) {
2878
+ t5 = /* @__PURE__ */ jsxDEV("button", {
2879
+ "data-testid": t22,
2880
+ onClick,
2881
+ title: t32,
2882
+ type: "button",
2883
+ children: [t4, " ↗"]
2884
+ }, void 0, true);
2885
+ $[5] = onClick;
2886
+ $[6] = t22;
2887
+ $[7] = t32;
2888
+ $[8] = t4;
2889
+ $[9] = t5;
2890
+ } else {
2891
+ t5 = $[9];
2892
+ }
2893
+ return t5;
2894
+ }
2895
+ if (looksLikeTimestamp(column, value)) {
2896
+ const t22 = `rd-ts-${column}`;
2897
+ let t32;
2898
+ if ($[10] !== value) {
2899
+ t32 = value.toString();
2900
+ $[10] = value;
2901
+ $[11] = t32;
2902
+ } else {
2903
+ t32 = $[11];
2904
+ }
2905
+ let t4;
2906
+ if ($[12] !== value) {
2907
+ t4 = formatTimestamp(value);
2908
+ $[12] = value;
2909
+ $[13] = t4;
2910
+ } else {
2911
+ t4 = $[13];
2912
+ }
2913
+ let t5;
2914
+ if ($[14] !== t22 || $[15] !== t32 || $[16] !== t4) {
2915
+ t5 = /* @__PURE__ */ jsxDEV("span", {
2916
+ "data-testid": t22,
2917
+ title: t32,
2918
+ children: t4
2919
+ }, void 0, false);
2920
+ $[14] = t22;
2921
+ $[15] = t32;
2922
+ $[16] = t4;
2923
+ $[17] = t5;
2924
+ } else {
2925
+ t5 = $[17];
2926
+ }
2927
+ return t5;
2928
+ }
2929
+ if (typeof value === "object") {
2930
+ let t22;
2931
+ if ($[18] !== value) {
2932
+ t22 = JSON.stringify(value, null, 2);
2933
+ $[18] = value;
2934
+ $[19] = t22;
2935
+ } else {
2936
+ t22 = $[19];
2937
+ }
2938
+ let t32;
2939
+ if ($[20] !== t22) {
2940
+ t32 = /* @__PURE__ */ jsxDEV("pre", {
2941
+ className: "m-0 overflow-auto rounded-md bg-muted/50 p-2 text-xs",
2942
+ children: t22
2943
+ }, void 0, false);
2944
+ $[20] = t22;
2945
+ $[21] = t32;
2946
+ } else {
2947
+ t32 = $[21];
2948
+ }
2949
+ return t32;
2950
+ }
2951
+ let t2;
2952
+ if ($[22] !== value) {
2953
+ t2 = formatCell(value);
2954
+ $[22] = value;
2955
+ $[23] = t2;
2956
+ } else {
2957
+ t2 = $[23];
2958
+ }
2959
+ let t3;
2960
+ if ($[24] !== t2) {
2961
+ t3 = /* @__PURE__ */ jsxDEV("span", {
2962
+ children: t2
2963
+ }, void 0, false);
2964
+ $[24] = t2;
2965
+ $[25] = t3;
2966
+ } else {
2967
+ t3 = $[25];
2968
+ }
2969
+ return t3;
2970
+ };
2971
+ const RowDetailDrawer = (t0) => {
2972
+ const $ = c(21);
2973
+ const {
2974
+ columns,
2975
+ onClose,
2976
+ onNavigate,
2977
+ refs,
2978
+ row
2979
+ } = t0;
2980
+ let t1;
2981
+ if ($[0] !== onClose || $[1] !== onNavigate) {
2982
+ t1 = (target, id) => {
2983
+ onNavigate(target, id);
2984
+ onClose();
2985
+ };
2986
+ $[0] = onClose;
2987
+ $[1] = onNavigate;
2988
+ $[2] = t1;
2989
+ } else {
2990
+ t1 = $[2];
2991
+ }
2992
+ const navigateAndClose = t1;
2993
+ let t2;
2994
+ if ($[3] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
2995
+ t2 = /* @__PURE__ */ jsxDEV("h3", {
2996
+ className: "m-0 text-base text-foreground",
2997
+ children: "Row detail"
2998
+ }, void 0, false);
2999
+ $[3] = t2;
3000
+ } else {
3001
+ t2 = $[3];
3002
+ }
3003
+ let t3;
3004
+ if ($[4] !== onClose) {
3005
+ t3 = /* @__PURE__ */ jsxDEV("div", {
3006
+ className: "mb-3 flex items-center justify-between",
3007
+ children: [t2, /* @__PURE__ */ jsxDEV("button", {
3008
+ "data-testid": "rd-close",
3009
+ onClick: onClose,
3010
+ type: "button",
3011
+ children: "Close"
3012
+ }, void 0, false)]
3013
+ }, void 0, true);
3014
+ $[4] = onClose;
3015
+ $[5] = t3;
3016
+ } else {
3017
+ t3 = $[5];
3018
+ }
3019
+ let t4;
3020
+ if ($[6] !== columns || $[7] !== navigateAndClose || $[8] !== refs || $[9] !== row) {
3021
+ let t52;
3022
+ if ($[11] !== navigateAndClose || $[12] !== refs || $[13] !== row) {
3023
+ t52 = (column) => /* @__PURE__ */ jsxDEV("div", {
3024
+ className: "border-t border-border py-2 first:border-t-0",
3025
+ "data-testid": `rd-field-${column}`,
3026
+ children: [/* @__PURE__ */ jsxDEV("dt", {
3027
+ className: "mb-0.5 text-xs font-semibold text-muted-foreground",
3028
+ children: column
3029
+ }, void 0, false), /* @__PURE__ */ jsxDEV("dd", {
3030
+ className: "m-0",
3031
+ children: /* @__PURE__ */ jsxDEV(FieldValue, {
3032
+ column,
3033
+ onNavigate: navigateAndClose,
3034
+ target: refs?.[column],
3035
+ value: row[column]
3036
+ }, void 0, false)
3037
+ }, void 0, false)]
3038
+ }, column, true);
3039
+ $[11] = navigateAndClose;
3040
+ $[12] = refs;
3041
+ $[13] = row;
3042
+ $[14] = t52;
3043
+ } else {
3044
+ t52 = $[14];
3045
+ }
3046
+ t4 = columns.map(t52);
3047
+ $[6] = columns;
3048
+ $[7] = navigateAndClose;
3049
+ $[8] = refs;
3050
+ $[9] = row;
3051
+ $[10] = t4;
3052
+ } else {
3053
+ t4 = $[10];
3054
+ }
3055
+ let t5;
3056
+ if ($[15] !== t4) {
3057
+ t5 = /* @__PURE__ */ jsxDEV("dl", {
3058
+ "data-testid": "rd-fields",
3059
+ children: t4
3060
+ }, void 0, false);
3061
+ $[15] = t4;
3062
+ $[16] = t5;
3063
+ } else {
3064
+ t5 = $[16];
3065
+ }
3066
+ let t6;
3067
+ if ($[17] !== onClose || $[18] !== t3 || $[19] !== t5) {
3068
+ t6 = /* @__PURE__ */ jsxDEV(ModalShell, {
3069
+ label: "Row detail",
3070
+ onClose,
3071
+ panelTestId: "rd-panel",
3072
+ testId: "rd-overlay",
3073
+ variant: "drawer",
3074
+ children: [t3, t5]
3075
+ }, void 0, true);
3076
+ $[17] = onClose;
3077
+ $[18] = t3;
3078
+ $[19] = t5;
3079
+ $[20] = t6;
3080
+ } else {
3081
+ t6 = $[20];
3082
+ }
3083
+ return t6;
3084
+ };
3085
+
3086
+ 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";
3087
+ 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";
3088
+ const TIMESTAMP_RE = /(?:_creationtime|(?:^|[a-z])(?:time|at))$/iu;
3089
+ const inferKind = (column, value) => {
3090
+ if (typeof value === "boolean") {
3091
+ return "boolean";
3092
+ }
3093
+ if (typeof value === "number") {
3094
+ return TIMESTAMP_RE.test(column) ? "date" : "number";
3095
+ }
3096
+ if (value !== null && typeof value === "object") {
3097
+ return "json";
3098
+ }
3099
+ return "text";
3100
+ };
3101
+ const parseDocument = (documentText) => {
3102
+ try {
3103
+ const value = JSON.parse(documentText);
3104
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
3105
+ } catch {
3106
+ return null;
3107
+ }
3108
+ };
3109
+ const toLocalDateTime = (ms) => {
3110
+ const date = new Date(ms);
3111
+ const pad = (n) => String(n).padStart(2, "0");
3112
+ return `${date.getFullYear().toString()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`;
3113
+ };
3114
+ const BooleanField = (t0) => {
3115
+ const $ = c(8);
3116
+ const {
3117
+ column,
3118
+ onChange,
3119
+ value
3120
+ } = t0;
3121
+ let t1;
3122
+ if ($[0] !== column || $[1] !== onChange) {
3123
+ t1 = (checked) => {
3124
+ onChange(column, checked);
3125
+ };
3126
+ $[0] = column;
3127
+ $[1] = onChange;
3128
+ $[2] = t1;
3129
+ } else {
3130
+ t1 = $[2];
3131
+ }
3132
+ const onCheckedChange = t1;
3133
+ const t2 = value === true;
3134
+ const t3 = `db-field-${column}`;
3135
+ let t4;
3136
+ if ($[3] !== column || $[4] !== onCheckedChange || $[5] !== t2 || $[6] !== t3) {
3137
+ t4 = /* @__PURE__ */ jsxDEV(Checkbox, {
3138
+ "aria-label": column,
3139
+ checked: t2,
3140
+ "data-testid": t3,
3141
+ onCheckedChange
3142
+ }, void 0, false);
3143
+ $[3] = column;
3144
+ $[4] = onCheckedChange;
3145
+ $[5] = t2;
3146
+ $[6] = t3;
3147
+ $[7] = t4;
3148
+ } else {
3149
+ t4 = $[7];
3150
+ }
3151
+ return t4;
3152
+ };
3153
+ const NumberField = (t0) => {
3154
+ const $ = c(7);
3155
+ const {
3156
+ column,
3157
+ onChange,
3158
+ value
3159
+ } = t0;
3160
+ let t1;
3161
+ if ($[0] !== column || $[1] !== onChange) {
3162
+ t1 = (event) => {
3163
+ const next = Number(event.target.value);
3164
+ if (event.target.value !== "" && !Number.isNaN(next)) {
3165
+ onChange(column, next);
3166
+ }
3167
+ };
3168
+ $[0] = column;
3169
+ $[1] = onChange;
3170
+ $[2] = t1;
3171
+ } else {
3172
+ t1 = $[2];
3173
+ }
3174
+ const onInput = t1;
3175
+ const t2 = `db-field-${column}`;
3176
+ const t3 = typeof value === "number" ? value : "";
3177
+ let t4;
3178
+ if ($[3] !== onInput || $[4] !== t2 || $[5] !== t3) {
3179
+ t4 = /* @__PURE__ */ jsxDEV("input", {
3180
+ className: FIELD_INPUT,
3181
+ "data-testid": t2,
3182
+ onChange: onInput,
3183
+ type: "number",
3184
+ value: t3
3185
+ }, void 0, false);
3186
+ $[3] = onInput;
3187
+ $[4] = t2;
3188
+ $[5] = t3;
3189
+ $[6] = t4;
3190
+ } else {
3191
+ t4 = $[6];
3192
+ }
3193
+ return t4;
3194
+ };
3195
+ const DateField = (t0) => {
3196
+ const $ = c(9);
3197
+ const {
3198
+ column,
3199
+ onChange,
3200
+ value
3201
+ } = t0;
3202
+ let t1;
3203
+ if ($[0] !== column || $[1] !== onChange) {
3204
+ t1 = (event) => {
3205
+ const ms = new Date(event.target.value).getTime();
3206
+ if (!Number.isNaN(ms)) {
3207
+ onChange(column, ms);
3208
+ }
3209
+ };
3210
+ $[0] = column;
3211
+ $[1] = onChange;
3212
+ $[2] = t1;
3213
+ } else {
3214
+ t1 = $[2];
3215
+ }
3216
+ const onInput = t1;
3217
+ const t2 = `db-field-${column}`;
3218
+ let t3;
3219
+ if ($[3] !== value) {
3220
+ t3 = typeof value === "number" ? toLocalDateTime(value) : "";
3221
+ $[3] = value;
3222
+ $[4] = t3;
3223
+ } else {
3224
+ t3 = $[4];
3225
+ }
3226
+ let t4;
3227
+ if ($[5] !== onInput || $[6] !== t2 || $[7] !== t3) {
3228
+ t4 = /* @__PURE__ */ jsxDEV("input", {
3229
+ className: FIELD_INPUT,
3230
+ "data-testid": t2,
3231
+ onChange: onInput,
3232
+ type: "datetime-local",
3233
+ value: t3
3234
+ }, void 0, false);
3235
+ $[5] = onInput;
3236
+ $[6] = t2;
3237
+ $[7] = t3;
3238
+ $[8] = t4;
3239
+ } else {
3240
+ t4 = $[8];
3241
+ }
3242
+ return t4;
3243
+ };
3244
+ const TextField = (t0) => {
3245
+ const $ = c(7);
3246
+ const {
3247
+ column,
3248
+ onChange,
3249
+ value
3250
+ } = t0;
3251
+ let t1;
3252
+ if ($[0] !== column || $[1] !== onChange) {
3253
+ t1 = (event) => {
3254
+ onChange(column, event.target.value);
3255
+ };
3256
+ $[0] = column;
3257
+ $[1] = onChange;
3258
+ $[2] = t1;
3259
+ } else {
3260
+ t1 = $[2];
3261
+ }
3262
+ const onInput = t1;
3263
+ const t2 = `db-field-${column}`;
3264
+ const t3 = typeof value === "string" ? value : "";
3265
+ let t4;
3266
+ if ($[3] !== onInput || $[4] !== t2 || $[5] !== t3) {
3267
+ t4 = /* @__PURE__ */ jsxDEV("input", {
3268
+ className: FIELD_INPUT,
3269
+ "data-testid": t2,
3270
+ onChange: onInput,
3271
+ type: "text",
3272
+ value: t3
3273
+ }, void 0, false);
3274
+ $[3] = onInput;
3275
+ $[4] = t2;
3276
+ $[5] = t3;
3277
+ $[6] = t4;
3278
+ } else {
3279
+ t4 = $[6];
3280
+ }
3281
+ return t4;
3282
+ };
3283
+ const JsonField = (t0) => {
3284
+ const $ = c(19);
3285
+ const {
3286
+ column,
3287
+ onChange,
3288
+ value
3289
+ } = t0;
3290
+ const t = useT();
3291
+ let t1;
3292
+ if ($[0] !== value) {
3293
+ t1 = () => JSON.stringify(value, null, 2);
3294
+ $[0] = value;
3295
+ $[1] = t1;
3296
+ } else {
3297
+ t1 = $[1];
3298
+ }
3299
+ const [text, setText] = useState(t1);
3300
+ const [error, setError] = useState(false);
3301
+ let t2;
3302
+ if ($[2] !== column || $[3] !== onChange) {
3303
+ t2 = (event) => {
3304
+ const next = event.target.value;
3305
+ setText(next);
3306
+ try {
3307
+ onChange(column, JSON.parse(next));
3308
+ setError(false);
3309
+ } catch {
3310
+ setError(true);
3311
+ }
3312
+ };
3313
+ $[2] = column;
3314
+ $[3] = onChange;
3315
+ $[4] = t2;
3316
+ } else {
3317
+ t2 = $[4];
3318
+ }
3319
+ const onInput = t2;
3320
+ const t3 = error && "border-destructive";
3321
+ let t4;
3322
+ if ($[5] !== t3) {
3323
+ t4 = cn(FIELD_INPUT, "min-h-16", t3);
3324
+ $[5] = t3;
3325
+ $[6] = t4;
3326
+ } else {
3327
+ t4 = $[6];
3328
+ }
3329
+ const t5 = `db-field-${column}`;
3330
+ let t6;
3331
+ if ($[7] !== onInput || $[8] !== t4 || $[9] !== t5 || $[10] !== text) {
3332
+ t6 = /* @__PURE__ */ jsxDEV("textarea", {
3333
+ className: t4,
3334
+ "data-testid": t5,
3335
+ onChange: onInput,
3336
+ value: text
3337
+ }, void 0, false);
3338
+ $[7] = onInput;
3339
+ $[8] = t4;
3340
+ $[9] = t5;
3341
+ $[10] = text;
3342
+ $[11] = t6;
3343
+ } else {
3344
+ t6 = $[11];
3345
+ }
3346
+ let t7;
3347
+ if ($[12] !== column || $[13] !== error || $[14] !== t) {
3348
+ t7 = error && /* @__PURE__ */ jsxDEV("span", {
3349
+ className: "text-xs text-destructive",
3350
+ "data-testid": `db-field-error-${column}`,
3351
+ children: t("Invalid JSON")
3352
+ }, void 0, false);
3353
+ $[12] = column;
3354
+ $[13] = error;
3355
+ $[14] = t;
3356
+ $[15] = t7;
3357
+ } else {
3358
+ t7 = $[15];
3359
+ }
3360
+ let t8;
3361
+ if ($[16] !== t6 || $[17] !== t7) {
3362
+ t8 = /* @__PURE__ */ jsxDEV("div", {
3363
+ className: "flex flex-col gap-1",
3364
+ children: [t6, t7]
3365
+ }, void 0, true);
3366
+ $[16] = t6;
3367
+ $[17] = t7;
3368
+ $[18] = t8;
3369
+ } else {
3370
+ t8 = $[18];
3371
+ }
3372
+ return t8;
3373
+ };
3374
+ const FieldRow = (t0) => {
3375
+ const $ = c(43);
3376
+ const {
3377
+ column,
3378
+ onChange,
3379
+ target,
3380
+ value
3381
+ } = t0;
3382
+ let t1;
3383
+ if ($[0] !== column || $[1] !== value) {
3384
+ t1 = inferKind(column, value);
3385
+ $[0] = column;
3386
+ $[1] = value;
3387
+ $[2] = t1;
3388
+ } else {
3389
+ t1 = $[2];
3390
+ }
3391
+ const kind = t1;
3392
+ const t2 = `db-field-${column}`;
3393
+ let t3;
3394
+ if ($[3] !== column) {
3395
+ t3 = /* @__PURE__ */ jsxDEV("span", {
3396
+ className: "font-mono",
3397
+ children: column
3398
+ }, void 0, false);
3399
+ $[3] = column;
3400
+ $[4] = t3;
3401
+ } else {
3402
+ t3 = $[4];
3403
+ }
3404
+ let t4;
3405
+ if ($[5] !== target) {
3406
+ t4 = target !== void 0 && /* @__PURE__ */ jsxDEV("span", {
3407
+ className: "rounded bg-muted px-1 font-mono text-[10px] tracking-wide uppercase",
3408
+ children: ["→ ", target]
3409
+ }, void 0, true);
3410
+ $[5] = target;
3411
+ $[6] = t4;
3412
+ } else {
3413
+ t4 = $[6];
3414
+ }
3415
+ let t5;
3416
+ if ($[7] !== t3 || $[8] !== t4) {
3417
+ t5 = /* @__PURE__ */ jsxDEV("span", {
3418
+ className: "flex items-center gap-1.5 font-medium text-muted-foreground",
3419
+ children: [t3, t4]
3420
+ }, void 0, true);
3421
+ $[7] = t3;
3422
+ $[8] = t4;
3423
+ $[9] = t5;
3424
+ } else {
3425
+ t5 = $[9];
3426
+ }
3427
+ let t6;
3428
+ if ($[10] !== column || $[11] !== kind || $[12] !== onChange || $[13] !== value) {
3429
+ t6 = kind === "boolean" && /* @__PURE__ */ jsxDEV(BooleanField, {
3430
+ column,
3431
+ onChange,
3432
+ value
3433
+ }, void 0, false);
3434
+ $[10] = column;
3435
+ $[11] = kind;
3436
+ $[12] = onChange;
3437
+ $[13] = value;
3438
+ $[14] = t6;
3439
+ } else {
3440
+ t6 = $[14];
3441
+ }
3442
+ let t7;
3443
+ if ($[15] !== column || $[16] !== kind || $[17] !== onChange || $[18] !== value) {
3444
+ t7 = kind === "number" && /* @__PURE__ */ jsxDEV(NumberField, {
3445
+ column,
3446
+ onChange,
3447
+ value
3448
+ }, void 0, false);
3449
+ $[15] = column;
3450
+ $[16] = kind;
3451
+ $[17] = onChange;
3452
+ $[18] = value;
3453
+ $[19] = t7;
3454
+ } else {
3455
+ t7 = $[19];
3456
+ }
3457
+ let t8;
3458
+ if ($[20] !== column || $[21] !== kind || $[22] !== onChange || $[23] !== value) {
3459
+ t8 = kind === "date" && /* @__PURE__ */ jsxDEV(DateField, {
3460
+ column,
3461
+ onChange,
3462
+ value
3463
+ }, void 0, false);
3464
+ $[20] = column;
3465
+ $[21] = kind;
3466
+ $[22] = onChange;
3467
+ $[23] = value;
3468
+ $[24] = t8;
3469
+ } else {
3470
+ t8 = $[24];
3471
+ }
3472
+ let t9;
3473
+ if ($[25] !== column || $[26] !== kind || $[27] !== onChange || $[28] !== value) {
3474
+ t9 = kind === "json" && /* @__PURE__ */ jsxDEV(JsonField, {
3475
+ column,
3476
+ onChange,
3477
+ value
3478
+ }, void 0, false);
3479
+ $[25] = column;
3480
+ $[26] = kind;
3481
+ $[27] = onChange;
3482
+ $[28] = value;
3483
+ $[29] = t9;
3484
+ } else {
3485
+ t9 = $[29];
3486
+ }
3487
+ let t10;
3488
+ if ($[30] !== column || $[31] !== kind || $[32] !== onChange || $[33] !== value) {
3489
+ t10 = kind === "text" && /* @__PURE__ */ jsxDEV(TextField, {
3490
+ column,
3491
+ onChange,
3492
+ value
3493
+ }, void 0, false);
3494
+ $[30] = column;
3495
+ $[31] = kind;
3496
+ $[32] = onChange;
3497
+ $[33] = value;
3498
+ $[34] = t10;
3499
+ } else {
3500
+ t10 = $[34];
3501
+ }
3502
+ let t11;
3503
+ if ($[35] !== t10 || $[36] !== t2 || $[37] !== t5 || $[38] !== t6 || $[39] !== t7 || $[40] !== t8 || $[41] !== t9) {
3504
+ t11 = /* @__PURE__ */ jsxDEV("label", {
3505
+ className: "flex flex-col gap-1 text-xs",
3506
+ htmlFor: t2,
3507
+ children: [t5, t6, t7, t8, t9, t10]
3508
+ }, void 0, true);
3509
+ $[35] = t10;
3510
+ $[36] = t2;
3511
+ $[37] = t5;
3512
+ $[38] = t6;
3513
+ $[39] = t7;
3514
+ $[40] = t8;
3515
+ $[41] = t9;
3516
+ $[42] = t11;
3517
+ } else {
3518
+ t11 = $[42];
3519
+ }
3520
+ return t11;
3521
+ };
3522
+ const RowFormEditor = (t0) => {
3523
+ const $ = c(48);
3524
+ const {
3525
+ documentText,
3526
+ onCancel,
3527
+ onDocumentTextChange,
3528
+ onSave,
3529
+ refs
3530
+ } = t0;
3531
+ const t = useT();
3532
+ let t1;
3533
+ if ($[0] !== documentText) {
3534
+ t1 = parseDocument(documentText);
3535
+ $[0] = documentText;
3536
+ $[1] = t1;
3537
+ } else {
3538
+ t1 = $[1];
3539
+ }
3540
+ const fields = t1;
3541
+ const [rawMode, setRawMode] = useState(false);
3542
+ const showForm = !rawMode && fields !== null;
3543
+ let t2;
3544
+ if ($[2] !== fields || $[3] !== onDocumentTextChange) {
3545
+ t2 = (column, value) => {
3546
+ onDocumentTextChange(JSON.stringify({
3547
+ ...fields,
3548
+ [column]: value
3549
+ }, null, 2));
3550
+ };
3551
+ $[2] = fields;
3552
+ $[3] = onDocumentTextChange;
3553
+ $[4] = t2;
3554
+ } else {
3555
+ t2 = $[4];
3556
+ }
3557
+ const onField = t2;
3558
+ let t3;
3559
+ if ($[5] !== onDocumentTextChange) {
3560
+ t3 = (event) => {
3561
+ onDocumentTextChange(event.target.value);
3562
+ };
3563
+ $[5] = onDocumentTextChange;
3564
+ $[6] = t3;
3565
+ } else {
3566
+ t3 = $[6];
3567
+ }
3568
+ const onTextarea = t3;
3569
+ let t4;
3570
+ if ($[7] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
3571
+ t4 = () => {
3572
+ setRawMode(false);
3573
+ };
3574
+ $[7] = t4;
3575
+ } else {
3576
+ t4 = $[7];
3577
+ }
3578
+ const showFormMode = t4;
3579
+ let t5;
3580
+ if ($[8] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
3581
+ t5 = () => {
3582
+ setRawMode(true);
3583
+ };
3584
+ $[8] = t5;
3585
+ } else {
3586
+ t5 = $[8];
3587
+ }
3588
+ const showJsonMode = t5;
3589
+ const t6 = fields === null;
3590
+ let t7;
3591
+ if ($[9] !== t) {
3592
+ t7 = t("Form");
3593
+ $[9] = t;
3594
+ $[10] = t7;
3595
+ } else {
3596
+ t7 = $[10];
3597
+ }
3598
+ let t8;
3599
+ if ($[11] !== showForm || $[12] !== t6 || $[13] !== t7) {
3600
+ t8 = /* @__PURE__ */ jsxDEV("button", {
3601
+ "aria-pressed": showForm,
3602
+ className: CONTROL_BTN$1,
3603
+ "data-testid": "db-editor-form",
3604
+ disabled: t6,
3605
+ onClick: showFormMode,
3606
+ type: "button",
3607
+ children: t7
3608
+ }, void 0, false);
3609
+ $[11] = showForm;
3610
+ $[12] = t6;
3611
+ $[13] = t7;
3612
+ $[14] = t8;
3613
+ } else {
3614
+ t8 = $[14];
3615
+ }
3616
+ const t9 = !showForm;
3617
+ let t10;
3618
+ if ($[15] !== t) {
3619
+ t10 = t("JSON");
3620
+ $[15] = t;
3621
+ $[16] = t10;
3622
+ } else {
3623
+ t10 = $[16];
3624
+ }
3625
+ let t11;
3626
+ if ($[17] !== t10 || $[18] !== t9) {
3627
+ t11 = /* @__PURE__ */ jsxDEV("button", {
3628
+ "aria-pressed": t9,
3629
+ className: CONTROL_BTN$1,
3630
+ "data-testid": "db-editor-json",
3631
+ onClick: showJsonMode,
3632
+ type: "button",
3633
+ children: t10
3634
+ }, void 0, false);
3635
+ $[17] = t10;
3636
+ $[18] = t9;
3637
+ $[19] = t11;
3638
+ } else {
3639
+ t11 = $[19];
3640
+ }
3641
+ let t12;
3642
+ if ($[20] !== t11 || $[21] !== t8) {
3643
+ t12 = /* @__PURE__ */ jsxDEV("div", {
3644
+ className: "flex items-center gap-1.5",
3645
+ children: [t8, t11]
3646
+ }, void 0, true);
3647
+ $[20] = t11;
3648
+ $[21] = t8;
3649
+ $[22] = t12;
3650
+ } else {
3651
+ t12 = $[22];
3652
+ }
3653
+ let t13;
3654
+ if ($[23] !== documentText || $[24] !== fields || $[25] !== onField || $[26] !== onTextarea || $[27] !== refs || $[28] !== showForm || $[29] !== t) {
3655
+ t13 = showForm ? /* @__PURE__ */ jsxDEV("div", {
3656
+ className: "flex flex-col gap-3",
3657
+ "data-testid": "db-editor-fields",
3658
+ children: Object.entries(fields).map((t142) => {
3659
+ const [column_0, value_0] = t142;
3660
+ return /* @__PURE__ */ jsxDEV(FieldRow, {
3661
+ column: column_0,
3662
+ onChange: onField,
3663
+ target: refs?.[column_0],
3664
+ value: value_0
3665
+ }, column_0, false);
3666
+ })
3667
+ }, void 0, false) : /* @__PURE__ */ jsxDEV("textarea", {
3668
+ "aria-label": t("Row document JSON"),
3669
+ 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",
3670
+ "data-testid": "db-editor-doc",
3671
+ onChange: onTextarea,
3672
+ value: documentText
3673
+ }, void 0, false);
3674
+ $[23] = documentText;
3675
+ $[24] = fields;
3676
+ $[25] = onField;
3677
+ $[26] = onTextarea;
3678
+ $[27] = refs;
3679
+ $[28] = showForm;
3680
+ $[29] = t;
3681
+ $[30] = t13;
3682
+ } else {
3683
+ t13 = $[30];
3684
+ }
3685
+ let t14;
3686
+ if ($[31] !== t) {
3687
+ t14 = t("Save");
3688
+ $[31] = t;
3689
+ $[32] = t14;
3690
+ } else {
3691
+ t14 = $[32];
3692
+ }
3693
+ let t15;
3694
+ if ($[33] !== onSave || $[34] !== t14) {
3695
+ t15 = /* @__PURE__ */ jsxDEV("button", {
3696
+ className: CONTROL_BTN$1,
3697
+ "data-testid": "db-editor-save",
3698
+ onClick: onSave,
3699
+ type: "button",
3700
+ children: t14
3701
+ }, void 0, false);
3702
+ $[33] = onSave;
3703
+ $[34] = t14;
3704
+ $[35] = t15;
3705
+ } else {
3706
+ t15 = $[35];
3707
+ }
3708
+ let t16;
3709
+ if ($[36] !== t) {
3710
+ t16 = t("Cancel");
3711
+ $[36] = t;
3712
+ $[37] = t16;
3713
+ } else {
3714
+ t16 = $[37];
3715
+ }
3716
+ let t17;
3717
+ if ($[38] !== onCancel || $[39] !== t16) {
3718
+ t17 = /* @__PURE__ */ jsxDEV("button", {
3719
+ className: CONTROL_BTN$1,
3720
+ "data-testid": "db-editor-cancel",
3721
+ onClick: onCancel,
3722
+ type: "button",
3723
+ children: t16
3724
+ }, void 0, false);
3725
+ $[38] = onCancel;
3726
+ $[39] = t16;
3727
+ $[40] = t17;
3728
+ } else {
3729
+ t17 = $[40];
3730
+ }
3731
+ let t18;
3732
+ if ($[41] !== t15 || $[42] !== t17) {
3733
+ t18 = /* @__PURE__ */ jsxDEV("div", {
3734
+ className: "flex items-center gap-1.5",
3735
+ children: [t15, t17]
3736
+ }, void 0, true);
3737
+ $[41] = t15;
3738
+ $[42] = t17;
3739
+ $[43] = t18;
3740
+ } else {
3741
+ t18 = $[43];
3742
+ }
3743
+ let t19;
3744
+ if ($[44] !== t12 || $[45] !== t13 || $[46] !== t18) {
3745
+ t19 = /* @__PURE__ */ jsxDEV("div", {
3746
+ className: "flex flex-col gap-2 border border-border bg-card p-3",
3747
+ "data-testid": "db-editor",
3748
+ children: [t12, t13, t18]
3749
+ }, void 0, true);
3750
+ $[44] = t12;
3751
+ $[45] = t13;
3752
+ $[46] = t18;
3753
+ $[47] = t19;
3754
+ } else {
3755
+ t19 = $[47];
3756
+ }
3757
+ return t19;
3758
+ };
3759
+
3760
+ const MAX_SUMMARY_TABLES = 50;
3761
+ const ShardButton = (t0) => {
3762
+ const $ = c(8);
3763
+ const {
3764
+ active,
3765
+ onPick,
3766
+ shard
3767
+ } = t0;
3768
+ let t1;
3769
+ if ($[0] !== onPick || $[1] !== shard) {
3770
+ t1 = () => {
3771
+ onPick(shard);
3772
+ };
3773
+ $[0] = onPick;
3774
+ $[1] = shard;
3775
+ $[2] = t1;
3776
+ } else {
3777
+ t1 = $[2];
3778
+ }
3779
+ const handleClick = t1;
3780
+ const t2 = `w-full rounded px-2 py-0.5 text-left text-xs transition-colors hover:bg-accent ${active ? "bg-accent font-medium" : ""}`;
3781
+ const t3 = `shard-explorer-item-${shard}`;
3782
+ let t4;
3783
+ if ($[3] !== handleClick || $[4] !== shard || $[5] !== t2 || $[6] !== t3) {
3784
+ t4 = /* @__PURE__ */ jsxDEV("button", {
3785
+ className: t2,
3786
+ "data-testid": t3,
3787
+ onClick: handleClick,
3788
+ type: "button",
3789
+ children: shard
3790
+ }, void 0, false);
3791
+ $[3] = handleClick;
3792
+ $[4] = shard;
3793
+ $[5] = t2;
3794
+ $[6] = t3;
3795
+ $[7] = t4;
3796
+ } else {
3797
+ t4 = $[7];
3798
+ }
3799
+ return t4;
3800
+ };
3801
+ const ShardExplorer = ({
3802
+ onFetchTables,
3803
+ onSelect
3804
+ }) => {
3805
+ const t = useT();
3806
+ const [recents] = useState(() => loadRecentShards());
3807
+ const [open, setOpen] = useState(false);
3808
+ const [activeShard, setActiveShard] = useState(void 0);
3809
+ const [tables, setTables] = useState(void 0);
3810
+ const [loading, setLoading] = useState(false);
3811
+ const [error, setError] = useState(void 0);
3812
+ const requestIdRef = useRef(0);
3813
+ const toggleOpen = () => {
3814
+ setOpen((current) => !current);
3815
+ };
3816
+ const pickShardAsync = async (shardKey) => {
3817
+ onSelect(shardKey);
3818
+ setActiveShard(shardKey);
3819
+ setTables(void 0);
3820
+ setError(void 0);
3821
+ setLoading(true);
3822
+ requestIdRef.current += 1;
3823
+ const myRequestId = requestIdRef.current;
3824
+ try {
3825
+ const result = await onFetchTables(shardKey);
3826
+ if (requestIdRef.current === myRequestId) {
3827
+ setTables(result?.slice(0, MAX_SUMMARY_TABLES));
3828
+ }
3829
+ } catch (error_) {
3830
+ if (requestIdRef.current === myRequestId) {
3831
+ setError(error_.message);
3832
+ }
3833
+ } finally {
3834
+ if (requestIdRef.current === myRequestId) {
3835
+ setLoading(false);
3836
+ }
3837
+ }
3838
+ };
3839
+ const pickShard = (shardKey_0) => {
3840
+ fireAndForget(pickShardAsync(shardKey_0));
3841
+ };
3842
+ if (recents.length === 0) {
3843
+ return null;
3844
+ }
3845
+ return /* @__PURE__ */ jsxDEV("div", {
3846
+ "data-testid": "shard-explorer",
3847
+ children: [/* @__PURE__ */ jsxDEV("button", {
3848
+ "aria-controls": "shard-explorer-panel",
3849
+ "aria-expanded": open,
3850
+ 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",
3851
+ "data-testid": "shard-explorer-toggle",
3852
+ onClick: toggleOpen,
3853
+ type: "button",
3854
+ children: [t("Shards seen"), /* @__PURE__ */ jsxDEV("span", {
3855
+ "aria-hidden": "true",
3856
+ className: `ml-0.5 transition-transform ${open ? "rotate-180" : ""}`,
3857
+ children: "▾"
3858
+ }, void 0, false)]
3859
+ }, void 0, true), open && /* @__PURE__ */ jsxDEV("div", {
3860
+ className: "mt-1 flex flex-col gap-1 rounded-md border border-border bg-popover p-2",
3861
+ "data-testid": "shard-explorer-panel",
3862
+ id: "shard-explorer-panel",
3863
+ children: [/* @__PURE__ */ jsxDEV("p", {
3864
+ className: "text-xs text-muted-foreground",
3865
+ "data-testid": "shard-explorer-hint",
3866
+ children: t("Recently visited shards — click to switch")
3867
+ }, void 0, false), /* @__PURE__ */ jsxDEV("ul", {
3868
+ className: "flex flex-col gap-0.5",
3869
+ "data-testid": "shard-explorer-list",
3870
+ children: recents.map((shard) => /* @__PURE__ */ jsxDEV("li", {
3871
+ children: /* @__PURE__ */ jsxDEV(ShardButton, {
3872
+ active: activeShard === shard,
3873
+ onPick: pickShard,
3874
+ shard
3875
+ }, void 0, false)
3876
+ }, shard, false))
3877
+ }, void 0, false), activeShard !== void 0 && /* @__PURE__ */ jsxDEV("div", {
3878
+ className: "mt-1 border-t border-border pt-1",
3879
+ "data-testid": "shard-explorer-summary",
3880
+ children: [/* @__PURE__ */ jsxDEV("p", {
3881
+ className: "mb-1 text-xs font-medium text-foreground",
3882
+ "data-testid": "shard-explorer-summary-title",
3883
+ children: t("{shard} tables", {
3884
+ shard: activeShard
3885
+ })
3886
+ }, void 0, false), loading && /* @__PURE__ */ jsxDEV("p", {
3887
+ className: "text-xs text-muted-foreground",
3888
+ "data-testid": "shard-explorer-loading",
3889
+ children: t("Loading…")
3890
+ }, void 0, false), error !== void 0 && /* @__PURE__ */ jsxDEV("p", {
3891
+ className: "text-xs text-destructive",
3892
+ "data-testid": "shard-explorer-error",
3893
+ role: "alert",
3894
+ children: error
3895
+ }, void 0, false), !loading && error === void 0 && tables?.length === 0 && /* @__PURE__ */ jsxDEV("p", {
3896
+ className: "text-xs text-muted-foreground",
3897
+ "data-testid": "shard-explorer-empty",
3898
+ children: t("No tables in this shard.")
3899
+ }, void 0, false), !loading && error === void 0 && tables !== void 0 && tables.length > 0 && /* @__PURE__ */ jsxDEV("ul", {
3900
+ className: "flex flex-col gap-0.5",
3901
+ "data-testid": "shard-explorer-tables",
3902
+ children: tables.map((tableInfo) => /* @__PURE__ */ jsxDEV("li", {
3903
+ className: "flex items-center justify-between text-xs",
3904
+ children: [/* @__PURE__ */ jsxDEV("span", {
3905
+ "data-testid": `shard-explorer-table-${tableInfo.name}`,
3906
+ children: tableInfo.name
3907
+ }, void 0, false), /* @__PURE__ */ jsxDEV("span", {
3908
+ className: "text-muted-foreground",
3909
+ "data-testid": `shard-explorer-rowcount-${tableInfo.name}`,
3910
+ children: tableInfo.rowCount
3911
+ }, void 0, false)]
3912
+ }, tableInfo.name, true))
3913
+ }, void 0, false)]
3914
+ }, void 0, true)]
3915
+ }, void 0, true)]
3916
+ }, void 0, true);
3917
+ };
3918
+
3919
+ const DEFAULT_PAGE_SIZE = 50;
3920
+ const NO_TABLES = [];
3921
+ 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";
3922
+ const LIST_TABLES = adminRef(ADMIN_FUNCTIONS.listTables);
3923
+ const DataBrowserSidebarHeader = (t0) => {
3924
+ const $ = c(10);
3925
+ const {
3926
+ onFetchShardTables,
3927
+ onShardChange,
3928
+ schemaSwitch,
3929
+ shardKey
3930
+ } = t0;
3931
+ let t1;
3932
+ if ($[0] !== onShardChange || $[1] !== shardKey) {
3933
+ t1 = /* @__PURE__ */ jsxDEV(ShardInput, {
3934
+ onChange: onShardChange,
3935
+ testId: "db-shard-input",
3936
+ value: shardKey
3937
+ }, void 0, false);
3938
+ $[0] = onShardChange;
3939
+ $[1] = shardKey;
3940
+ $[2] = t1;
3941
+ } else {
3942
+ t1 = $[2];
3943
+ }
3944
+ let t2;
3945
+ if ($[3] !== onFetchShardTables || $[4] !== onShardChange) {
3946
+ t2 = /* @__PURE__ */ jsxDEV(ShardExplorer, {
3947
+ onFetchTables: onFetchShardTables,
3948
+ onSelect: onShardChange
3949
+ }, void 0, false);
3950
+ $[3] = onFetchShardTables;
3951
+ $[4] = onShardChange;
3952
+ $[5] = t2;
3953
+ } else {
3954
+ t2 = $[5];
3955
+ }
3956
+ let t3;
3957
+ if ($[6] !== schemaSwitch || $[7] !== t1 || $[8] !== t2) {
3958
+ t3 = /* @__PURE__ */ jsxDEV("div", {
3959
+ className: "flex shrink-0 flex-col items-stretch gap-2 border-b border-border p-3",
3960
+ children: [schemaSwitch, t1, t2]
3961
+ }, void 0, true);
3962
+ $[6] = schemaSwitch;
3963
+ $[7] = t1;
3964
+ $[8] = t2;
3965
+ $[9] = t3;
3966
+ } else {
3967
+ t3 = $[9];
3968
+ }
3969
+ return t3;
3970
+ };
3971
+ const DataBrowserViewControls = (t0) => {
3972
+ const $ = c(60);
3973
+ const {
3974
+ columns,
3975
+ editable,
3976
+ filter,
3977
+ filters,
3978
+ hasMaskedColumns,
3979
+ liveError,
3980
+ maskOn,
3981
+ onAddRow,
3982
+ onBulkDelete,
3983
+ onClearTable,
3984
+ onFilterChange,
3985
+ onFiltersChange,
3986
+ onGenerateRows,
3987
+ onShowJson,
3988
+ onShowTable,
3989
+ onToggleMask,
3990
+ total,
3991
+ viewMode
3992
+ } = t0;
3993
+ const t = useT();
3994
+ const t1 = viewMode === "table";
3995
+ let t2;
3996
+ if ($[0] !== onShowTable || $[1] !== t1) {
3997
+ t2 = /* @__PURE__ */ jsxDEV("button", {
3998
+ "aria-pressed": t1,
3999
+ className: CONTROL_BTN,
4000
+ "data-testid": "db-view-table",
4001
+ onClick: onShowTable,
4002
+ type: "button",
4003
+ children: "Table"
4004
+ }, void 0, false);
4005
+ $[0] = onShowTable;
4006
+ $[1] = t1;
4007
+ $[2] = t2;
4008
+ } else {
4009
+ t2 = $[2];
4010
+ }
4011
+ const t3 = viewMode === "json";
4012
+ let t4;
4013
+ if ($[3] !== onShowJson || $[4] !== t3) {
4014
+ t4 = /* @__PURE__ */ jsxDEV("button", {
4015
+ "aria-pressed": t3,
4016
+ className: CONTROL_BTN,
4017
+ "data-testid": "db-view-json",
4018
+ onClick: onShowJson,
4019
+ type: "button",
4020
+ children: "JSON"
4021
+ }, void 0, false);
4022
+ $[3] = onShowJson;
4023
+ $[4] = t3;
4024
+ $[5] = t4;
4025
+ } else {
4026
+ t4 = $[5];
4027
+ }
4028
+ let t5;
4029
+ if ($[6] !== liveError || $[7] !== t) {
4030
+ t5 = liveError === void 0 ? t("Live — changes stream in automatically") : t("Live unavailable: {liveError}", {
4031
+ liveError
4032
+ });
4033
+ $[6] = liveError;
4034
+ $[7] = t;
4035
+ $[8] = t5;
4036
+ } else {
4037
+ t5 = $[8];
4038
+ }
4039
+ const t6 = `size-1.5 rounded-full ${liveError === void 0 ? "bg-success" : "bg-muted-foreground/50"}`;
4040
+ let t7;
4041
+ if ($[9] !== t6) {
4042
+ t7 = /* @__PURE__ */ jsxDEV("span", {
4043
+ "aria-hidden": "true",
4044
+ className: t6
4045
+ }, void 0, false);
4046
+ $[9] = t6;
4047
+ $[10] = t7;
4048
+ } else {
4049
+ t7 = $[10];
4050
+ }
4051
+ let t8;
4052
+ if ($[11] !== liveError || $[12] !== t) {
4053
+ t8 = liveError === void 0 ? t("Live") : t("Live unavailable");
4054
+ $[11] = liveError;
4055
+ $[12] = t;
4056
+ $[13] = t8;
4057
+ } else {
4058
+ t8 = $[13];
4059
+ }
4060
+ let t9;
4061
+ if ($[14] !== t5 || $[15] !== t7 || $[16] !== t8) {
4062
+ t9 = /* @__PURE__ */ jsxDEV("span", {
4063
+ className: "inline-flex items-center gap-1.5 px-1 text-xs font-medium text-muted-foreground",
4064
+ "data-testid": "db-live-indicator",
4065
+ role: "status",
4066
+ title: t5,
4067
+ children: [t7, t8]
4068
+ }, void 0, true);
4069
+ $[14] = t5;
4070
+ $[15] = t7;
4071
+ $[16] = t8;
4072
+ $[17] = t9;
4073
+ } else {
4074
+ t9 = $[17];
4075
+ }
4076
+ let t10;
4077
+ if ($[18] !== hasMaskedColumns || $[19] !== maskOn || $[20] !== onToggleMask || $[21] !== t) {
4078
+ t10 = hasMaskedColumns && /* @__PURE__ */ jsxDEV("button", {
4079
+ "aria-pressed": maskOn,
4080
+ className: CONTROL_BTN,
4081
+ "data-testid": "db-mask-toggle",
4082
+ onClick: onToggleMask,
4083
+ type: "button",
4084
+ children: t("Mask sensitive columns")
4085
+ }, void 0, false);
4086
+ $[18] = hasMaskedColumns;
4087
+ $[19] = maskOn;
4088
+ $[20] = onToggleMask;
4089
+ $[21] = t;
4090
+ $[22] = t10;
4091
+ } else {
4092
+ t10 = $[22];
4093
+ }
4094
+ let t11;
4095
+ if ($[23] !== editable || $[24] !== onAddRow) {
4096
+ t11 = editable && /* @__PURE__ */ jsxDEV("button", {
4097
+ className: CONTROL_BTN,
4098
+ "data-testid": "db-add-row",
4099
+ onClick: onAddRow,
4100
+ type: "button",
4101
+ children: "Add row"
4102
+ }, void 0, false);
4103
+ $[23] = editable;
4104
+ $[24] = onAddRow;
4105
+ $[25] = t11;
4106
+ } else {
4107
+ t11 = $[25];
4108
+ }
4109
+ let t12;
4110
+ if ($[26] !== editable || $[27] !== onGenerateRows || $[28] !== t) {
4111
+ t12 = editable && /* @__PURE__ */ jsxDEV("button", {
4112
+ className: CONTROL_BTN,
4113
+ "data-testid": "db-generate-rows",
4114
+ onClick: onGenerateRows,
4115
+ type: "button",
4116
+ children: t("Generate rows")
4117
+ }, void 0, false);
4118
+ $[26] = editable;
4119
+ $[27] = onGenerateRows;
4120
+ $[28] = t;
4121
+ $[29] = t12;
4122
+ } else {
4123
+ t12 = $[29];
4124
+ }
4125
+ let t13;
4126
+ if ($[30] !== editable || $[31] !== filter || $[32] !== filters || $[33] !== onBulkDelete || $[34] !== total) {
4127
+ t13 = editable && total > 0 && (filter !== "" || filters.length > 0) && /* @__PURE__ */ jsxDEV(ConfirmButton, {
4128
+ confirmLabel: `Delete ${total.toString()} matching?`,
4129
+ onConfirm: onBulkDelete,
4130
+ testId: "db-bulk-delete",
4131
+ children: `Delete ${total.toString()} matching`
4132
+ }, void 0, false);
4133
+ $[30] = editable;
4134
+ $[31] = filter;
4135
+ $[32] = filters;
4136
+ $[33] = onBulkDelete;
4137
+ $[34] = total;
4138
+ $[35] = t13;
4139
+ } else {
4140
+ t13 = $[35];
4141
+ }
4142
+ let t14;
4143
+ if ($[36] !== editable || $[37] !== filter || $[38] !== filters || $[39] !== onClearTable || $[40] !== total) {
4144
+ t14 = editable && total > 0 && filter === "" && filters.length === 0 && /* @__PURE__ */ jsxDEV(ConfirmButton, {
4145
+ confirmLabel: `Clear all ${total.toString()} rows?`,
4146
+ onConfirm: onClearTable,
4147
+ testId: "db-clear-table",
4148
+ children: `Clear table (${total.toString()})`
4149
+ }, void 0, false);
4150
+ $[36] = editable;
4151
+ $[37] = filter;
4152
+ $[38] = filters;
4153
+ $[39] = onClearTable;
4154
+ $[40] = total;
4155
+ $[41] = t14;
4156
+ } else {
4157
+ t14 = $[41];
4158
+ }
4159
+ let t15;
4160
+ if ($[42] !== t10 || $[43] !== t11 || $[44] !== t12 || $[45] !== t13 || $[46] !== t14 || $[47] !== t2 || $[48] !== t4 || $[49] !== t9) {
4161
+ t15 = /* @__PURE__ */ jsxDEV("div", {
4162
+ className: "flex flex-wrap items-center gap-1.5",
4163
+ children: [t2, t4, t9, t10, t11, t12, t13, t14]
4164
+ }, void 0, true);
4165
+ $[42] = t10;
4166
+ $[43] = t11;
4167
+ $[44] = t12;
4168
+ $[45] = t13;
4169
+ $[46] = t14;
4170
+ $[47] = t2;
4171
+ $[48] = t4;
4172
+ $[49] = t9;
4173
+ $[50] = t15;
4174
+ } else {
4175
+ t15 = $[50];
4176
+ }
4177
+ let t16;
4178
+ if ($[51] !== columns || $[52] !== filter || $[53] !== filters || $[54] !== onFilterChange || $[55] !== onFiltersChange) {
4179
+ t16 = /* @__PURE__ */ jsxDEV(DataFilters, {
4180
+ columns,
4181
+ filters,
4182
+ onFiltersChange,
4183
+ onSearchChange: onFilterChange,
4184
+ search: filter
4185
+ }, void 0, false);
4186
+ $[51] = columns;
4187
+ $[52] = filter;
4188
+ $[53] = filters;
4189
+ $[54] = onFilterChange;
4190
+ $[55] = onFiltersChange;
4191
+ $[56] = t16;
4192
+ } else {
4193
+ t16 = $[56];
4194
+ }
4195
+ let t17;
4196
+ if ($[57] !== t15 || $[58] !== t16) {
4197
+ t17 = /* @__PURE__ */ jsxDEV("div", {
4198
+ className: "flex flex-col gap-2",
4199
+ "data-testid": "db-view-toggle",
4200
+ children: [t15, t16]
4201
+ }, void 0, true);
4202
+ $[57] = t15;
4203
+ $[58] = t16;
4204
+ $[59] = t17;
4205
+ } else {
4206
+ t17 = $[59];
4207
+ }
4208
+ return t17;
4209
+ };
4210
+ const DataBrowser = ({
4211
+ editable = false,
4212
+ globalTableNames,
4213
+ initialFilters,
4214
+ initialOrderBy,
4215
+ initialSearch,
4216
+ initialShardKey,
4217
+ onNavigateToGlobal,
4218
+ onSelectTable,
4219
+ onViewChange,
4220
+ pageSize: initialPageSize = DEFAULT_PAGE_SIZE,
4221
+ queryBar,
4222
+ schemaSwitch,
4223
+ tableParam
4224
+ }) => {
4225
+ const {
4226
+ addRow,
4227
+ bulkDelete,
4228
+ cancelCellEdit,
4229
+ cancelEdit,
4230
+ changePageSize,
4231
+ clearTable,
4232
+ columns,
4233
+ committing,
4234
+ currentView,
4235
+ discardStaged,
4236
+ editableColumn,
4237
+ editing,
4238
+ editingCell,
4239
+ facetFilter,
4240
+ facets,
4241
+ filter,
4242
+ filters,
4243
+ goNext,
4244
+ goPrevious,
4245
+ hasNext,
4246
+ hasPrevious,
4247
+ jumpToPage,
4248
+ liveError,
4249
+ loadTables,
4250
+ navigateToRef,
4251
+ onBulkDeleteSelected,
4252
+ onCommitStaged,
4253
+ onFilterChange,
4254
+ onFiltersChange,
4255
+ onRowDelete,
4256
+ onRowEdit,
4257
+ page,
4258
+ pageError,
4259
+ previewRef,
4260
+ pageSize,
4261
+ rangeEnd,
4262
+ rangeStart,
4263
+ saveEdit,
4264
+ selectedTable,
4265
+ selectTable,
4266
+ setEditorDocumentText,
4267
+ setShardKey,
4268
+ shardKey,
4269
+ showJson,
4270
+ showTable,
4271
+ stage,
4272
+ stagedChanges,
4273
+ stagedValue,
4274
+ startCellEdit,
4275
+ table,
4276
+ tables,
4277
+ tablesError,
4278
+ toggleFacet,
4279
+ total,
4280
+ viewMode,
4281
+ writeError
4282
+ } = useDataBrowser({
4283
+ initialFilters,
4284
+ initialOrderBy,
4285
+ initialSearch,
4286
+ initialShardKey,
4287
+ onSelectTable,
4288
+ onViewChange,
4289
+ pageSize: initialPageSize,
4290
+ tableParam
4291
+ });
4292
+ const client = useLunora();
4293
+ const onFetchShardTables = async (targetShard) => {
4294
+ const result = await client.query(LIST_TABLES, {}, callOptions(targetShard));
4295
+ return result;
4296
+ };
4297
+ const onRefreshAfterGenerate = () => {
4298
+ if (selectedTable !== null) {
4299
+ selectTable(selectedTable);
4300
+ }
4301
+ };
4302
+ const {
4303
+ closeDialog: closeGenerateDialog,
4304
+ columnMeta,
4305
+ fkPools,
4306
+ insertBatch,
4307
+ open: generateOpen,
4308
+ openDialog: openGenerateDialog
4309
+ } = useGenerateRows(onRefreshAfterGenerate);
4310
+ const onOpenGenerateRows = () => {
4311
+ if (selectedTable !== null) {
4312
+ openGenerateDialog(selectedTable, shardKey);
4313
+ }
4314
+ };
4315
+ const onInsertGeneratedRows = (rows) => insertBatch(rows, closeGenerateDialog);
4316
+ const [inspecting, setInspecting] = useState(null);
4317
+ const closeInspect = () => {
4318
+ setInspecting(null);
4319
+ };
4320
+ const [transposed, setTransposed] = useState(false);
4321
+ const onToggleTranspose = () => {
4322
+ setTransposed((current) => !current);
4323
+ };
4324
+ const maskPolicies = useMaskPolicies();
4325
+ const [maskOn, setMaskOn] = useState(true);
4326
+ const onToggleMask = () => {
4327
+ setMaskOn((current_0) => !current_0);
4328
+ };
4329
+ const explicitMaskColumns = maskColumnsForTable(maskPolicies, selectedTable ?? "");
4330
+ const maskColumns = mergeSensitiveColumns(explicitMaskColumns, columns);
4331
+ const maskView = {
4332
+ columns: maskColumns,
4333
+ enabled: maskOn
4334
+ };
4335
+ const [expandedCell, setExpandedCell] = useState(null);
4336
+ const onExpandCell = (column, value) => {
4337
+ setExpandedCell({
4338
+ column,
4339
+ value
4340
+ });
4341
+ };
4342
+ const closeExpandedCell = () => {
4343
+ setExpandedCell(null);
4344
+ };
4345
+ const handleNavigateRef = (target, id) => {
4346
+ if (onNavigateToGlobal !== void 0 && globalTableNames?.has(target) === true) {
4347
+ onNavigateToGlobal(target, id);
4348
+ return;
4349
+ }
4350
+ navigateToRef(target, id);
4351
+ };
4352
+ const onSaveQuery = queryBar?.onSaveQuery;
4353
+ const saveCurrentQuery = (name) => {
4354
+ onSaveQuery?.(name, currentView);
4355
+ };
4356
+ const edit = {
4357
+ cancelEdit: cancelCellEdit,
4358
+ editable,
4359
+ editableColumn,
4360
+ editingCell,
4361
+ onExpandCell,
4362
+ stage,
4363
+ stagedValue,
4364
+ startEdit: startCellEdit
4365
+ };
4366
+ const references = {
4367
+ columns: page?.refs,
4368
+ onNavigate: handleNavigateRef,
4369
+ onPreview: previewRef
4370
+ };
4371
+ return /* @__PURE__ */ jsxDEV("div", {
4372
+ className: "flex h-full min-w-0",
4373
+ "data-testid": "lunora-data-browser",
4374
+ children: [/* @__PURE__ */ jsxDEV(TableListSidebar, {
4375
+ header: /* @__PURE__ */ jsxDEV(DataBrowserSidebarHeader, {
4376
+ onFetchShardTables,
4377
+ onShardChange: setShardKey,
4378
+ schemaSwitch,
4379
+ shardKey
4380
+ }, void 0, false),
4381
+ onReload: loadTables,
4382
+ onSelect: selectTable,
4383
+ prefix: "db",
4384
+ selected: selectedTable,
4385
+ tables: tables ?? NO_TABLES
4386
+ }, void 0, false), /* @__PURE__ */ jsxDEV("div", {
4387
+ className: "flex min-w-0 flex-1 flex-col overflow-hidden",
4388
+ children: [tablesError !== null && /* @__PURE__ */ jsxDEV("p", {
4389
+ className: "shrink-0 border-b border-border px-4 py-2 text-sm text-destructive",
4390
+ "data-testid": "db-tables-error",
4391
+ role: "alert",
4392
+ children: tablesError
4393
+ }, void 0, false), page === null && pageError === null && /* @__PURE__ */ jsxDEV("div", {
4394
+ className: "flex flex-1 items-center justify-center p-6",
4395
+ children: /* @__PURE__ */ jsxDEV("p", {
4396
+ className: "text-sm text-muted-foreground",
4397
+ children: "Select a table to browse its rows."
4398
+ }, void 0, false)
4399
+ }, void 0, false), pageError !== null && /* @__PURE__ */ jsxDEV("p", {
4400
+ className: "shrink-0 border-b border-border px-4 py-2 text-sm text-destructive",
4401
+ "data-testid": "db-page-error",
4402
+ role: "alert",
4403
+ children: pageError
4404
+ }, void 0, false), page !== null && /* @__PURE__ */ jsxDEV("div", {
4405
+ className: "flex min-h-0 flex-1 flex-col",
4406
+ "data-testid": "db-page",
4407
+ children: [/* @__PURE__ */ jsxDEV("div", {
4408
+ className: "flex shrink-0 flex-col gap-2 border-b border-border px-4 py-3",
4409
+ children: [/* @__PURE__ */ jsxDEV(DataBrowserViewControls, {
4410
+ columns,
4411
+ editable,
4412
+ filter,
4413
+ filters,
4414
+ hasMaskedColumns: maskColumns.size > 0,
4415
+ liveError,
4416
+ maskOn,
4417
+ onAddRow: addRow,
4418
+ onBulkDelete: bulkDelete,
4419
+ onClearTable: clearTable,
4420
+ onFilterChange,
4421
+ onFiltersChange,
4422
+ onGenerateRows: onOpenGenerateRows,
4423
+ onShowJson: showJson,
4424
+ onShowTable: showTable,
4425
+ onToggleMask,
4426
+ total,
4427
+ viewMode
4428
+ }, void 0, false), queryBar !== void 0 && /* @__PURE__ */ jsxDEV(DataQueryBar, {
4429
+ onApply: queryBar.onApplyQuery,
4430
+ onCopyLink: queryBar.onCopyLink,
4431
+ onDelete: queryBar.onDeleteQuery,
4432
+ onSave: saveCurrentQuery,
4433
+ saved: queryBar.saved
4434
+ }, void 0, false), viewMode === "table" && page.rows.length > 0 && /* @__PURE__ */ jsxDEV(GridActionsBar, {
4435
+ columns: page.columns,
4436
+ editable,
4437
+ name: selectedTable ?? "export",
4438
+ onBulkDelete: onBulkDeleteSelected,
4439
+ onToggleTranspose,
4440
+ rows: page.rows,
4441
+ table: table.table,
4442
+ transposed
4443
+ }, void 0, false), editable && editing !== null && /* @__PURE__ */ jsxDEV(RowFormEditor, {
4444
+ documentText: editing.docText,
4445
+ onCancel: cancelEdit,
4446
+ onDocumentTextChange: setEditorDocumentText,
4447
+ onSave: saveEdit,
4448
+ refs: page.refs
4449
+ }, void 0, false), editable && stagedChanges.length > 0 && /* @__PURE__ */ jsxDEV(StagedDiffPanel, {
4450
+ changes: stagedChanges,
4451
+ committing,
4452
+ onCommit: onCommitStaged,
4453
+ onDiscard: discardStaged
4454
+ }, void 0, false), writeError !== null && /* @__PURE__ */ jsxDEV("p", {
4455
+ className: "text-sm text-destructive",
4456
+ "data-testid": "db-write-error",
4457
+ role: "alert",
4458
+ children: writeError
4459
+ }, void 0, false)]
4460
+ }, void 0, true), viewMode === "table" && page.rows.length === 0 && /* @__PURE__ */ jsxDEV("div", {
4461
+ className: "flex flex-1 items-center justify-center p-6",
4462
+ children: /* @__PURE__ */ jsxDEV(EmptyState, {
4463
+ description: "Rows you insert into this table will show up here.",
4464
+ icon: /* @__PURE__ */ jsxDEV("svg", {
4465
+ "aria-hidden": "true",
4466
+ fill: "none",
4467
+ stroke: "currentColor",
4468
+ strokeLinecap: "round",
4469
+ strokeLinejoin: "round",
4470
+ strokeWidth: 1.6,
4471
+ viewBox: "0 0 24 24",
4472
+ children: /* @__PURE__ */ jsxDEV("path", {
4473
+ d: "M4 5h16v14H4V5Zm0 5h16M10 10v9M4 14.5h16"
4474
+ }, void 0, false)
4475
+ }, void 0, false),
4476
+ testId: "db-empty-rows",
4477
+ title: "This table is empty."
4478
+ }, void 0, false)
4479
+ }, void 0, false), viewMode === "table" && page.rows.length > 0 && transposed && /* @__PURE__ */ jsxDEV(TransposedTable, {
4480
+ columns: page.columns,
4481
+ rows: maskRows(page.rows, maskView)
4482
+ }, void 0, false), viewMode === "table" && page.rows.length > 0 && !transposed && /* @__PURE__ */ jsxDEV(DataBrowserTableView, {
4483
+ edit,
4484
+ editable,
4485
+ mask: maskView,
4486
+ onDelete: onRowDelete,
4487
+ onEdit: onRowEdit,
4488
+ onInspect: setInspecting,
4489
+ refs: references,
4490
+ scrollRef: table.scrollRef,
4491
+ scrollToIndex: table.scrollToIndex,
4492
+ table: table.table,
4493
+ tableRows: table.tableRows,
4494
+ tbodyStyle: table.tbodyStyle,
4495
+ virtualRows: table.virtualRows
4496
+ }, void 0, false), viewMode === "json" && /* @__PURE__ */ jsxDEV("pre", {
4497
+ className: "min-h-0 flex-1 overflow-auto border-t border-border bg-muted/30 p-3 text-xs",
4498
+ "data-testid": "db-json",
4499
+ children: JSON.stringify(maskRows(page.rows, maskView), null, 2)
4500
+ }, void 0, false), /* @__PURE__ */ jsxDEV("div", {
4501
+ className: "flex shrink-0 items-center border-t border-border px-4 py-2",
4502
+ children: /* @__PURE__ */ jsxDEV(GridPagination, {
4503
+ hasNext,
4504
+ hasPrevious,
4505
+ onJumpToPage: jumpToPage,
4506
+ onNext: goNext,
4507
+ onPageSizeChange: changePageSize,
4508
+ onPrevious: goPrevious,
4509
+ pageSize,
4510
+ prefix: "db",
4511
+ rangeEnd,
4512
+ rangeStart,
4513
+ total
4514
+ }, void 0, false)
4515
+ }, void 0, false)]
4516
+ }, void 0, true)]
4517
+ }, void 0, true), page !== null && /* @__PURE__ */ jsxDEV(DataFacets, {
4518
+ columns,
4519
+ facets,
4520
+ onFacetFilter: facetFilter,
4521
+ onToggleFacet: toggleFacet
4522
+ }, void 0, false), inspecting !== null && page !== null && /* @__PURE__ */ jsxDEV(RowDetailDrawer, {
4523
+ columns: page.columns,
4524
+ onClose: closeInspect,
4525
+ onNavigate: handleNavigateRef,
4526
+ refs: page.refs,
4527
+ row: inspecting
4528
+ }, void 0, false), expandedCell !== null && /* @__PURE__ */ jsxDEV(CellDetailDialog, {
4529
+ column: expandedCell.column,
4530
+ onClose: closeExpandedCell,
4531
+ value: expandedCell.value
4532
+ }, void 0, false), generateOpen && selectedTable !== null && columnMeta !== void 0 && /* @__PURE__ */ jsxDEV(GenerateRowsDialog, {
4533
+ columns: columnMeta,
4534
+ fkPools,
4535
+ onClose: closeGenerateDialog,
4536
+ onInsertRows: onInsertGeneratedRows,
4537
+ table: selectedTable
4538
+ }, void 0, false)]
4539
+ }, void 0, true);
4540
+ };
4541
+
4542
+ export { DataBrowser };