@flanksource/clicky-ui 0.2.9 → 0.2.11

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 (105) hide show
  1. package/dist/components/Combobox.cjs +4 -1
  2. package/dist/components/Combobox.cjs.map +1 -1
  3. package/dist/components/Combobox.d.ts +6 -0
  4. package/dist/components/Combobox.d.ts.map +1 -1
  5. package/dist/components/Combobox.js +4 -1
  6. package/dist/components/Combobox.js.map +1 -1
  7. package/dist/components/JsonSchemaForm.cjs +24 -5
  8. package/dist/components/JsonSchemaForm.cjs.map +1 -1
  9. package/dist/components/JsonSchemaForm.d.ts +1 -1
  10. package/dist/components/JsonSchemaForm.d.ts.map +1 -1
  11. package/dist/components/JsonSchemaForm.js +24 -5
  12. package/dist/components/JsonSchemaForm.js.map +1 -1
  13. package/dist/components/json-schema-form-array.cjs +117 -37
  14. package/dist/components/json-schema-form-array.cjs.map +1 -1
  15. package/dist/components/json-schema-form-array.d.ts.map +1 -1
  16. package/dist/components/json-schema-form-array.js +118 -38
  17. package/dist/components/json-schema-form-array.js.map +1 -1
  18. package/dist/components/json-schema-form-fields.cjs +121 -51
  19. package/dist/components/json-schema-form-fields.cjs.map +1 -1
  20. package/dist/components/json-schema-form-fields.d.ts +9 -6
  21. package/dist/components/json-schema-form-fields.d.ts.map +1 -1
  22. package/dist/components/json-schema-form-fields.js +121 -51
  23. package/dist/components/json-schema-form-fields.js.map +1 -1
  24. package/dist/components/json-schema-form-render.cjs +15 -8
  25. package/dist/components/json-schema-form-render.cjs.map +1 -1
  26. package/dist/components/json-schema-form-render.d.ts +5 -2
  27. package/dist/components/json-schema-form-render.d.ts.map +1 -1
  28. package/dist/components/json-schema-form-render.js +15 -8
  29. package/dist/components/json-schema-form-render.js.map +1 -1
  30. package/dist/components/json-schema-form-resolve.cjs +41 -6
  31. package/dist/components/json-schema-form-resolve.cjs.map +1 -1
  32. package/dist/components/json-schema-form-resolve.d.ts.map +1 -1
  33. package/dist/components/json-schema-form-resolve.js +41 -6
  34. package/dist/components/json-schema-form-resolve.js.map +1 -1
  35. package/dist/components/json-schema-form-size.cjs +61 -0
  36. package/dist/components/json-schema-form-size.cjs.map +1 -0
  37. package/dist/components/json-schema-form-size.d.ts +11 -0
  38. package/dist/components/json-schema-form-size.d.ts.map +1 -0
  39. package/dist/components/json-schema-form-size.js +61 -0
  40. package/dist/components/json-schema-form-size.js.map +1 -0
  41. package/dist/components/json-schema-form-types.d.ts +36 -1
  42. package/dist/components/json-schema-form-types.d.ts.map +1 -1
  43. package/dist/components.cjs +2 -0
  44. package/dist/components.cjs.map +1 -1
  45. package/dist/components.d.ts +3 -1
  46. package/dist/components.d.ts.map +1 -1
  47. package/dist/components.js +2 -0
  48. package/dist/components.js.map +1 -1
  49. package/dist/data/Clicky.cjs +412 -90
  50. package/dist/data/Clicky.cjs.map +1 -1
  51. package/dist/data/Clicky.d.ts +4 -2
  52. package/dist/data/Clicky.d.ts.map +1 -1
  53. package/dist/data/Clicky.js +413 -91
  54. package/dist/data/Clicky.js.map +1 -1
  55. package/dist/data/DataTable.cjs +534 -293
  56. package/dist/data/DataTable.cjs.map +1 -1
  57. package/dist/data/DataTable.d.ts +12 -0
  58. package/dist/data/DataTable.d.ts.map +1 -1
  59. package/dist/data/DataTable.js +534 -293
  60. package/dist/data/DataTable.js.map +1 -1
  61. package/dist/data.d.ts +1 -1
  62. package/dist/data.d.ts.map +1 -1
  63. package/dist/index.cjs +2 -0
  64. package/dist/index.cjs.map +1 -1
  65. package/dist/index.js +2 -0
  66. package/dist/index.js.map +1 -1
  67. package/dist/rpc/CommandOutput.cjs +101 -20
  68. package/dist/rpc/CommandOutput.cjs.map +1 -1
  69. package/dist/rpc/CommandOutput.d.ts +12 -4
  70. package/dist/rpc/CommandOutput.d.ts.map +1 -1
  71. package/dist/rpc/CommandOutput.js +102 -21
  72. package/dist/rpc/CommandOutput.js.map +1 -1
  73. package/dist/rpc/ExecutionResult.cjs +4 -76
  74. package/dist/rpc/ExecutionResult.cjs.map +1 -1
  75. package/dist/rpc/ExecutionResult.d.ts +3 -22
  76. package/dist/rpc/ExecutionResult.d.ts.map +1 -1
  77. package/dist/rpc/ExecutionResult.js +4 -76
  78. package/dist/rpc/ExecutionResult.js.map +1 -1
  79. package/dist/rpc/OperationCatalog.cjs +22 -13
  80. package/dist/rpc/OperationCatalog.cjs.map +1 -1
  81. package/dist/rpc/OperationCatalog.d.ts.map +1 -1
  82. package/dist/rpc/OperationCatalog.js +24 -15
  83. package/dist/rpc/OperationCatalog.js.map +1 -1
  84. package/dist/rpc/OperationCommandPage.cjs +10 -20
  85. package/dist/rpc/OperationCommandPage.cjs.map +1 -1
  86. package/dist/rpc/OperationCommandPage.d.ts.map +1 -1
  87. package/dist/rpc/OperationCommandPage.js +11 -21
  88. package/dist/rpc/OperationCommandPage.js.map +1 -1
  89. package/dist/rpc/apiClient.cjs +18 -0
  90. package/dist/rpc/apiClient.cjs.map +1 -1
  91. package/dist/rpc/apiClient.d.ts.map +1 -1
  92. package/dist/rpc/apiClient.js +18 -0
  93. package/dist/rpc/apiClient.js.map +1 -1
  94. package/dist/rpc/formMetadata.cjs +31 -0
  95. package/dist/rpc/formMetadata.cjs.map +1 -1
  96. package/dist/rpc/formMetadata.d.ts +3 -1
  97. package/dist/rpc/formMetadata.d.ts.map +1 -1
  98. package/dist/rpc/formMetadata.js +31 -0
  99. package/dist/rpc/formMetadata.js.map +1 -1
  100. package/dist/rpc/types.cjs.map +1 -1
  101. package/dist/rpc/types.d.ts +7 -0
  102. package/dist/rpc/types.d.ts.map +1 -1
  103. package/dist/rpc/types.js.map +1 -1
  104. package/dist/styles.css +1 -1
  105. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import { QueryClient, QueryClientProvider, useQuery } from "@tanstack/react-query";
3
- import { useState, useContext, useMemo, useEffect, Fragment as Fragment$1, createContext, useRef } from "react";
3
+ import { useState, useMemo, useContext, useEffect, Fragment as Fragment$1, createContext, useRef } from "react";
4
4
  import { FilterForm } from "../rpc/FilterForm.js";
5
5
  import { parseJsonBody } from "../rpc/classify.js";
6
6
  import { packParameterValues, pruneParameterValues } from "../rpc/formMetadata.js";
@@ -25,6 +25,10 @@ import { UiChevronDown } from "../icons/components/UiChevronDown.js";
25
25
  import { UiComment } from "../icons/components/UiComment.js";
26
26
  import { UiTable } from "../icons/components/UiTable.js";
27
27
  import { UiFileCode } from "../icons/components/UiFileCode.js";
28
+ import { UiFileSpreadsheet } from "../icons/components/UiFileSpreadsheet.js";
29
+ import { UiMarkdown } from "../icons/components/UiMarkdown.js";
30
+ import { UiFileText } from "../icons/components/UiFileText.js";
31
+ import { UiJson } from "../icons/components/UiJson.js";
28
32
  import { UiEye } from "../icons/components/UiEye.js";
29
33
  const CLICKY_PRIMARY_VIEW_FORMATS = ["clicky", "json"];
30
34
  const CLICKY_OVERFLOW_VIEW_FORMATS = [
@@ -37,12 +41,20 @@ const CLICKY_OVERFLOW_VIEW_FORMATS = [
37
41
  "excel",
38
42
  "slack"
39
43
  ];
40
- const CLICKY_DOWNLOAD_FORMATS = ["json", "clicky", ...CLICKY_OVERFLOW_VIEW_FORMATS];
44
+ const CLICKY_DOWNLOAD_FORMATS = [
45
+ "yaml",
46
+ "json",
47
+ "csv",
48
+ "pdf",
49
+ "markdown"
50
+ ];
41
51
  const clickyRuntimeContextDefault = {
42
52
  operations: [],
43
53
  operationsLoading: false
44
54
  };
45
- const ClickyRuntimeContext = createContext(clickyRuntimeContextDefault);
55
+ const ClickyRuntimeContext = createContext(
56
+ clickyRuntimeContextDefault
57
+ );
46
58
  function Clicky(props) {
47
59
  const [queryClient] = useState(
48
60
  () => new QueryClient({
@@ -54,6 +66,10 @@ function Clicky(props) {
54
66
  }
55
67
  })
56
68
  );
69
+ const tableMenuActions = useMemo(
70
+ () => getDownloadMenuActions({ url: props.url, download: props.download }),
71
+ [props.download, props.url]
72
+ );
57
73
  const content = /* @__PURE__ */ jsx(
58
74
  ClickyRuntimeProvider,
59
75
  {
@@ -65,6 +81,7 @@ function Clicky(props) {
65
81
  ...props.timeRange ? { tableTimeRange: props.timeRange } : {},
66
82
  ...props.externalFilters ? { tableExternalFilters: props.externalFilters } : {},
67
83
  ...props.pagination ? { tablePagination: props.pagination } : {},
84
+ ...tableMenuActions.length > 0 ? { tableMenuActions } : {},
68
85
  children: props.url ? /* @__PURE__ */ jsx(ClickyRemoteRenderer, { ...props, url: props.url }) : /* @__PURE__ */ jsx(
69
86
  ClickyContent,
70
87
  {
@@ -88,10 +105,11 @@ function ClickyRuntimeProvider({
88
105
  tableTimeRange,
89
106
  tableExternalFilters,
90
107
  tablePagination,
108
+ tableMenuActions,
91
109
  children
92
110
  }) {
93
111
  if (!commandRuntime) {
94
- const hasOverrides = onTableRowClick || getTableRowHref || isTableRowClickable || tableSearch || tableTimeRange || tableExternalFilters || tablePagination;
112
+ const hasOverrides = onTableRowClick || getTableRowHref || isTableRowClickable || tableSearch || tableTimeRange || tableExternalFilters || tablePagination || tableMenuActions;
95
113
  return /* @__PURE__ */ jsx(
96
114
  ClickyRuntimeContext.Provider,
97
115
  {
@@ -103,7 +121,8 @@ function ClickyRuntimeProvider({
103
121
  tableSearch,
104
122
  tableTimeRange,
105
123
  tableExternalFilters,
106
- tablePagination
124
+ tablePagination,
125
+ tableMenuActions
107
126
  } : clickyRuntimeContextDefault,
108
127
  children
109
128
  }
@@ -120,6 +139,7 @@ function ClickyRuntimeProvider({
120
139
  ...tableTimeRange ? { tableTimeRange } : {},
121
140
  ...tableExternalFilters ? { tableExternalFilters } : {},
122
141
  ...tablePagination ? { tablePagination } : {},
142
+ ...tableMenuActions ? { tableMenuActions } : {},
123
143
  children
124
144
  }
125
145
  );
@@ -133,6 +153,7 @@ function ClickyCommandRuntimeProvider({
133
153
  tableTimeRange,
134
154
  tableExternalFilters,
135
155
  tablePagination,
156
+ tableMenuActions,
136
157
  children
137
158
  }) {
138
159
  const { operations, isLoading } = useOperations(commandRuntime.client);
@@ -146,6 +167,7 @@ function ClickyCommandRuntimeProvider({
146
167
  tableTimeRange,
147
168
  tableExternalFilters,
148
169
  tablePagination,
170
+ tableMenuActions,
149
171
  operations,
150
172
  operationsLoading: isLoading
151
173
  }),
@@ -159,7 +181,8 @@ function ClickyCommandRuntimeProvider({
159
181
  tableSearch,
160
182
  tableTimeRange,
161
183
  tableExternalFilters,
162
- tablePagination
184
+ tablePagination,
185
+ tableMenuActions
163
186
  ]
164
187
  );
165
188
  return /* @__PURE__ */ jsx(ClickyRuntimeContext.Provider, { value, children });
@@ -192,13 +215,22 @@ function ClickyRemoteRenderer({
192
215
  className
193
216
  }) {
194
217
  var _a, _b;
195
- const availableViews = useMemo(() => getAvailableViews({ data, url, view }), [data, url, view]);
196
- const primaryViews = useMemo(() => availableViews.filter(isPrimaryViewFormat), [availableViews]);
218
+ const availableViews = useMemo(
219
+ () => getAvailableViews({ data, url, view }),
220
+ [data, url, view]
221
+ );
222
+ const primaryViews = useMemo(
223
+ () => availableViews.filter(isPrimaryViewFormat),
224
+ [availableViews]
225
+ );
197
226
  const overflowViews = useMemo(
198
227
  () => availableViews.filter(isOverflowViewFormat),
199
228
  [availableViews]
200
229
  );
201
- const downloadFormats = useMemo(() => getDownloadFormats({ url, download }), [download, url]);
230
+ const downloadFormats = useMemo(
231
+ () => getDownloadFormats({ url, download }),
232
+ [download, url]
233
+ );
202
234
  const [activeView, setActiveView] = useState(
203
235
  () => availableViews[0] ?? "clicky"
204
236
  );
@@ -217,25 +249,34 @@ function ClickyRemoteRenderer({
217
249
  const fallbackJsonData = useMemo(() => parseJsonValue(data), [data]);
218
250
  const effectiveJsonData = activeView === "json" && ((_b = activeQuery.data) == null ? void 0 : _b.kind) === "text" ? parseJsonValue(activeQuery.data.text) : fallbackJsonData;
219
251
  const activeOverflowView = isOverflowViewFormat(activeView) ? activeView : null;
220
- const canDownload = downloadFormats.length > 0;
252
+ const downloadHandledByTable = clickyPayloadHasTable(effectiveClickyData);
253
+ const canDownload = downloadFormats.length > 0 && !downloadHandledByTable;
221
254
  const loadingMessage = `Fetching ${formattedUrl}`;
222
255
  return /* @__PURE__ */ jsxs("div", { className: cn("space-y-density-3", className), children: [
223
256
  /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 rounded-md border border-border bg-muted/20 px-density-3 py-density-2", children: [
224
- primaryViews.length > 1 && /* @__PURE__ */ jsx("div", { role: "radiogroup", "aria-label": "Clicky view mode", className: "flex flex-wrap gap-1", children: primaryViews.map((mode) => /* @__PURE__ */ jsx(
225
- "button",
257
+ primaryViews.length > 1 && /* @__PURE__ */ jsx(
258
+ "div",
226
259
  {
227
- type: "button",
228
- role: "radio",
229
- "aria-checked": activeView === mode,
230
- onClick: () => setActiveView(mode),
231
- className: cn(
232
- "rounded-md border px-2.5 py-1 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
233
- activeView === mode ? "border-foreground/20 bg-accent text-foreground" : "border-transparent text-muted-foreground hover:border-foreground/20 hover:text-foreground"
234
- ),
235
- children: formatViewLabel(mode)
236
- },
237
- mode
238
- )) }),
260
+ role: "radiogroup",
261
+ "aria-label": "Clicky view mode",
262
+ className: "flex flex-wrap gap-1",
263
+ children: primaryViews.map((mode) => /* @__PURE__ */ jsx(
264
+ "button",
265
+ {
266
+ type: "button",
267
+ role: "radio",
268
+ "aria-checked": activeView === mode,
269
+ onClick: () => setActiveView(mode),
270
+ className: cn(
271
+ "rounded-md border px-2.5 py-1 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
272
+ activeView === mode ? "border-foreground/20 bg-accent text-foreground" : "border-transparent text-muted-foreground hover:border-foreground/20 hover:text-foreground"
273
+ ),
274
+ children: formatViewLabel(mode)
275
+ },
276
+ mode
277
+ ))
278
+ }
279
+ ),
239
280
  overflowViews.length > 0 && /* @__PURE__ */ jsx(
240
281
  ClickyViewMenu,
241
282
  {
@@ -246,7 +287,14 @@ function ClickyRemoteRenderer({
246
287
  ),
247
288
  /* @__PURE__ */ jsxs("div", { className: "ml-auto flex items-center gap-2", children: [
248
289
  shouldFetchRemoteView(activeView) && activeQuery.isFetching && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "Refreshing…" }),
249
- canDownload && /* @__PURE__ */ jsx(ClickyDownloadMenu, { url, formats: downloadFormats, label: download == null ? void 0 : download.label })
290
+ canDownload && /* @__PURE__ */ jsx(
291
+ ClickyDownloadMenu,
292
+ {
293
+ url,
294
+ formats: downloadFormats,
295
+ label: download == null ? void 0 : download.label
296
+ }
297
+ )
250
298
  ] })
251
299
  ] }),
252
300
  activeView === "pdf" ? /* @__PURE__ */ jsx(ClickyPdfPreview, { src: formattedUrl }) : activeView === "html" ? /* @__PURE__ */ jsx(ClickyHtmlPreview, { src: formattedUrl }) : activeView === "excel" ? /* @__PURE__ */ jsx(
@@ -290,7 +338,13 @@ function ClickyRemoteRenderer({
290
338
  }
291
339
  ),
292
340
  /* @__PURE__ */ jsx(ClickyJsonTree, { value: effectiveJsonData })
293
- ] }) : activeQuery.isPending ? /* @__PURE__ */ jsx(ClickyNotice, { title: `Loading ${formatViewLabel(activeView)}`, message: loadingMessage }) : activeQuery.isError ? /* @__PURE__ */ jsx(
341
+ ] }) : activeQuery.isPending ? /* @__PURE__ */ jsx(
342
+ ClickyNotice,
343
+ {
344
+ title: `Loading ${formatViewLabel(activeView)}`,
345
+ message: loadingMessage
346
+ }
347
+ ) : activeQuery.isError ? /* @__PURE__ */ jsx(
294
348
  ClickyNotice,
295
349
  {
296
350
  title: `${formatViewLabel(activeView)} request failed`,
@@ -355,15 +409,22 @@ function ClickyViewMenu({
355
409
  {
356
410
  icon: meta.icon,
357
411
  className: cn(
358
- "mt-0.5 shrink-0 text-base text-muted-foreground",
359
- active && "text-foreground"
412
+ "mt-0.5 shrink-0 text-base",
413
+ meta.iconClassName ?? "text-muted-foreground",
414
+ active && !meta.iconClassName && "text-foreground"
360
415
  )
361
416
  }
362
417
  ),
363
418
  /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
364
419
  /* @__PURE__ */ jsxs("span", { className: "flex items-center justify-between gap-3", children: [
365
420
  /* @__PURE__ */ jsx("span", { className: "font-medium", children: meta.label }),
366
- active && /* @__PURE__ */ jsx(Icon, { icon: UiCheck, className: "text-xs text-muted-foreground" })
421
+ active && /* @__PURE__ */ jsx(
422
+ Icon,
423
+ {
424
+ icon: UiCheck,
425
+ className: "text-xs text-muted-foreground"
426
+ }
427
+ )
367
428
  ] }),
368
429
  /* @__PURE__ */ jsx("span", { className: "mt-0.5 block text-xs text-muted-foreground", children: meta.description })
369
430
  ] })
@@ -395,7 +456,7 @@ function ClickyDownloadMenu({
395
456
  type: "button",
396
457
  "aria-label": label ? `Download ${primaryMeta.label} ${label}` : `Download ${primaryMeta.label}`,
397
458
  className: "inline-flex items-center gap-2 rounded-md border border-input bg-background px-3 py-1.5 text-xs font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
398
- onClick: () => submitDownloadRequest(buildFormatUrl(url, primaryFormat)),
459
+ onClick: () => triggerDownload(buildDownloadUrl(url, primaryFormat, label)),
399
460
  children: [
400
461
  /* @__PURE__ */ jsx(Icon, { icon: UiCloudDownload, className: "text-sm" }),
401
462
  /* @__PURE__ */ jsx("span", { children: `Download ${primaryMeta.label}` })
@@ -429,10 +490,10 @@ function ClickyDownloadMenu({
429
490
  type: "button",
430
491
  role: "menuitem",
431
492
  className: cn(
432
- "flex w-full items-start gap-3 rounded-md px-3 py-2 text-left text-sm transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:outline-none"
493
+ "flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:outline-none"
433
494
  ),
434
495
  onClick: () => {
435
- submitDownloadRequest(buildFormatUrl(url, format));
496
+ triggerDownload(buildDownloadUrl(url, format, label));
436
497
  setOpen(false);
437
498
  },
438
499
  children: [
@@ -440,13 +501,13 @@ function ClickyDownloadMenu({
440
501
  Icon,
441
502
  {
442
503
  icon: meta.icon,
443
- className: "mt-0.5 shrink-0 text-base text-muted-foreground"
504
+ className: cn(
505
+ "shrink-0 text-sm",
506
+ meta.iconClassName ?? "text-muted-foreground"
507
+ )
444
508
  }
445
509
  ),
446
- /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
447
- /* @__PURE__ */ jsx("span", { className: "font-medium", children: meta.label }),
448
- /* @__PURE__ */ jsx("span", { className: "mt-0.5 block text-xs text-muted-foreground", children: meta.description })
449
- ] })
510
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx("span", { className: "font-medium", children: meta.label }) })
450
511
  ]
451
512
  },
452
513
  format
@@ -501,7 +562,9 @@ function fetchRemoteFormat(url, format) {
501
562
  }
502
563
  }).then(async (response) => {
503
564
  if (!response.ok) {
504
- throw new Error(`Request failed with ${response.status} ${response.statusText}`.trim());
565
+ throw new Error(
566
+ `Request failed with ${response.status} ${response.statusText}`.trim()
567
+ );
505
568
  }
506
569
  const contentType = response.headers.get("Content-Type") ?? "";
507
570
  if (format === "excel") {
@@ -578,16 +641,41 @@ function ClickyPdfPreview({ src }) {
578
641
  return /* @__PURE__ */ jsxs("div", { className: "overflow-hidden rounded-md border border-border bg-background", children: [
579
642
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b border-border px-3 py-2 text-xs text-muted-foreground", children: [
580
643
  /* @__PURE__ */ jsx("span", { children: "PDF preview" }),
581
- /* @__PURE__ */ jsx("a", { href: src, target: "_blank", rel: "noreferrer", className: "text-primary hover:underline", children: "Open in new tab" })
644
+ /* @__PURE__ */ jsx(
645
+ "a",
646
+ {
647
+ href: src,
648
+ target: "_blank",
649
+ rel: "noreferrer",
650
+ className: "text-primary hover:underline",
651
+ children: "Open in new tab"
652
+ }
653
+ )
582
654
  ] }),
583
- /* @__PURE__ */ jsx("iframe", { title: "Clicky PDF preview", src, className: "h-[720px] w-full bg-white" })
655
+ /* @__PURE__ */ jsx(
656
+ "iframe",
657
+ {
658
+ title: "Clicky PDF preview",
659
+ src,
660
+ className: "h-[720px] w-full bg-white"
661
+ }
662
+ )
584
663
  ] });
585
664
  }
586
665
  function ClickyHtmlPreview({ src }) {
587
666
  return /* @__PURE__ */ jsxs("div", { className: "overflow-hidden rounded-md border border-border bg-background", children: [
588
667
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b border-border px-3 py-2 text-xs text-muted-foreground", children: [
589
668
  /* @__PURE__ */ jsx("span", { children: "HTML preview" }),
590
- /* @__PURE__ */ jsx("a", { href: src, target: "_blank", rel: "noreferrer", className: "text-primary hover:underline", children: "Open in new tab" })
669
+ /* @__PURE__ */ jsx(
670
+ "a",
671
+ {
672
+ href: src,
673
+ target: "_blank",
674
+ rel: "noreferrer",
675
+ className: "text-primary hover:underline",
676
+ children: "Open in new tab"
677
+ }
678
+ )
591
679
  ] }),
592
680
  /* @__PURE__ */ jsx(
593
681
  "iframe",
@@ -614,7 +702,16 @@ function ClickyUnsupportedPreview({
614
702
  message,
615
703
  " "
616
704
  ] }),
617
- /* @__PURE__ */ jsx("a", { href, target: "_blank", rel: "noreferrer", className: "text-primary hover:underline", children: "Open format" })
705
+ /* @__PURE__ */ jsx(
706
+ "a",
707
+ {
708
+ href,
709
+ target: "_blank",
710
+ rel: "noreferrer",
711
+ className: "text-primary hover:underline",
712
+ children: "Open format"
713
+ }
714
+ )
618
715
  ] })
619
716
  }
620
717
  );
@@ -636,7 +733,10 @@ function ClickyRemotePreview({
636
733
  }
637
734
  );
638
735
  }
639
- function ClickyTextPreview({ title, content }) {
736
+ function ClickyTextPreview({
737
+ title,
738
+ content
739
+ }) {
640
740
  return /* @__PURE__ */ jsxs("div", { className: "overflow-hidden rounded-md border border-border bg-background", children: [
641
741
  /* @__PURE__ */ jsx("div", { className: "border-b border-border px-3 py-2 text-xs text-muted-foreground", children: title }),
642
742
  /* @__PURE__ */ jsx(
@@ -649,7 +749,10 @@ function ClickyTextPreview({ title, content }) {
649
749
  )
650
750
  ] });
651
751
  }
652
- function ClickyJsonTree({ value, emptyLabel = "JSON" }) {
752
+ function ClickyJsonTree({
753
+ value,
754
+ emptyLabel = "JSON"
755
+ }) {
653
756
  const roots = useMemo(() => buildJsonTree(value), [value]);
654
757
  if (value === void 0) {
655
758
  return /* @__PURE__ */ jsx(
@@ -727,6 +830,23 @@ function getDownloadFormats({
727
830
  }
728
831
  return [...CLICKY_DOWNLOAD_FORMATS];
729
832
  }
833
+ function getDownloadMenuActions({
834
+ url,
835
+ download
836
+ }) {
837
+ const formats = getDownloadFormats({ url, download });
838
+ if (!url || formats.length === 0) return [];
839
+ return formats.map((format) => {
840
+ const meta = getRemoteFormatMeta(format);
841
+ return {
842
+ id: `download-${format}`,
843
+ label: meta.label,
844
+ icon: meta.icon,
845
+ ...meta.iconClassName ? { iconClassName: meta.iconClassName } : {},
846
+ onSelect: () => triggerDownload(buildDownloadUrl(url, format, download == null ? void 0 : download.label))
847
+ };
848
+ });
849
+ }
730
850
  function getRemoteFormatMeta(format) {
731
851
  switch (format) {
732
852
  case "clicky":
@@ -740,14 +860,15 @@ function getRemoteFormatMeta(format) {
740
860
  return {
741
861
  label: "JSON",
742
862
  description: "Plain JSON for inspecting the raw response body",
743
- icon: UiFileCode,
863
+ icon: UiJson,
744
864
  accept: "application/json, text/plain;q=0.8,*/*;q=0.7"
745
865
  };
746
866
  case "pdf":
747
867
  return {
748
868
  label: "PDF",
749
869
  description: "Portable document for sharing and printing",
750
- icon: UiFileCode,
870
+ icon: UiFileText,
871
+ iconClassName: "text-rose-600 dark:text-rose-400",
751
872
  accept: "application/pdf, */*;q=0.7"
752
873
  };
753
874
  case "html":
@@ -761,7 +882,7 @@ function getRemoteFormatMeta(format) {
761
882
  return {
762
883
  label: "Markdown",
763
884
  description: "Markdown formatted for docs, comments, and chat",
764
- icon: UiFileCode,
885
+ icon: UiMarkdown,
765
886
  accept: "text/markdown, text/plain;q=0.8,*/*;q=0.7"
766
887
  };
767
888
  case "yaml":
@@ -769,13 +890,15 @@ function getRemoteFormatMeta(format) {
769
890
  label: "YAML",
770
891
  description: "YAML for config-friendly inspection and export",
771
892
  icon: UiFileCode,
893
+ iconClassName: "text-violet-600 dark:text-violet-400",
772
894
  accept: "application/yaml, text/yaml;q=0.9, text/plain;q=0.8,*/*;q=0.7"
773
895
  };
774
896
  case "csv":
775
897
  return {
776
898
  label: "CSV",
777
899
  description: "Comma-separated values for spreadsheets and imports",
778
- icon: UiTable,
900
+ icon: UiFileSpreadsheet,
901
+ iconClassName: "text-emerald-600 dark:text-emerald-400",
779
902
  accept: "text/csv, text/plain;q=0.8,*/*;q=0.7"
780
903
  };
781
904
  case "pretty":
@@ -807,12 +930,66 @@ function formatViewLabel(mode) {
807
930
  function buildFormatUrl(url, format) {
808
931
  const base = typeof window === "undefined" ? "http://localhost" : window.location.origin;
809
932
  const resolved = new URL(url, base);
810
- resolved.searchParams.set("format", format === "clicky" ? "clicky-json" : format);
933
+ resolved.searchParams.set(
934
+ "format",
935
+ format === "clicky" ? "clicky-json" : format
936
+ );
811
937
  if (isAbsoluteUrl(url)) {
812
938
  return resolved.toString();
813
939
  }
814
940
  return `${resolved.pathname}${resolved.search}${resolved.hash}`;
815
941
  }
942
+ function buildDownloadUrl(url, format, label) {
943
+ const formatted = buildFormatUrl(url, format);
944
+ const base = typeof window === "undefined" ? "http://localhost" : window.location.origin;
945
+ const resolved = new URL(formatted, base);
946
+ resolved.searchParams.set("filename", downloadFilename(url, format, label));
947
+ resolved.searchParams.set("_download", Date.now().toString());
948
+ if (isAbsoluteUrl(formatted)) {
949
+ return resolved.toString();
950
+ }
951
+ return `${resolved.pathname}${resolved.search}${resolved.hash}`;
952
+ }
953
+ function downloadFilename(url, format, label) {
954
+ const stem = sanitizeFilenameStem(
955
+ label || filenameStemFromUrl(url) || "clicky-output"
956
+ );
957
+ return `${stem}${downloadExtension(format)}`;
958
+ }
959
+ function filenameStemFromUrl(url) {
960
+ const base = typeof window === "undefined" ? "http://localhost" : window.location.origin;
961
+ const resolved = new URL(url, base);
962
+ const segment = resolved.pathname.split("/").filter(Boolean).at(-1);
963
+ return segment ?? "";
964
+ }
965
+ function sanitizeFilenameStem(value) {
966
+ const cleaned = value.trim().replace(/\.[a-z0-9]+$/i, "").replace(/[^a-z0-9._-]+/gi, "-").replace(/-+/g, "-").replace(/^[._-]+|[._-]+$/g, "");
967
+ return cleaned || "clicky-output";
968
+ }
969
+ function downloadExtension(format) {
970
+ switch (format) {
971
+ case "clicky":
972
+ return ".clicky.json";
973
+ case "json":
974
+ return ".json";
975
+ case "pdf":
976
+ return ".pdf";
977
+ case "html":
978
+ return ".html";
979
+ case "markdown":
980
+ return ".md";
981
+ case "yaml":
982
+ return ".yaml";
983
+ case "csv":
984
+ return ".csv";
985
+ case "pretty":
986
+ return ".txt";
987
+ case "excel":
988
+ return ".xlsx";
989
+ case "slack":
990
+ return ".slack.json";
991
+ }
992
+ }
816
993
  function shouldFetchRemoteView(format) {
817
994
  return format !== "pdf" && format !== "html" && format !== "excel";
818
995
  }
@@ -861,12 +1038,36 @@ function parseJsonValue(data) {
861
1038
  return data;
862
1039
  }
863
1040
  }
1041
+ function clickyPayloadHasTable(data) {
1042
+ if (data === void 0) return false;
1043
+ const parsed = parseClickyData(data);
1044
+ return parsed.ok ? clickyNodeHasTable(parsed.document.node) : false;
1045
+ }
1046
+ function clickyNodeHasTable(node) {
1047
+ var _a, _b, _c, _d;
1048
+ if (!node) return false;
1049
+ if (node.kind === "table") return true;
1050
+ if ((_a = node.children) == null ? void 0 : _a.some(clickyNodeHasTable)) return true;
1051
+ if ((_b = node.items) == null ? void 0 : _b.some(clickyNodeHasTable)) return true;
1052
+ if ((_c = node.fields) == null ? void 0 : _c.some((field) => clickyNodeHasTable(field.value)))
1053
+ return true;
1054
+ if (node.label && clickyNodeHasTable(node.label)) return true;
1055
+ if (node.content && clickyNodeHasTable(node.content)) return true;
1056
+ if (node.tooltip && clickyNodeHasTable(node.tooltip)) return true;
1057
+ if ((_d = node.rows) == null ? void 0 : _d.some((row) => row.detail && clickyNodeHasTable(row.detail)))
1058
+ return true;
1059
+ return false;
1060
+ }
864
1061
  function buildJsonTree(value) {
865
1062
  if (Array.isArray(value)) {
866
- return value.map((entry, index) => buildJsonTreeNode(String(index), entry, `$[${index}]`));
1063
+ return value.map(
1064
+ (entry, index) => buildJsonTreeNode(String(index), entry, `$[${index}]`)
1065
+ );
867
1066
  }
868
1067
  if (isPlainObject(value)) {
869
- return Object.entries(value).map(([key, entry]) => buildJsonTreeNode(key, entry, `$.${key}`));
1068
+ return Object.entries(value).map(
1069
+ ([key, entry]) => buildJsonTreeNode(key, entry, `$.${key}`)
1070
+ );
870
1071
  }
871
1072
  if (value === void 0) {
872
1073
  return [];
@@ -915,15 +1116,23 @@ function summarizeJsonValue(value) {
915
1116
  function isPlainObject(value) {
916
1117
  return value != null && typeof value === "object" && !Array.isArray(value);
917
1118
  }
918
- function submitDownloadRequest(url) {
1119
+ const CLICKY_DOWNLOAD_FRAME_ID = "clicky-download-frame";
1120
+ function triggerDownload(url) {
919
1121
  if (typeof document === "undefined") return;
920
- const form = document.createElement("form");
921
- form.method = "GET";
922
- form.action = url;
923
- form.style.display = "none";
924
- document.body.appendChild(form);
925
- form.submit();
926
- document.body.removeChild(form);
1122
+ let frame = document.getElementById(
1123
+ CLICKY_DOWNLOAD_FRAME_ID
1124
+ );
1125
+ if (!frame) {
1126
+ frame = document.createElement("iframe");
1127
+ frame.id = CLICKY_DOWNLOAD_FRAME_ID;
1128
+ frame.name = CLICKY_DOWNLOAD_FRAME_ID;
1129
+ frame.title = "Clicky download target";
1130
+ frame.setAttribute("aria-hidden", "true");
1131
+ frame.tabIndex = -1;
1132
+ frame.style.display = "none";
1133
+ document.body.appendChild(frame);
1134
+ }
1135
+ frame.src = url;
927
1136
  }
928
1137
  function isAbsoluteUrl(url) {
929
1138
  return /^[a-z][a-z\d+\-.]*:/i.test(url) || url.startsWith("//");
@@ -1016,7 +1225,10 @@ function ClickyComment({ node }) {
1016
1225
  return /* @__PURE__ */ jsx(
1017
1226
  "div",
1018
1227
  {
1019
- className: cn("mt-1 text-xs leading-snug text-muted-foreground", (_d = node.style) == null ? void 0 : _d.className),
1228
+ className: cn(
1229
+ "mt-1 text-xs leading-snug text-muted-foreground",
1230
+ (_d = node.style) == null ? void 0 : _d.className
1231
+ ),
1020
1232
  style: inlineStyle,
1021
1233
  title: ((_e = node.tooltip) == null ? void 0 : _e.plain) ?? text,
1022
1234
  children: content
@@ -1218,11 +1430,17 @@ function ClickyCommandDialog({
1218
1430
  setIsExecuting(true);
1219
1431
  setError("");
1220
1432
  try {
1221
- const response = await executeClickyCommand(runtime.commandRuntime.client, operation, values);
1433
+ const response = await executeClickyCommand(
1434
+ runtime.commandRuntime.client,
1435
+ operation,
1436
+ values
1437
+ );
1222
1438
  setResult(response);
1223
1439
  } catch (err) {
1224
1440
  setResult(null);
1225
- setError(err instanceof Error ? err.message : String(err ?? "Unknown error"));
1441
+ setError(
1442
+ err instanceof Error ? err.message : String(err ?? "Unknown error")
1443
+ );
1226
1444
  } finally {
1227
1445
  setIsExecuting(false);
1228
1446
  }
@@ -1245,7 +1463,13 @@ function ClickyCommandDialog({
1245
1463
  operation ? /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3 text-xs text-muted-foreground", children: [
1246
1464
  /* @__PURE__ */ jsx("span", { className: "rounded-md border border-border bg-muted px-2 py-1 font-medium uppercase", children: operation.method }),
1247
1465
  /* @__PURE__ */ jsx("code", { children: operation.path })
1248
- ] }) : runtime.operationsLoading ? /* @__PURE__ */ jsx(ClickyNotice, { title: "Loading commands", message: "Resolving the command definition." }) : /* @__PURE__ */ jsx(
1466
+ ] }) : runtime.operationsLoading ? /* @__PURE__ */ jsx(
1467
+ ClickyNotice,
1468
+ {
1469
+ title: "Loading commands",
1470
+ message: "Resolving the command definition."
1471
+ }
1472
+ ) : /* @__PURE__ */ jsx(
1249
1473
  ClickyNotice,
1250
1474
  {
1251
1475
  title: "Unknown command",
@@ -1267,7 +1491,14 @@ function ClickyCommandDialog({
1267
1491
  onSubmit: runCommand
1268
1492
  }
1269
1493
  ) }),
1270
- error ? /* @__PURE__ */ jsx(ClickyNotice, { title: "Command failed", message: error, tone: "destructive" }) : /* @__PURE__ */ jsx(
1494
+ error ? /* @__PURE__ */ jsx(
1495
+ ClickyNotice,
1496
+ {
1497
+ title: "Command failed",
1498
+ message: error,
1499
+ tone: "destructive"
1500
+ }
1501
+ ) : /* @__PURE__ */ jsx(
1271
1502
  ClickyCommandResponse,
1272
1503
  {
1273
1504
  response: result,
@@ -1279,7 +1510,9 @@ function ClickyCommandDialog({
1279
1510
  }
1280
1511
  );
1281
1512
  }
1282
- function ClickyAsyncCommandResult({ resolved }) {
1513
+ function ClickyAsyncCommandResult({
1514
+ resolved
1515
+ }) {
1283
1516
  const runtime = useContext(ClickyRuntimeContext);
1284
1517
  const operation = resolved.operation;
1285
1518
  const parameters = (operation == null ? void 0 : operation.operation.parameters) ?? [];
@@ -1301,7 +1534,11 @@ function ClickyAsyncCommandResult({ resolved }) {
1301
1534
  ],
1302
1535
  enabled: runtime.commandRuntime != null && operation != null && missing.length === 0,
1303
1536
  retry: 0,
1304
- queryFn: async () => executeClickyCommand(runtime.commandRuntime.client, operation, initialValues)
1537
+ queryFn: async () => executeClickyCommand(
1538
+ runtime.commandRuntime.client,
1539
+ operation,
1540
+ initialValues
1541
+ )
1305
1542
  });
1306
1543
  if (!runtime.commandRuntime) {
1307
1544
  return /* @__PURE__ */ jsx(
@@ -1315,7 +1552,13 @@ function ClickyAsyncCommandResult({ resolved }) {
1315
1552
  }
1316
1553
  if (!operation) {
1317
1554
  if (runtime.operationsLoading) {
1318
- return /* @__PURE__ */ jsx(ClickyNotice, { title: "Loading commands", message: "Resolving the command definition." });
1555
+ return /* @__PURE__ */ jsx(
1556
+ ClickyNotice,
1557
+ {
1558
+ title: "Loading commands",
1559
+ message: "Resolving the command definition."
1560
+ }
1561
+ );
1319
1562
  }
1320
1563
  return /* @__PURE__ */ jsx(
1321
1564
  ClickyNotice,
@@ -1337,7 +1580,13 @@ function ClickyAsyncCommandResult({ resolved }) {
1337
1580
  );
1338
1581
  }
1339
1582
  if (query.isPending) {
1340
- return /* @__PURE__ */ jsx(ClickyNotice, { title: "Running command", message: "Loading Clicky response…" });
1583
+ return /* @__PURE__ */ jsx(
1584
+ ClickyNotice,
1585
+ {
1586
+ title: "Running command",
1587
+ message: "Loading Clicky response…"
1588
+ }
1589
+ );
1341
1590
  }
1342
1591
  if (query.isError) {
1343
1592
  return /* @__PURE__ */ jsx(
@@ -1349,7 +1598,13 @@ function ClickyAsyncCommandResult({ resolved }) {
1349
1598
  }
1350
1599
  );
1351
1600
  }
1352
- return /* @__PURE__ */ jsx(ClickyCommandResponse, { response: query.data, emptyMessage: "No response body returned." });
1601
+ return /* @__PURE__ */ jsx(
1602
+ ClickyCommandResponse,
1603
+ {
1604
+ response: query.data,
1605
+ emptyMessage: "No response body returned."
1606
+ }
1607
+ );
1353
1608
  }
1354
1609
  function ClickyCommandResponse({
1355
1610
  response,
@@ -1357,7 +1612,13 @@ function ClickyCommandResponse({
1357
1612
  emptyMessage
1358
1613
  }) {
1359
1614
  if (pending) {
1360
- return /* @__PURE__ */ jsx(ClickyNotice, { title: "Running command", message: "Loading Clicky response…" });
1615
+ return /* @__PURE__ */ jsx(
1616
+ ClickyNotice,
1617
+ {
1618
+ title: "Running command",
1619
+ message: "Loading Clicky response…"
1620
+ }
1621
+ );
1361
1622
  }
1362
1623
  if (!response) {
1363
1624
  return /* @__PURE__ */ jsx(ClickyNotice, { title: "No response", message: emptyMessage });
@@ -1377,7 +1638,15 @@ function ClickyCommandResponse({
1377
1638
  function ClickyIconNode({ node }) {
1378
1639
  var _a;
1379
1640
  const inlineStyle = toInlineStyle(node.style, node.plain ?? node.unicode);
1380
- return /* @__PURE__ */ jsx("span", { style: inlineStyle, title: (_a = node.tooltip) == null ? void 0 : _a.plain, className: "inline-flex items-center", children: node.iconify ? /* @__PURE__ */ jsx(Icon, { name: node.iconify }) : /* @__PURE__ */ jsx("span", { children: node.unicode ?? node.plain }) });
1641
+ return /* @__PURE__ */ jsx(
1642
+ "span",
1643
+ {
1644
+ style: inlineStyle,
1645
+ title: (_a = node.tooltip) == null ? void 0 : _a.plain,
1646
+ className: "inline-flex items-center",
1647
+ children: node.iconify ? /* @__PURE__ */ jsx(Icon, { name: node.iconify }) : /* @__PURE__ */ jsx("span", { children: node.unicode ?? node.plain })
1648
+ }
1649
+ );
1381
1650
  }
1382
1651
  function ClickyList({ node }) {
1383
1652
  const items = node.items ?? [];
@@ -1410,7 +1679,10 @@ function ClickyList({ node }) {
1410
1679
  return /* @__PURE__ */ jsx(Tag, { className: cn("ml-5 space-y-1 text-sm", listClass), children: items.map((item, index) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(ClickyNodeRenderer, { node: item }) }, index)) });
1411
1680
  }
1412
1681
  function ClickyMap({ node }) {
1413
- const fields = node.fields ?? [];
1682
+ const runtime = useContext(ClickyRuntimeContext);
1683
+ const fields = (node.fields ?? []).filter(
1684
+ (field) => !(runtime.tablePagination && isPaginationMetadataField(field))
1685
+ );
1414
1686
  if (fields.length === 0) return null;
1415
1687
  const inlineFields = fields.filter((field) => isInlineNode(field.value));
1416
1688
  const blockFields = fields.filter((field) => !isInlineNode(field.value));
@@ -1425,6 +1697,14 @@ function ClickyMap({ node }) {
1425
1697
  ] }, field.name))
1426
1698
  ] });
1427
1699
  }
1700
+ function isPaginationMetadataField(field) {
1701
+ const name = (field.label || field.name || "").toLowerCase();
1702
+ if (name !== "page" || field.value.kind !== "map") return false;
1703
+ const keys = new Set(
1704
+ (field.value.fields ?? []).map((item) => item.name.toLowerCase())
1705
+ );
1706
+ return keys.has("limit") && keys.has("offset") && keys.has("total");
1707
+ }
1428
1708
  function ClickyTableNode({ node }) {
1429
1709
  return /* @__PURE__ */ jsx(
1430
1710
  ClickyTable,
@@ -1445,7 +1725,8 @@ function ClickyTable({
1445
1725
  search,
1446
1726
  timeRange,
1447
1727
  externalFilters,
1448
- pagination
1728
+ pagination,
1729
+ menuActions
1449
1730
  }) {
1450
1731
  const runtime = useContext(ClickyRuntimeContext);
1451
1732
  const rowClick = onTableRowClick ?? runtime.onTableRowClick;
@@ -1455,6 +1736,7 @@ function ClickyTable({
1455
1736
  const effectiveTimeRange = timeRange ?? runtime.tableTimeRange;
1456
1737
  const effectiveExternalFilters = externalFilters ?? runtime.tableExternalFilters;
1457
1738
  const effectivePagination = pagination ?? runtime.tablePagination;
1739
+ const effectiveMenuActions = menuActions ?? runtime.tableMenuActions;
1458
1740
  if (columns.length === 0 || rows.length === 0) {
1459
1741
  return /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: "No data" });
1460
1742
  }
@@ -1515,7 +1797,8 @@ function ClickyTable({
1515
1797
  ...effectiveSearch ? { externalSearch: effectiveSearch } : {},
1516
1798
  ...effectiveTimeRange ? { externalTimeRange: effectiveTimeRange } : {},
1517
1799
  ...effectiveExternalFilters ? { externalFilters: effectiveExternalFilters } : {},
1518
- ...effectivePagination ? { pagination: effectivePagination } : {}
1800
+ ...effectivePagination ? { pagination: effectivePagination } : {},
1801
+ ...effectiveMenuActions ? { menuActions: effectiveMenuActions } : {}
1519
1802
  }
1520
1803
  );
1521
1804
  }
@@ -1534,7 +1817,14 @@ function ClickyTableRowDetail({
1534
1817
  /* @__PURE__ */ jsx("div", { className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Tags" }),
1535
1818
  /* @__PURE__ */ jsx("div", { className: "grid gap-2", children: tagFields.map(({ column, tags, tableKey }) => {
1536
1819
  const tagActions = context.filterActionsByColumn[tableKey];
1537
- const content = /* @__PURE__ */ jsx(TagList, { tags, maxVisible: tags.length, actions: "inline" });
1820
+ const content = /* @__PURE__ */ jsx(
1821
+ TagList,
1822
+ {
1823
+ tags,
1824
+ maxVisible: tags.length,
1825
+ actions: "inline"
1826
+ }
1827
+ );
1538
1828
  return /* @__PURE__ */ jsxs(
1539
1829
  "div",
1540
1830
  {
@@ -1550,10 +1840,17 @@ function ClickyTableRowDetail({
1550
1840
  ] }),
1551
1841
  /* @__PURE__ */ jsxs("section", { className: "space-y-2", children: [
1552
1842
  /* @__PURE__ */ jsx("div", { className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Fields" }),
1553
- /* @__PURE__ */ jsx("dl", { className: "grid gap-2 md:grid-cols-2", children: columns.map((column) => /* @__PURE__ */ jsxs("div", { className: "rounded-md border border-border bg-background p-2", children: [
1554
- /* @__PURE__ */ jsx("dt", { className: "text-xs font-medium uppercase tracking-wide text-muted-foreground", children: column.label || prettifyName(column.name) }),
1555
- /* @__PURE__ */ jsx("dd", { className: "mt-1 min-w-0 text-sm text-foreground", children: /* @__PURE__ */ jsx(ClickyNodeRenderer, { node: row.cells[column.name] }) })
1556
- ] }, column.name)) })
1843
+ /* @__PURE__ */ jsx("dl", { className: "grid gap-2 md:grid-cols-2", children: columns.map((column) => /* @__PURE__ */ jsxs(
1844
+ "div",
1845
+ {
1846
+ className: "rounded-md border border-border bg-background p-2",
1847
+ children: [
1848
+ /* @__PURE__ */ jsx("dt", { className: "text-xs font-medium uppercase tracking-wide text-muted-foreground", children: column.label || prettifyName(column.name) }),
1849
+ /* @__PURE__ */ jsx("dd", { className: "mt-1 min-w-0 text-sm text-foreground", children: /* @__PURE__ */ jsx(ClickyNodeRenderer, { node: row.cells[column.name] }) })
1850
+ ]
1851
+ },
1852
+ column.name
1853
+ )) })
1557
1854
  ] }),
1558
1855
  row.detail && /* @__PURE__ */ jsxs("section", { className: "space-y-2", children: [
1559
1856
  /* @__PURE__ */ jsx("div", { className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Detail" }),
@@ -1694,7 +1991,9 @@ function findFieldText(node, preferredName) {
1694
1991
  return "";
1695
1992
  }
1696
1993
  function hasMeaningfulText(node) {
1697
- return Boolean(clickyNodeText(node).trim() || ((node == null ? void 0 : node.fields) ?? []).length > 0);
1994
+ return Boolean(
1995
+ clickyNodeText(node).trim() || ((node == null ? void 0 : node.fields) ?? []).length > 0
1996
+ );
1698
1997
  }
1699
1998
  function normalizeFieldName(name) {
1700
1999
  return name.toLowerCase().replace(/[^a-z0-9]/g, "");
@@ -1784,17 +2083,20 @@ function ClickyHtmlNode({ node }) {
1784
2083
  return /* @__PURE__ */ jsx(Tag, { dangerouslySetInnerHTML: { __html: sanitized } });
1785
2084
  }
1786
2085
  function toInlineStyle(style, text) {
1787
- if (!style) return (text == null ? void 0 : text.includes("\n")) ? { whiteSpace: "pre-wrap" } : void 0;
2086
+ if (!style)
2087
+ return (text == null ? void 0 : text.includes("\n")) ? { whiteSpace: "pre-wrap" } : void 0;
1788
2088
  const inlineStyle = {};
1789
2089
  if (style.color) inlineStyle.color = style.color;
1790
- if (style.backgroundColor) inlineStyle.backgroundColor = style.backgroundColor;
2090
+ if (style.backgroundColor)
2091
+ inlineStyle.backgroundColor = style.backgroundColor;
1791
2092
  if (style.bold) inlineStyle.fontWeight = 700;
1792
2093
  if (style.faint) inlineStyle.opacity = 0.7;
1793
2094
  if (style.italic) inlineStyle.fontStyle = "italic";
1794
2095
  const decorations = [];
1795
2096
  if (style.underline) decorations.push("underline");
1796
2097
  if (style.strikethrough) decorations.push("line-through");
1797
- if (decorations.length > 0) inlineStyle.textDecoration = decorations.join(" ");
2098
+ if (decorations.length > 0)
2099
+ inlineStyle.textDecoration = decorations.join(" ");
1798
2100
  if (style.textTransform === "uppercase" || style.textTransform === "lowercase" || style.textTransform === "capitalize") {
1799
2101
  inlineStyle.textTransform = style.textTransform;
1800
2102
  }
@@ -1845,11 +2147,15 @@ function defaultResolveClickyCommand(request, operations) {
1845
2147
  if (!wanted) return void 0;
1846
2148
  return operations.find((operation) => {
1847
2149
  var _a, _b;
1848
- const metaCommand = normalizeCommandPath((_a = operation.operation["x-clicky"]) == null ? void 0 : _a.command);
2150
+ const metaCommand = normalizeCommandPath(
2151
+ (_a = operation.operation["x-clicky"]) == null ? void 0 : _a.command
2152
+ );
1849
2153
  if (metaCommand && metaCommand === wanted) {
1850
2154
  return true;
1851
2155
  }
1852
- const operationId = normalizeCommandPath((_b = operation.operation.operationId) == null ? void 0 : _b.replaceAll("_", "/"));
2156
+ const operationId = normalizeCommandPath(
2157
+ (_b = operation.operation.operationId) == null ? void 0 : _b.replaceAll("_", "/")
2158
+ );
1853
2159
  return operationId === wanted;
1854
2160
  });
1855
2161
  }
@@ -1859,7 +2165,9 @@ function normalizeCommandPath(value) {
1859
2165
  function buildCommandParameterValues(parameters, request) {
1860
2166
  const values = { ...request.flags };
1861
2167
  const args = [...request.args ?? []];
1862
- const positionalParams = parameters.filter((param) => isPositionalParam(param));
2168
+ const positionalParams = parameters.filter(
2169
+ (param) => isPositionalParam(param)
2170
+ );
1863
2171
  let argIndex = 0;
1864
2172
  for (const param of positionalParams) {
1865
2173
  if (param.name === "args") {
@@ -1878,13 +2186,18 @@ function buildCommandParameterValues(parameters, request) {
1878
2186
  return values;
1879
2187
  }
1880
2188
  function missingRequiredParameters(parameters, values) {
1881
- return parameters.filter((param) => param.required && (values[param.name] ?? "").trim() === "");
2189
+ return parameters.filter(
2190
+ (param) => param.required && (values[param.name] ?? "").trim() === ""
2191
+ );
1882
2192
  }
1883
2193
  async function executeClickyCommand(client, operation, values) {
1884
2194
  return client.executeCommand(
1885
2195
  operation.path,
1886
2196
  operation.method,
1887
- packParameterValues(pruneParameterValues(values), operation.operation.parameters ?? []),
2197
+ packParameterValues(
2198
+ pruneParameterValues(values),
2199
+ operation.operation.parameters ?? []
2200
+ ),
1888
2201
  { Accept: "application/json+clicky" }
1889
2202
  );
1890
2203
  }
@@ -1912,7 +2225,10 @@ function substituteOperationPath(path, params) {
1912
2225
  const remaining = { ...params };
1913
2226
  for (const [key, value] of Object.entries(params)) {
1914
2227
  if (url.pathname.includes(`{${key}}`)) {
1915
- url.pathname = url.pathname.replace(`{${key}}`, encodeURIComponent(value));
2228
+ url.pathname = url.pathname.replace(
2229
+ `{${key}}`,
2230
+ encodeURIComponent(value)
2231
+ );
1916
2232
  delete remaining[key];
1917
2233
  }
1918
2234
  }
@@ -1942,14 +2258,20 @@ function clickyNodeText(node) {
1942
2258
  return sanitizeHtml(node.html ?? "").replace(/<[^>]+>/g, " ").trim();
1943
2259
  if (node.kind === "code") return node.source ?? "";
1944
2260
  if ((node.kind === "link" || node.kind === "link-command") && ((_a = node.children) == null ? void 0 : _a.length)) {
1945
- return [node.text, ...node.children.map((child) => clickyNodeText(child))].join("");
2261
+ return [
2262
+ node.text,
2263
+ ...node.children.map((child) => clickyNodeText(child))
2264
+ ].join("");
1946
2265
  }
1947
2266
  if (node.kind === "button" && node.label) return clickyNodeText(node.label);
1948
2267
  if (node.kind === "button-group") {
1949
2268
  return (node.items ?? []).map((item) => clickyNodeText(item)).join(" ");
1950
2269
  }
1951
2270
  if (node.kind === "text" && ((_b = node.children) == null ? void 0 : _b.length)) {
1952
- return [node.text, ...node.children.map((child) => clickyNodeText(child))].join("");
2271
+ return [
2272
+ node.text,
2273
+ ...node.children.map((child) => clickyNodeText(child))
2274
+ ].join("");
1953
2275
  }
1954
2276
  return "";
1955
2277
  }