@burdenoff/microfe-cosmicintersection 2026.805.1 → 2026.827.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.
@@ -16,8 +16,8 @@ import fe, { buildDatasetLineage as pe } from "../../components/LineageGraph.js"
16
16
  import { useMemo as me, useState as u } from "react";
17
17
  import { Fragment as he, jsx as d, jsxs as f } from "react/jsx-runtime";
18
18
  import { useParams as ge } from "react-router";
19
- import { ArrowRight as _e, Boxes as ve, Columns3 as p, Database as ye, Download as be, GitBranch as xe, History as Se, MessagesSquare as Ce, Pencil as we, Plus as Te, Radar as Ee, Share2 as De } from "lucide-react";
20
- import { Badge as m, Button as h, Checkbox as Oe, Dialog as ke, DialogContent as Ae, DialogDescription as je, DialogFooter as Me, DialogHeader as Ne, DialogTitle as Pe, Input as g, Label as _, Select as Fe, SelectContent as Ie, SelectItem as Le, SelectTrigger as Re, SelectValue as ze, Table as Be, TableBody as Ve, TableCell as v, TableHead as y, TableHeader as He, TableRow as b, Textarea as Ue } from "@burdenoff/fe-libs/ui";
19
+ import { ArrowRight as _e, Boxes as ve, Columns3 as p, Database as ye, Download as be, GitBranch as xe, History as Se, MessagesSquare as Ce, Pencil as we, Plus as Te, Radar as Ee, Share2 as De, TriangleAlert as m } from "lucide-react";
20
+ import { Badge as h, Button as g, Checkbox as Oe, Dialog as ke, DialogContent as Ae, DialogDescription as je, DialogFooter as Me, DialogHeader as Ne, DialogTitle as Pe, Input as _, Label as v, Select as Fe, SelectContent as Ie, SelectItem as Le, SelectTrigger as Re, SelectValue as ze, Table as Be, TableBody as Ve, TableCell as y, TableHead as b, TableHeader as He, TableRow as x, Textarea as Ue } from "@burdenoff/fe-libs/ui";
21
21
  //#region src/cosmicintersection/pages/datasets/DatasetDetailPage.tsx
22
22
  var We = [
23
23
  "STRING",
@@ -30,7 +30,14 @@ var We = [
30
30
  "GEOMETRY",
31
31
  "IMAGE_REF",
32
32
  "JSON"
33
- ];
33
+ ], S = new Set([
34
+ "FLOAT",
35
+ "COORDINATE",
36
+ "SPECTRUM"
37
+ ]);
38
+ function C(e) {
39
+ return S.has(e.fieldType) && !e.unit;
40
+ }
34
41
  function Ge(e) {
35
42
  if (!e) return "—";
36
43
  let t = Number(e);
@@ -46,12 +53,12 @@ function Ge(e) {
46
53
  for (; r >= 1024 && i < n.length - 1;) r /= 1024, i += 1;
47
54
  return `${r >= 10 || i === 0 ? Math.round(r) : r.toFixed(1)} ${n[i]}`;
48
55
  }
49
- function x(e) {
56
+ function w(e) {
50
57
  if (!e) return "—";
51
58
  let t = new Date(e);
52
59
  return Number.isNaN(t.getTime()) ? "—" : t.toLocaleString();
53
60
  }
54
- function S({ label: e, value: t }) {
61
+ function T({ label: e, value: t }) {
55
62
  return /* @__PURE__ */ f("div", {
56
63
  className: "rounded-card border border-border-default bg-bg-elevated p-4",
57
64
  children: [/* @__PURE__ */ d("p", {
@@ -63,47 +70,47 @@ function S({ label: e, value: t }) {
63
70
  })]
64
71
  });
65
72
  }
66
- function C() {
67
- let { id: C = "" } = ge(), { navigate: w } = e(), { data: T, loading: Ke, error: qe, refetch: E } = ee(C), D = T?.cosDataset ?? null, O = de(D?.file?.id).data?.getFileDownloadUrl ?? null, [Je, { loading: Ye }] = ne(), [Xe] = i(), [Ze, { loading: k }] = ae(), [Qe, { loading: A }] = n(), j = r({ datasetId: C }), M = ie({ pagination: {
73
+ function E() {
74
+ let { id: S = "" } = ge(), { navigate: E } = e(), { data: D, loading: Ke, error: qe, refetch: O } = ee(S), k = D?.cosDataset ?? null, A = de(k?.file?.id).data?.getFileDownloadUrl ?? null, [Je, { loading: j }] = ne(), [Ye] = i(), [Xe, { loading: M }] = ae(), [Ze, { loading: N }] = n(), P = r({ datasetId: S }), F = ie({ pagination: {
68
75
  limit: 100,
69
76
  offset: 0
70
- } }), N = te({ pagination: {
77
+ } }), I = te({ pagination: {
71
78
  limit: 100,
72
79
  offset: 0
73
- } }), P = re({ pagination: {
80
+ } }), L = re({ pagination: {
74
81
  limit: 100,
75
82
  offset: 0
76
- } }), F = T?.cosDataset ?? null, I = me(() => {
77
- if (!F) return {
83
+ } }), R = D?.cosDataset ?? null, z = me(() => {
84
+ if (!R) return {
78
85
  nodes: [],
79
86
  edges: []
80
87
  };
81
88
  let e = /* @__PURE__ */ new Map();
82
- F.source && e.set(F.source.id, F.source);
89
+ R.source && e.set(R.source.id, R.source);
83
90
  let t = /* @__PURE__ */ new Map();
84
- F.collection && t.set(F.collection.id, F.collection);
91
+ R.collection && t.set(R.collection.id, R.collection);
85
92
  let n = {
86
- datasetsById: new Map([[F.id, F]]),
93
+ datasetsById: new Map([[R.id, R]]),
87
94
  sourcesById: e,
88
95
  collectionsById: t,
89
- runs: (M.data?.cosListRuns?.items ?? []).filter((e) => e.datasetId === F.id),
90
- notebooks: (N.data?.cosListNotebooks?.items ?? []).filter((e) => e.datasetIds.includes(F.id)),
91
- analyses: j.data?.cosListAnalyses ?? [],
92
- releases: (P.data?.cosListReleases?.items ?? []).filter((e) => e.datasetIds.includes(F.id))
96
+ runs: (F.data?.cosListRuns?.items ?? []).filter((e) => e.datasetId === R.id),
97
+ notebooks: (I.data?.cosListNotebooks?.items ?? []).filter((e) => e.datasetIds.includes(R.id)),
98
+ analyses: P.data?.cosListAnalyses ?? [],
99
+ releases: (L.data?.cosListReleases?.items ?? []).filter((e) => e.datasetIds.includes(R.id))
93
100
  };
94
- return pe(F.id, n);
101
+ return pe(R.id, n);
95
102
  }, [
96
- F,
97
- M.data,
98
- N.data,
99
- j.data,
100
- P.data
101
- ]), $e = M.loading || N.loading || j.loading || P.loading, [L, R] = u([]), [et, tt] = u(null), z = D ? `${D.id}:${D.updatedAt}` : null;
102
- z && z !== et && (tt(z), R(D?.tags ?? []));
103
- let nt = D != null && (L.length !== D.tags.length || L.some((e, t) => e !== D.tags[t])), [rt, it] = u(!1), [B, V] = u(""), [H, U] = u("STRING"), [W, G] = u(""), [K, q] = u(""), [J, Y] = u(""), [X, Z] = u(!0), at = () => {
104
- V(""), U("STRING"), G(""), q(""), Y(""), Z(!0);
105
- }, Q = (e) => {
106
- it(e), e || at();
103
+ R,
104
+ F.data,
105
+ I.data,
106
+ P.data,
107
+ L.data
108
+ ]), Qe = F.loading || I.loading || P.loading || L.loading, [B, V] = u([]), [$e, et] = u(null), H = k ? `${k.id}:${k.updatedAt}` : null;
109
+ H && H !== $e && (et(H), V(k?.tags ?? []));
110
+ let tt = k != null && (B.length !== k.tags.length || B.some((e, t) => e !== k.tags[t])), [nt, rt] = u(!1), [U, W] = u(""), [G, K] = u("STRING"), [q, J] = u(""), [Y, it] = u(""), [X, at] = u(""), [ot, st] = u(!0), ct = () => {
111
+ W(""), K("STRING"), J(""), it(""), at(""), st(!0);
112
+ }, Z = (e) => {
113
+ rt(e), e || ct();
107
114
  };
108
115
  if (Ke) return /* @__PURE__ */ d(s, {
109
116
  title: "Dataset",
@@ -115,73 +122,73 @@ function C() {
115
122
  backPath: "datasets",
116
123
  children: /* @__PURE__ */ d(se, {
117
124
  message: "We could not load this dataset.",
118
- onRetry: () => void E()
125
+ onRetry: () => void O()
119
126
  })
120
127
  });
121
- if (!D) return /* @__PURE__ */ d(s, {
128
+ if (!k) return /* @__PURE__ */ d(s, {
122
129
  title: "Dataset",
123
130
  backPath: "datasets",
124
131
  children: /* @__PURE__ */ d(a, {
125
132
  icon: ye,
126
133
  title: "Dataset not found.",
127
134
  description: "This dataset may have been removed or is outside your current scope.",
128
- action: /* @__PURE__ */ d(h, {
135
+ action: /* @__PURE__ */ d(g, {
129
136
  type: "button",
130
- onClick: () => w("datasets"),
137
+ onClick: () => E("datasets"),
131
138
  children: "Back to datasets"
132
139
  })
133
140
  })
134
141
  });
135
- let $ = [...D.schemaFields ?? []].sort((e, t) => e.position - t.position), ot = D.status !== "AVAILABLE" && D.status !== "ARCHIVED", st = async () => {
136
- (await Je({ variables: { id: D.id } })).data?.cosPublishDataset && (t.success("Dataset published", `“${D.name}” is now available.`), await E());
137
- }, ct = async () => {
138
- let e = await Xe({ variables: { id: D.id } });
142
+ let Q = [...k.schemaFields ?? []].sort((e, t) => e.position - t.position), $ = Q.filter(C).length, lt = k.status !== "AVAILABLE" && k.status !== "ARCHIVED", ut = async () => {
143
+ (await Je({ variables: { id: k.id } })).data?.cosPublishDataset && (t.success("Dataset published", `“${k.name}” is now available.`), await O());
144
+ }, dt = async () => {
145
+ let e = await Ye({ variables: { id: k.id } });
139
146
  if (e.error) throw Error(e.error.message);
140
147
  if (!e.data?.cosArchiveDataset) throw t.error("Could not archive dataset", "The server did not confirm the change."), Error("Archive not confirmed");
141
- t.success("Dataset archived"), w("datasets");
142
- }, lt = async () => {
143
- (await Ze({ variables: {
144
- id: D.id,
145
- input: { tags: L }
146
- } })).data?.cosUpdateDataset && (t.success("Tags updated"), await E());
147
- }, ut = async () => {
148
- if (!B.trim()) {
148
+ t.success("Dataset archived"), E("datasets");
149
+ }, ft = async () => {
150
+ (await Xe({ variables: {
151
+ id: k.id,
152
+ input: { tags: B }
153
+ } })).data?.cosUpdateDataset && (t.success("Tags updated"), await O());
154
+ }, pt = async () => {
155
+ if (!U.trim()) {
149
156
  t.error("Field name is required");
150
157
  return;
151
158
  }
152
- (await Qe({ variables: { input: {
153
- datasetId: D.id,
154
- name: B.trim(),
155
- fieldType: H,
156
- unit: W.trim() || void 0,
157
- description: K.trim() || void 0,
158
- provenance: J.trim() || void 0,
159
- nullable: X
160
- } } })).data?.cosAddSchemaField && (t.success("Schema field added"), Q(!1), await E());
159
+ (await Ze({ variables: { input: {
160
+ datasetId: k.id,
161
+ name: U.trim(),
162
+ fieldType: G,
163
+ unit: q.trim() || void 0,
164
+ description: Y.trim() || void 0,
165
+ provenance: X.trim() || void 0,
166
+ nullable: ot
167
+ } } })).data?.cosAddSchemaField && (t.success("Schema field added"), Z(!1), await O());
161
168
  };
162
169
  return /* @__PURE__ */ f(s, {
163
- title: D.name,
164
- description: D.description ?? void 0,
170
+ title: k.name,
171
+ description: k.description ?? void 0,
165
172
  backPath: "datasets",
166
173
  actions: /* @__PURE__ */ f("div", {
167
174
  className: "flex flex-wrap items-center justify-end gap-2",
168
175
  children: [
169
- /* @__PURE__ */ f(h, {
176
+ /* @__PURE__ */ f(g, {
170
177
  type: "button",
171
178
  variant: "outline",
172
- onClick: () => w(`datasets/${D.id}/edit`),
179
+ onClick: () => E(`datasets/${k.id}/edit`),
173
180
  children: [/* @__PURE__ */ d(we, { className: "size-4" }), "Edit"]
174
181
  }),
175
- ot ? /* @__PURE__ */ d(h, {
182
+ lt ? /* @__PURE__ */ d(g, {
176
183
  type: "button",
177
- onClick: () => void st(),
178
- disabled: Ye,
179
- children: Ye ? "Publishing…" : "Publish"
184
+ onClick: () => void ut(),
185
+ disabled: j,
186
+ children: j ? "Publishing…" : "Publish"
180
187
  }) : null,
181
188
  /* @__PURE__ */ d(oe, {
182
- ariaLabel: `Actions for ${D.name}`,
183
- entityName: D.name,
184
- onDelete: () => ct(),
189
+ ariaLabel: `Actions for ${k.name}`,
190
+ entityName: k.name,
191
+ onDelete: () => dt(),
185
192
  deleteLabel: "Archive dataset"
186
193
  })
187
194
  ]
@@ -192,10 +199,10 @@ function C() {
192
199
  /* @__PURE__ */ f("div", {
193
200
  className: "flex flex-wrap items-center gap-2",
194
201
  children: [
195
- /* @__PURE__ */ d(c, { status: D.status }),
202
+ /* @__PURE__ */ d(c, { status: k.status }),
196
203
  /* @__PURE__ */ d(c, {
197
- status: D.accessLevel,
198
- label: l(D.accessLevel)
204
+ status: k.accessLevel,
205
+ label: l(k.accessLevel)
199
206
  }),
200
207
  /* @__PURE__ */ f("span", {
201
208
  className: "inline-flex items-center gap-1.5 rounded-full border border-border-default bg-bg-elevated px-2.5 py-0.5 text-xs font-medium",
@@ -207,7 +214,7 @@ function C() {
207
214
  }),
208
215
  /* @__PURE__ */ f("span", {
209
216
  className: "text-text-primary",
210
- children: ["v", D.version]
217
+ children: ["v", k.version]
211
218
  }),
212
219
  /* @__PURE__ */ d("span", {
213
220
  className: "text-text-tertiary",
@@ -220,71 +227,71 @@ function C() {
220
227
  /* @__PURE__ */ f("div", {
221
228
  className: "grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4",
222
229
  children: [
223
- /* @__PURE__ */ d(S, {
230
+ /* @__PURE__ */ d(T, {
224
231
  label: "Source",
225
- value: D.source ? /* @__PURE__ */ f("button", {
232
+ value: k.source ? /* @__PURE__ */ f("button", {
226
233
  type: "button",
227
- onClick: () => w(`sources/${D.source?.id}`),
234
+ onClick: () => E(`sources/${k.source?.id}`),
228
235
  className: "inline-flex items-center gap-1.5 text-text-primary underline-offset-2 hover:underline",
229
236
  children: [/* @__PURE__ */ d(Ee, {
230
237
  className: "size-4 text-text-secondary",
231
238
  "aria-hidden": "true"
232
- }), D.source.name]
239
+ }), k.source.name]
233
240
  }) : /* @__PURE__ */ d("span", {
234
241
  className: "text-text-secondary",
235
242
  children: "Not linked"
236
243
  })
237
244
  }),
238
- /* @__PURE__ */ d(S, {
245
+ /* @__PURE__ */ d(T, {
239
246
  label: "Collection",
240
- value: D.collection ? /* @__PURE__ */ f("button", {
247
+ value: k.collection ? /* @__PURE__ */ f("button", {
241
248
  type: "button",
242
- onClick: () => w(`collections/${D.collection?.id}`),
249
+ onClick: () => E(`collections/${k.collection?.id}`),
243
250
  className: "inline-flex items-center gap-1.5 text-text-primary underline-offset-2 hover:underline",
244
251
  children: [/* @__PURE__ */ d(ve, {
245
252
  className: "size-4 text-text-secondary",
246
253
  "aria-hidden": "true"
247
- }), D.collection.name]
254
+ }), k.collection.name]
248
255
  }) : /* @__PURE__ */ d("span", {
249
256
  className: "text-text-secondary",
250
257
  children: "Not in a collection"
251
258
  })
252
259
  }),
253
- /* @__PURE__ */ d(S, {
260
+ /* @__PURE__ */ d(T, {
254
261
  label: "Format",
255
- value: /* @__PURE__ */ d("span", { children: D.format || "Not specified" })
262
+ value: /* @__PURE__ */ d("span", { children: k.format || "Not specified" })
256
263
  }),
257
- /* @__PURE__ */ d(S, {
264
+ /* @__PURE__ */ d(T, {
258
265
  label: "Size",
259
266
  value: /* @__PURE__ */ f("span", {
260
267
  className: "tabular-nums",
261
- children: [Ge(D.sizeBytes), Number(D.rowCount) > 0 ? /* @__PURE__ */ f("span", {
268
+ children: [Ge(k.sizeBytes), Number(k.rowCount) > 0 ? /* @__PURE__ */ f("span", {
262
269
  className: "text-text-secondary",
263
270
  children: [
264
271
  " ",
265
272
  "· ",
266
- Number(D.rowCount).toLocaleString(),
273
+ Number(k.rowCount).toLocaleString(),
267
274
  " rows"
268
275
  ]
269
276
  }) : null]
270
277
  })
271
278
  }),
272
- /* @__PURE__ */ d(S, {
279
+ /* @__PURE__ */ d(T, {
273
280
  label: "Ingested",
274
- value: /* @__PURE__ */ d("span", { children: x(D.ingestedAt) })
281
+ value: /* @__PURE__ */ d("span", { children: w(k.ingestedAt) })
275
282
  }),
276
- /* @__PURE__ */ d(S, {
283
+ /* @__PURE__ */ d(T, {
277
284
  label: "Created",
278
- value: /* @__PURE__ */ d("span", { children: x(D.createdAt) })
285
+ value: /* @__PURE__ */ d("span", { children: w(k.createdAt) })
279
286
  }),
280
- /* @__PURE__ */ d(S, {
287
+ /* @__PURE__ */ d(T, {
281
288
  label: "Updated",
282
- value: /* @__PURE__ */ d("span", { children: x(D.updatedAt) })
289
+ value: /* @__PURE__ */ d("span", { children: w(k.updatedAt) })
283
290
  }),
284
- /* @__PURE__ */ d(S, {
291
+ /* @__PURE__ */ d(T, {
285
292
  label: "Artifact",
286
- value: D.file ? O ? /* @__PURE__ */ f("a", {
287
- href: O,
293
+ value: k.file ? A ? /* @__PURE__ */ f("a", {
294
+ href: A,
288
295
  target: "_blank",
289
296
  rel: "noopener noreferrer",
290
297
  className: "inline-flex items-center gap-1.5 text-text-primary underline-offset-2 hover:underline",
@@ -317,20 +324,20 @@ function C() {
317
324
  })]
318
325
  }), /* @__PURE__ */ f("button", {
319
326
  type: "button",
320
- onClick: () => w(`lineage/${D.id}`),
327
+ onClick: () => E(`lineage/${k.id}`),
321
328
  className: "inline-flex items-center gap-1 rounded-button text-sm font-medium text-text-link underline-offset-2 hover:underline focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border-focus",
322
329
  children: ["View full lineage", /* @__PURE__ */ d(_e, {
323
330
  className: "size-4",
324
331
  "aria-hidden": "true"
325
332
  })]
326
333
  })]
327
- }), $e && I.nodes.length <= 1 ? /* @__PURE__ */ d(o, { label: "Building lineage…" }) : I.nodes.length <= 1 ? /* @__PURE__ */ d("div", {
334
+ }), Qe && z.nodes.length <= 1 ? /* @__PURE__ */ d(o, { label: "Building lineage…" }) : z.nodes.length <= 1 ? /* @__PURE__ */ d("div", {
328
335
  className: "rounded-card border border-dashed border-border-default bg-bg-sunken p-6 text-sm text-text-secondary",
329
336
  children: "No upstream or downstream provenance is linked to this dataset yet. Connect a source, run a pipeline, attach a notebook, or publish a release to build its lineage."
330
337
  }) : /* @__PURE__ */ d(fe, {
331
- model: I,
338
+ model: z,
332
339
  mode: "compact",
333
- onNavigate: w
340
+ onNavigate: E
334
341
  })]
335
342
  }),
336
343
  /* @__PURE__ */ f("section", {
@@ -338,61 +345,96 @@ function C() {
338
345
  children: [/* @__PURE__ */ f("div", {
339
346
  className: "flex items-center justify-between gap-3",
340
347
  children: [/* @__PURE__ */ f("div", {
341
- className: "flex items-center gap-2",
342
- children: [/* @__PURE__ */ d(p, {
343
- className: "size-5 text-text-secondary",
344
- "aria-hidden": "true"
345
- }), /* @__PURE__ */ d("h2", {
346
- className: "text-lg font-semibold text-text-primary",
347
- children: "Schema fields"
348
- })]
349
- }), /* @__PURE__ */ f(h, {
348
+ className: "flex flex-wrap items-center gap-2",
349
+ children: [
350
+ /* @__PURE__ */ d(p, {
351
+ className: "size-5 text-text-secondary",
352
+ "aria-hidden": "true"
353
+ }),
354
+ /* @__PURE__ */ d("h2", {
355
+ className: "text-lg font-semibold text-text-primary",
356
+ children: "Schema fields"
357
+ }),
358
+ Q.length > 0 ? /* @__PURE__ */ d(h, {
359
+ variant: "secondary",
360
+ className: "text-xs",
361
+ children: Q.length
362
+ }) : null,
363
+ $ > 0 ? /* @__PURE__ */ f(h, {
364
+ variant: "outline",
365
+ className: "gap-1 border-status-warning-border bg-status-warning-bg-subtle text-xs text-status-warning-text",
366
+ children: [
367
+ /* @__PURE__ */ d(m, {
368
+ className: "size-3",
369
+ "aria-hidden": "true"
370
+ }),
371
+ $,
372
+ " missing a unit"
373
+ ]
374
+ }) : null
375
+ ]
376
+ }), /* @__PURE__ */ f(g, {
350
377
  type: "button",
351
378
  variant: "outline",
352
379
  size: "sm",
353
- onClick: () => Q(!0),
380
+ onClick: () => Z(!0),
354
381
  children: [/* @__PURE__ */ d(Te, { className: "size-4" }), "Add field"]
355
382
  })]
356
- }), $.length === 0 ? /* @__PURE__ */ d(a, {
383
+ }), Q.length === 0 ? /* @__PURE__ */ d(a, {
357
384
  icon: p,
358
385
  title: "No schema fields yet.",
359
386
  description: "Describe the columns in this dataset so consumers know what each field means."
360
387
  }) : /* @__PURE__ */ f(he, { children: [/* @__PURE__ */ d("div", {
361
388
  className: "hidden rounded-card border border-border-default bg-bg-elevated md:block",
362
- children: /* @__PURE__ */ f(Be, { children: [/* @__PURE__ */ d(He, { children: /* @__PURE__ */ f(b, { children: [
363
- /* @__PURE__ */ d(y, { children: "Name" }),
364
- /* @__PURE__ */ d(y, { children: "Type" }),
365
- /* @__PURE__ */ d(y, { children: "Unit" }),
366
- /* @__PURE__ */ d(y, { children: "Nullable" }),
367
- /* @__PURE__ */ d(y, { children: "Provenance" })
368
- ] }) }), /* @__PURE__ */ d(Ve, { children: $.map((e) => /* @__PURE__ */ f(b, { children: [
369
- /* @__PURE__ */ f(v, { children: [/* @__PURE__ */ d("span", {
389
+ children: /* @__PURE__ */ f(Be, { children: [/* @__PURE__ */ d(He, { children: /* @__PURE__ */ f(x, { children: [
390
+ /* @__PURE__ */ d(b, {
391
+ className: "w-10 text-right",
392
+ children: "#"
393
+ }),
394
+ /* @__PURE__ */ d(b, { children: "Name" }),
395
+ /* @__PURE__ */ d(b, { children: "Type" }),
396
+ /* @__PURE__ */ d(b, { children: "Unit" }),
397
+ /* @__PURE__ */ d(b, { children: "Nullable" }),
398
+ /* @__PURE__ */ d(b, { children: "Provenance" })
399
+ ] }) }), /* @__PURE__ */ d(Ve, { children: Q.map((e, t) => /* @__PURE__ */ f(x, { children: [
400
+ /* @__PURE__ */ d(y, {
401
+ className: "text-right text-xs tabular-nums text-text-tertiary",
402
+ children: t + 1
403
+ }),
404
+ /* @__PURE__ */ f(y, { children: [/* @__PURE__ */ d("span", {
370
405
  className: "font-medium text-text-primary",
371
406
  children: e.name
372
407
  }), e.description ? /* @__PURE__ */ d("p", {
373
408
  className: "mt-0.5 line-clamp-1 max-w-xs text-xs text-text-secondary",
374
409
  children: e.description
375
410
  }) : null] }),
376
- /* @__PURE__ */ d(v, { children: /* @__PURE__ */ d(m, {
411
+ /* @__PURE__ */ d(y, { children: /* @__PURE__ */ d(h, {
377
412
  variant: "secondary",
378
413
  children: l(e.fieldType)
379
414
  }) }),
380
- /* @__PURE__ */ d(v, {
415
+ /* @__PURE__ */ d(y, {
381
416
  className: "text-sm text-text-secondary",
382
- children: e.unit || "—"
417
+ children: e.unit ? e.unit : C(e) ? /* @__PURE__ */ f("span", {
418
+ className: "inline-flex items-center gap-1 text-status-warning-text",
419
+ title: `${l(e.fieldType)} fields carry a measured quantity — record the unit so consumers can interpret the values.`,
420
+ children: [/* @__PURE__ */ d(m, {
421
+ className: "size-3.5",
422
+ "aria-hidden": "true"
423
+ }), "Not set"]
424
+ }) : "—"
383
425
  }),
384
- /* @__PURE__ */ d(v, {
426
+ /* @__PURE__ */ d(y, {
385
427
  className: "text-sm text-text-secondary",
386
428
  children: e.nullable ? "Yes" : "No"
387
429
  }),
388
- /* @__PURE__ */ d(v, {
430
+ /* @__PURE__ */ d(y, {
389
431
  className: "text-sm text-text-secondary",
390
432
  children: e.provenance || "—"
391
433
  })
392
434
  ] }, e.id)) })] })
393
435
  }), /* @__PURE__ */ d("div", {
394
436
  className: "space-y-2 md:hidden",
395
- children: $.map((e) => /* @__PURE__ */ f("div", {
437
+ children: Q.map((e) => /* @__PURE__ */ f("div", {
396
438
  className: "rounded-card border border-border-default bg-bg-elevated p-3",
397
439
  children: [
398
440
  /* @__PURE__ */ f("div", {
@@ -400,7 +442,7 @@ function C() {
400
442
  children: [/* @__PURE__ */ d("span", {
401
443
  className: "font-medium text-text-primary",
402
444
  children: e.name
403
- }), /* @__PURE__ */ d(m, {
445
+ }), /* @__PURE__ */ d(h, {
404
446
  variant: "secondary",
405
447
  children: l(e.fieldType)
406
448
  })]
@@ -417,7 +459,13 @@ function C() {
417
459
  children: "Unit"
418
460
  }), /* @__PURE__ */ d("dd", {
419
461
  className: "text-text-secondary",
420
- children: e.unit || "—"
462
+ children: e.unit ? e.unit : C(e) ? /* @__PURE__ */ f("span", {
463
+ className: "inline-flex items-center gap-1 text-status-warning-text",
464
+ children: [/* @__PURE__ */ d(m, {
465
+ className: "size-3",
466
+ "aria-hidden": "true"
467
+ }), "Not set"]
468
+ }) : "—"
421
469
  })] }),
422
470
  /* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("dt", {
423
471
  className: "text-text-tertiary",
@@ -445,17 +493,17 @@ function C() {
445
493
  /* @__PURE__ */ f("section", {
446
494
  className: "space-y-3 rounded-card border border-border-default bg-bg-elevated p-5",
447
495
  children: [/* @__PURE__ */ d(ue, {
448
- value: L,
449
- onChange: R,
496
+ value: B,
497
+ onChange: V,
450
498
  label: "Dataset tags"
451
- }), nt ? /* @__PURE__ */ d("div", {
499
+ }), tt ? /* @__PURE__ */ d("div", {
452
500
  className: "flex justify-end",
453
- children: /* @__PURE__ */ d(h, {
501
+ children: /* @__PURE__ */ d(g, {
454
502
  type: "button",
455
503
  size: "sm",
456
- onClick: () => void lt(),
457
- disabled: k,
458
- children: k ? "Saving…" : "Save tags"
504
+ onClick: () => void ft(),
505
+ disabled: M,
506
+ children: M ? "Saving…" : "Save tags"
459
507
  })
460
508
  }) : null]
461
509
  }),
@@ -471,7 +519,7 @@ function C() {
471
519
  children: "Activity"
472
520
  })]
473
521
  }), /* @__PURE__ */ d(ce, {
474
- resourceId: D.id,
522
+ resourceId: k.id,
475
523
  resourceType: "cosmicintersection-dataset"
476
524
  })]
477
525
  }),
@@ -488,19 +536,19 @@ function C() {
488
536
  })]
489
537
  }), /* @__PURE__ */ d(le, {
490
538
  entityType: "cosmicintersection-dataset",
491
- entityId: D.id,
492
- title: D.name,
539
+ entityId: k.id,
540
+ title: k.name,
493
541
  widgetKey: "dataset-discussion"
494
542
  })]
495
543
  })
496
544
  ]
497
545
  }), /* @__PURE__ */ d(ke, {
498
- open: rt,
499
- onOpenChange: Q,
546
+ open: nt,
547
+ onOpenChange: Z,
500
548
  children: /* @__PURE__ */ f(Ae, { children: [
501
549
  /* @__PURE__ */ f(Ne, { children: [/* @__PURE__ */ d(Pe, { children: "Add schema field" }), /* @__PURE__ */ f(je, { children: [
502
550
  "Document a column in “",
503
- D.name,
551
+ k.name,
504
552
  "” — its type, unit and provenance."
505
553
  ] })] }),
506
554
  /* @__PURE__ */ f("div", {
@@ -508,13 +556,13 @@ function C() {
508
556
  children: [
509
557
  /* @__PURE__ */ f("div", {
510
558
  className: "space-y-1.5",
511
- children: [/* @__PURE__ */ d(_, {
559
+ children: [/* @__PURE__ */ d(v, {
512
560
  htmlFor: "cos-field-name",
513
561
  children: "Name"
514
- }), /* @__PURE__ */ d(g, {
562
+ }), /* @__PURE__ */ d(_, {
515
563
  id: "cos-field-name",
516
- value: B,
517
- onChange: (e) => V(e.target.value),
564
+ value: U,
565
+ onChange: (e) => W(e.target.value),
518
566
  placeholder: "e.g. right_ascension",
519
567
  required: !0
520
568
  })]
@@ -523,12 +571,12 @@ function C() {
523
571
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
524
572
  children: [/* @__PURE__ */ f("div", {
525
573
  className: "space-y-1.5",
526
- children: [/* @__PURE__ */ d(_, {
574
+ children: [/* @__PURE__ */ d(v, {
527
575
  htmlFor: "cos-field-type",
528
576
  children: "Type"
529
577
  }), /* @__PURE__ */ f(Fe, {
530
- value: H,
531
- onValueChange: (e) => U(e),
578
+ value: G,
579
+ onValueChange: (e) => K(e),
532
580
  children: [/* @__PURE__ */ d(Re, {
533
581
  id: "cos-field-type",
534
582
  "aria-label": "Field type",
@@ -540,67 +588,67 @@ function C() {
540
588
  })]
541
589
  }), /* @__PURE__ */ f("div", {
542
590
  className: "space-y-1.5",
543
- children: [/* @__PURE__ */ d(_, {
591
+ children: [/* @__PURE__ */ d(v, {
544
592
  htmlFor: "cos-field-unit",
545
593
  children: "Unit"
546
- }), /* @__PURE__ */ d(g, {
594
+ }), /* @__PURE__ */ d(_, {
547
595
  id: "cos-field-unit",
548
- value: W,
549
- onChange: (e) => G(e.target.value),
596
+ value: q,
597
+ onChange: (e) => J(e.target.value),
550
598
  placeholder: "e.g. deg, mag, Jy"
551
599
  })]
552
600
  })]
553
601
  }),
554
602
  /* @__PURE__ */ f("div", {
555
603
  className: "space-y-1.5",
556
- children: [/* @__PURE__ */ d(_, {
604
+ children: [/* @__PURE__ */ d(v, {
557
605
  htmlFor: "cos-field-desc",
558
606
  children: "Description"
559
607
  }), /* @__PURE__ */ d(Ue, {
560
608
  id: "cos-field-desc",
561
- value: K,
562
- onChange: (e) => q(e.target.value),
609
+ value: Y,
610
+ onChange: (e) => it(e.target.value),
563
611
  rows: 2
564
612
  })]
565
613
  }),
566
614
  /* @__PURE__ */ f("div", {
567
615
  className: "space-y-1.5",
568
- children: [/* @__PURE__ */ d(_, {
616
+ children: [/* @__PURE__ */ d(v, {
569
617
  htmlFor: "cos-field-prov",
570
618
  children: "Provenance"
571
- }), /* @__PURE__ */ d(g, {
619
+ }), /* @__PURE__ */ d(_, {
572
620
  id: "cos-field-prov",
573
- value: J,
574
- onChange: (e) => Y(e.target.value),
621
+ value: X,
622
+ onChange: (e) => at(e.target.value),
575
623
  placeholder: "Where this field comes from"
576
624
  })]
577
625
  }),
578
626
  /* @__PURE__ */ f("label", {
579
627
  className: "flex items-center gap-2 text-sm text-text-primary",
580
628
  children: [/* @__PURE__ */ d(Oe, {
581
- checked: X,
582
- onCheckedChange: (e) => Z(e === !0)
629
+ checked: ot,
630
+ onCheckedChange: (e) => st(e === !0)
583
631
  }), "Nullable (may contain empty values)"]
584
632
  })
585
633
  ]
586
634
  }),
587
- /* @__PURE__ */ f(Me, { children: [/* @__PURE__ */ d(h, {
635
+ /* @__PURE__ */ f(Me, { children: [/* @__PURE__ */ d(g, {
588
636
  type: "button",
589
637
  variant: "outline",
590
- onClick: () => Q(!1),
591
- disabled: A,
638
+ onClick: () => Z(!1),
639
+ disabled: N,
592
640
  children: "Cancel"
593
- }), /* @__PURE__ */ d(h, {
641
+ }), /* @__PURE__ */ d(g, {
594
642
  type: "button",
595
- onClick: () => void ut(),
596
- disabled: A,
597
- children: A ? "Adding…" : "Add field"
643
+ onClick: () => void pt(),
644
+ disabled: N,
645
+ children: N ? "Adding…" : "Add field"
598
646
  })] })
599
647
  ] })
600
648
  })]
601
649
  });
602
650
  }
603
651
  //#endregion
604
- export { C as default };
652
+ export { E as default };
605
653
 
606
654
  //# sourceMappingURL=DatasetDetailPage.js.map