@apiboost/omnispec 1.1.0-next.1 → 1.1.0-next.3

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 (77) hide show
  1. package/dist/cjs/asyncapi/index.js +4 -4
  2. package/dist/cjs/chunks/{AsyncApiSpec-CHvM1swf.js → AsyncApiSpec-BzgUioEK.js} +872 -151
  3. package/dist/cjs/chunks/AsyncApiSpec-BzgUioEK.js.map +1 -0
  4. package/dist/cjs/chunks/{Collapsible-Jlb_vtdW.js → Collapsible-BTWyDBkX.js} +161 -2
  5. package/dist/cjs/chunks/Collapsible-BTWyDBkX.js.map +1 -0
  6. package/dist/cjs/chunks/{ErrorBoundary-c1piU8da.js → ErrorBoundary-CezYgQDG.js} +2 -2
  7. package/dist/cjs/chunks/{ErrorBoundary-c1piU8da.js.map → ErrorBoundary-CezYgQDG.js.map} +1 -1
  8. package/dist/cjs/chunks/{OmniSpecRenderer-Dj6Z6W2J.js → OmniSpecRenderer-CRipDRtC.js} +6 -6
  9. package/dist/cjs/chunks/{OmniSpecRenderer-Dj6Z6W2J.js.map → OmniSpecRenderer-CRipDRtC.js.map} +1 -1
  10. package/dist/cjs/chunks/{OpenApiSpec-BPtXvk7C.js → OpenApiSpec-BOlesoUX.js} +7 -7
  11. package/dist/cjs/chunks/OpenApiSpec-BOlesoUX.js.map +1 -0
  12. package/dist/cjs/chunks/{OpenIdConnectManual-DBP0Do-3.js → OpenIdConnectManual-Bh7tdxoH.js} +3 -162
  13. package/dist/cjs/chunks/OpenIdConnectManual-Bh7tdxoH.js.map +1 -0
  14. package/dist/cjs/chunks/{useSpecDetector-A4OwYrmY.js → useSpecDetector-BemsWW9u.js} +2 -2
  15. package/dist/cjs/chunks/{useSpecDetector-A4OwYrmY.js.map → useSpecDetector-BemsWW9u.js.map} +1 -1
  16. package/dist/cjs/chunks/{useSpecFetcher-BKz1jHTV.js → useSpecFetcher-BAbHnXax.js} +28 -1
  17. package/dist/{esm/chunks/useSpecFetcher-CZvAnU7Z.js.map → cjs/chunks/useSpecFetcher-BAbHnXax.js.map} +1 -1
  18. package/dist/cjs/core/public.js +5 -5
  19. package/dist/cjs/index.js +8 -8
  20. package/dist/cjs/openapi/index.js +5 -5
  21. package/dist/cjs/wc/index.js +4 -4
  22. package/dist/esm/asyncapi/index.js +4 -4
  23. package/dist/esm/chunks/{AsyncApiSpec-BPiA9b5T.js → AsyncApiSpec-B757IIHz.js} +880 -159
  24. package/dist/esm/chunks/AsyncApiSpec-B757IIHz.js.map +1 -0
  25. package/dist/esm/chunks/{Collapsible-0ryLh6wX.js → Collapsible-MyJB2agz.js} +161 -3
  26. package/dist/esm/chunks/Collapsible-MyJB2agz.js.map +1 -0
  27. package/dist/esm/chunks/{ErrorBoundary-posRNrbt.js → ErrorBoundary-9pDlZFfM.js} +2 -2
  28. package/dist/esm/chunks/{ErrorBoundary-posRNrbt.js.map → ErrorBoundary-9pDlZFfM.js.map} +1 -1
  29. package/dist/esm/chunks/{OmniSpecRenderer-yF2Zw_B9.js → OmniSpecRenderer-5RUZx-C7.js} +6 -6
  30. package/dist/esm/chunks/{OmniSpecRenderer-yF2Zw_B9.js.map → OmniSpecRenderer-5RUZx-C7.js.map} +1 -1
  31. package/dist/esm/chunks/{OpenApiSpec-MGJ3oFHZ.js → OpenApiSpec-wm3tH2vF.js} +5 -5
  32. package/dist/esm/chunks/OpenApiSpec-wm3tH2vF.js.map +1 -0
  33. package/dist/esm/chunks/{OpenIdConnectManual-BS-n811Z.js → OpenIdConnectManual-DPmTIIIy.js} +4 -162
  34. package/dist/esm/chunks/OpenIdConnectManual-DPmTIIIy.js.map +1 -0
  35. package/dist/esm/chunks/{useSpecDetector-5SGcKnJx.js → useSpecDetector-BJBNbfN5.js} +2 -2
  36. package/dist/esm/chunks/{useSpecDetector-5SGcKnJx.js.map → useSpecDetector-BJBNbfN5.js.map} +1 -1
  37. package/dist/esm/chunks/{useSpecFetcher-CZvAnU7Z.js → useSpecFetcher-BvVfMuzf.js} +28 -1
  38. package/dist/{cjs/chunks/useSpecFetcher-BKz1jHTV.js.map → esm/chunks/useSpecFetcher-BvVfMuzf.js.map} +1 -1
  39. package/dist/esm/core/public.js +4 -4
  40. package/dist/esm/index.js +8 -8
  41. package/dist/esm/openapi/index.js +5 -5
  42. package/dist/esm/wc/index.js +4 -4
  43. package/dist/types/asyncapi/AsyncApiSpec.d.ts +1 -1
  44. package/dist/types/asyncapi/AsyncApiSpec.d.ts.map +1 -1
  45. package/dist/types/asyncapi/components/AsyncOverview.d.ts.map +1 -1
  46. package/dist/types/asyncapi/components/ChannelDetail.d.ts +6 -1
  47. package/dist/types/asyncapi/components/ChannelDetail.d.ts.map +1 -1
  48. package/dist/types/asyncapi/components/ChannelReferenceDetail.d.ts +35 -0
  49. package/dist/types/asyncapi/components/ChannelReferenceDetail.d.ts.map +1 -0
  50. package/dist/types/asyncapi/components/ComponentsSection.d.ts.map +1 -1
  51. package/dist/types/asyncapi/components/ExternalDocsLink.d.ts +29 -0
  52. package/dist/types/asyncapi/components/ExternalDocsLink.d.ts.map +1 -0
  53. package/dist/types/asyncapi/components/MessagePayload.d.ts.map +1 -1
  54. package/dist/types/asyncapi/components/SecurityRequirementBadges.d.ts +13 -6
  55. package/dist/types/asyncapi/components/SecurityRequirementBadges.d.ts.map +1 -1
  56. package/dist/types/asyncapi/components/TagGroupHeader.d.ts +1 -1
  57. package/dist/types/asyncapi/components/TagGroupHeader.d.ts.map +1 -1
  58. package/dist/types/asyncapi/components/field-display.d.ts +11 -1
  59. package/dist/types/asyncapi/components/field-display.d.ts.map +1 -1
  60. package/dist/types/asyncapi/parser/asyncapi-parser.d.ts.map +1 -1
  61. package/dist/types/asyncapi/tag-grouping.d.ts +5 -1
  62. package/dist/types/asyncapi/tag-grouping.d.ts.map +1 -1
  63. package/dist/types/asyncapi/types/asyncapi.types.d.ts +37 -8
  64. package/dist/types/asyncapi/types/asyncapi.types.d.ts.map +1 -1
  65. package/dist/types/core/components/Layout/DocLayout.d.ts.map +1 -1
  66. package/dist/types/core/types/auth.types.d.ts +1 -1
  67. package/dist/wc/standalone.js +1 -1
  68. package/dist/wc/standalone.js.map +1 -1
  69. package/package.json +1 -1
  70. package/dist/cjs/chunks/AsyncApiSpec-CHvM1swf.js.map +0 -1
  71. package/dist/cjs/chunks/Collapsible-Jlb_vtdW.js.map +0 -1
  72. package/dist/cjs/chunks/OpenApiSpec-BPtXvk7C.js.map +0 -1
  73. package/dist/cjs/chunks/OpenIdConnectManual-DBP0Do-3.js.map +0 -1
  74. package/dist/esm/chunks/AsyncApiSpec-BPiA9b5T.js.map +0 -1
  75. package/dist/esm/chunks/Collapsible-0ryLh6wX.js.map +0 -1
  76. package/dist/esm/chunks/OpenApiSpec-MGJ3oFHZ.js.map +0 -1
  77. package/dist/esm/chunks/OpenIdConnectManual-BS-n811Z.js.map +0 -1
@@ -1,21 +1,13 @@
1
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
- import { useCallback, useState, useMemo } from 'react';
3
- import { css, cx } from '@emotion/css';
4
- import { a as useSpecFetcher, I as Icon, m as mq, r as resolveSchemaStyle, S as SpecType, T as ThemeProvider, L as LoadingScreen, b as SpecStatusScreen, E as ErrorMessage, N as NavTree, h as buildSidebar, C as ConfigProvider, e as DocLayout } from './useSpecFetcher-CZvAnU7Z.js';
5
- import { M as MarkdownRenderer, T as Tabs, t as SchemaTree, A as schemaToNodes, x as generateExample, H as ExampleSelector, C as CodeBlock, d as ExpandableCard, f as MethodBar, I as buildConstraints, S as SchemaBadge, a as Collapsible, D as useHashScroll, y as requestExpand, w as flattenNavItemIds, G as useScrollSpy, u as SearchBar, J as ExpandProvider, v as SpecToolbar, z as resolveDownloadLink } from './Collapsible-0ryLh6wX.js';
6
- import { E as ErrorBoundary } from './ErrorBoundary-posRNrbt.js';
1
+ import { jsxs, jsx, Fragment as Fragment$1 } from 'react/jsx-runtime';
2
+ import { useCallback, Fragment, useState, useMemo } from 'react';
3
+ import { cx, css } from '@emotion/css';
4
+ import { a as useSpecFetcher, I as Icon, m as mq, r as resolveSchemaStyle, S as SpecType, T as ThemeProvider, L as LoadingScreen, b as SpecStatusScreen, E as ErrorMessage, N as NavTree, h as buildSidebar, C as ConfigProvider, e as DocLayout } from './useSpecFetcher-BvVfMuzf.js';
5
+ import { M as MarkdownRenderer, C as CodeBlock, T as Tabs, t as SchemaTree, A as schemaToNodes, x as generateExample, J as ExampleSelector, d as ExpandableCard, f as MethodBar, K as buildConstraints, S as SchemaBadge, R as ReferenceLayout, a as Collapsible, D as useHashScroll, y as requestExpand, w as flattenNavItemIds, G as useScrollSpy, u as SearchBar, L as ExpandProvider, v as SpecToolbar, z as resolveDownloadLink } from './Collapsible-MyJB2agz.js';
6
+ import { E as ErrorBoundary } from './ErrorBoundary-9pDlZFfM.js';
7
7
  import { r as resolveRefs, p as parse, d as decodeJsonPointerSegment } from './ref-resolver-B0C36NuQ.js';
8
8
  import '@emotion/styled';
9
9
  import './ssrf-guard-CsZoYdEq.js';
10
10
 
11
- function unionTags(a, b) {
12
- if (!a && !b) return void 0;
13
- const byName = /* @__PURE__ */ new Map();
14
- for (const tag of [...a ?? [], ...b ?? []]) {
15
- if (!byName.has(tag.name)) byName.set(tag.name, tag);
16
- }
17
- return Array.from(byName.values());
18
- }
19
11
  function mergeSchema(base, override) {
20
12
  if (!base) return override;
21
13
  if (!override) return base;
@@ -35,9 +27,7 @@ function mergeMessageLayer(base, override) {
35
27
  const result = { ...base };
36
28
  for (const [key, value] of Object.entries(override)) {
37
29
  if (key === "traits" || value === void 0) continue;
38
- if (key === "tags") {
39
- result.tags = unionTags(base.tags, value);
40
- } else if (key === "headers") {
30
+ if (key === "headers") {
41
31
  result.headers = mergeSchema(base.headers, value);
42
32
  } else if (key === "examples") {
43
33
  result.examples = [...base.examples ?? [], ...value ?? []];
@@ -49,19 +39,22 @@ function mergeMessageLayer(base, override) {
49
39
  }
50
40
  return result;
51
41
  }
52
- function applyMessageTraits(msg) {
42
+ function applyMessageTraits(msg, isV3) {
53
43
  if (!msg.traits || msg.traits.length === 0) return msg;
54
- let acc = {};
44
+ if (isV3) {
45
+ let acc2 = {};
46
+ for (const trait of msg.traits) acc2 = mergeMessageLayer(acc2, trait);
47
+ return mergeMessageLayer(acc2, msg);
48
+ }
49
+ let acc = msg;
55
50
  for (const trait of msg.traits) acc = mergeMessageLayer(acc, trait);
56
- return mergeMessageLayer(acc, msg);
51
+ return acc;
57
52
  }
58
53
  function mergeOperationLayer(base, override) {
59
54
  const result = { ...base };
60
55
  for (const [key, value] of Object.entries(override)) {
61
56
  if (key === "traits" || value === void 0) continue;
62
- if (key === "tags") {
63
- result.tags = unionTags(base.tags, value);
64
- } else if (key === "bindings") {
57
+ if (key === "bindings") {
65
58
  result.bindings = { ...base.bindings ?? {}, ...value };
66
59
  } else {
67
60
  result[key] = value;
@@ -69,11 +62,16 @@ function mergeOperationLayer(base, override) {
69
62
  }
70
63
  return result;
71
64
  }
72
- function applyOperationTraits(op) {
65
+ function applyOperationTraits(op, isV3) {
73
66
  if (!op.traits || op.traits.length === 0) return op;
74
- let acc = {};
67
+ if (isV3) {
68
+ let acc2 = {};
69
+ for (const trait of op.traits) acc2 = mergeOperationLayer(acc2, trait);
70
+ return mergeOperationLayer(acc2, op);
71
+ }
72
+ let acc = op;
75
73
  for (const trait of op.traits) acc = mergeOperationLayer(acc, trait);
76
- return mergeOperationLayer(acc, op);
74
+ return acc;
77
75
  }
78
76
  async function parseAsyncApiSpec(specInput) {
79
77
  const raw = typeof specInput === "string" ? parseSpecString(specInput) : specInput;
@@ -82,8 +80,9 @@ async function parseAsyncApiSpec(specInput) {
82
80
  const isV3 = majorVersion >= 3;
83
81
  const servers = extractServers(api, raw);
84
82
  const rawApi = raw;
85
- const channels = isV3 ? extractChannelsV3(api, rawApi) : extractChannelsV2(api);
86
- const components = extractComponents(api);
83
+ const defaultContentType = api.defaultContentType;
84
+ const channels = isV3 ? extractChannelsV3(api, rawApi, defaultContentType) : extractChannelsV2(api, defaultContentType);
85
+ const components = extractComponents(api, isV3, defaultContentType);
87
86
  const root = api;
88
87
  const tags = api.tags?.map((tag) => {
89
88
  const raw2 = tag;
@@ -108,11 +107,13 @@ async function parseAsyncApiSpec(specInput) {
108
107
  contact: api.info.contact,
109
108
  license: api.info.license,
110
109
  termsOfService: api.info.termsOfService,
111
- logo: api.info["x-logo"]
110
+ logo: api.info["x-logo"],
111
+ defaultContentType
112
112
  };
113
113
  }
114
114
  function extractServers(api, rawApi) {
115
115
  if (!api.servers) return [];
116
+ const isV3 = parseInt(api.asyncapi.split(".")[0], 10) >= 3;
116
117
  const toServer = (s, name, rawSecurity) => ({
117
118
  name,
118
119
  url: s.host ? `${s.protocol}://${s.host}${s.pathname ?? ""}` : s.url ?? "",
@@ -122,6 +123,7 @@ function extractServers(api, rawApi) {
122
123
  variables: s.variables,
123
124
  security: s.security,
124
125
  securityNames: deriveSecurityNames(rawSecurity, s.security),
126
+ securityRequirements: deriveSecurityRequirements(rawSecurity, s.security, isV3),
125
127
  bindings: s.bindings
126
128
  });
127
129
  if (Array.isArray(api.servers)) {
@@ -131,15 +133,15 @@ function extractServers(api, rawApi) {
131
133
  const rawServers = !Array.isArray(rawApi.servers) && rawApi.servers || {};
132
134
  return Object.entries(api.servers).map(([name, s]) => toServer(s, name, rawServers[name]?.security));
133
135
  }
134
- function extractChannelsV2(api) {
136
+ function extractChannelsV2(api, defaultContentType) {
135
137
  if (!api.channels) return [];
136
138
  return Object.entries(api.channels).map(([channelName, ch]) => {
137
139
  const operations = [];
138
140
  if (ch.publish) {
139
- operations.push(convertOperationV2("publish", ch.publish));
141
+ operations.push(convertOperationV2("publish", ch.publish, defaultContentType));
140
142
  }
141
143
  if (ch.subscribe) {
142
- operations.push(convertOperationV2("subscribe", ch.subscribe));
144
+ operations.push(convertOperationV2("subscribe", ch.subscribe, defaultContentType));
143
145
  }
144
146
  const raw = ch;
145
147
  return {
@@ -149,20 +151,21 @@ function extractChannelsV2(api) {
149
151
  operations: operations.filter((op) => !op.xInternal),
150
152
  parameters: ch.parameters,
151
153
  bindings: ch.bindings,
154
+ // 2.x channels have no externalDocs or channel-level tags.
152
155
  xInternal: raw["x-internal"]
153
156
  };
154
157
  });
155
158
  }
156
- function convertOperationV2(action, rawOp) {
157
- const op = applyOperationTraits(rawOp);
159
+ function convertOperationV2(action, rawOp, defaultContentType) {
160
+ const op = applyOperationTraits(rawOp, false);
158
161
  const messages = [];
159
162
  if (op.message) {
160
163
  if ("oneOf" in op.message) {
161
164
  for (const m of op.message.oneOf) {
162
- messages.push(convertMessage(m));
165
+ messages.push(convertMessage(m, false, defaultContentType));
163
166
  }
164
167
  } else {
165
- messages.push(convertMessage(op.message));
168
+ messages.push(convertMessage(op.message, false, defaultContentType));
166
169
  }
167
170
  }
168
171
  const raw = op;
@@ -175,7 +178,9 @@ function convertOperationV2(action, rawOp) {
175
178
  message: messages[0],
176
179
  tags: op.tags,
177
180
  bindings: op.bindings,
181
+ externalDocs: op.externalDocs,
178
182
  securityNames: deriveSecurityNames(void 0, op.security),
183
+ securityRequirements: deriveSecurityRequirements(void 0, op.security, false),
179
184
  xBadges: raw["x-badges"],
180
185
  xInternal: raw["x-internal"]
181
186
  };
@@ -192,7 +197,7 @@ function resolveChannelName(rawChannel, resolvedChannel, addressToName) {
192
197
  }
193
198
  return void 0;
194
199
  }
195
- function extractChannelsV3(api, rawApi) {
200
+ function extractChannelsV3(api, rawApi, defaultContentType) {
196
201
  if (!api.channels) return [];
197
202
  const channelMap = /* @__PURE__ */ new Map();
198
203
  const addressToName = /* @__PURE__ */ new Map();
@@ -207,69 +212,108 @@ function extractChannelsV3(api, rawApi) {
207
212
  operations: [],
208
213
  parameters: ch.parameters,
209
214
  bindings: ch.bindings,
215
+ externalDocs: ch.externalDocs,
216
+ tags: ch.tags,
210
217
  xInternal: raw["x-internal"]
211
218
  });
212
219
  }
220
+ const orphanOperations = [];
213
221
  if (api.operations) {
214
222
  for (const [opKey, resolvedOp] of Object.entries(api.operations)) {
215
- const op = applyOperationTraits(resolvedOp);
223
+ const op = applyOperationTraits(resolvedOp, true);
216
224
  const rawOp = rawApi.operations?.[opKey];
217
225
  const channelName = resolveChannelName(rawOp?.channel, op.channel, addressToName);
218
226
  const collectMessages = (list) => {
219
227
  const out = [];
220
228
  for (const msg of list ?? []) {
221
229
  if (msg && typeof msg === "object" && "$ref" in msg) continue;
222
- out.push(convertMessage(msg));
230
+ out.push(convertMessage(msg, true, defaultContentType));
223
231
  }
224
232
  return out;
225
233
  };
226
- const messages = collectMessages(op.messages);
234
+ let messages = collectMessages(op.messages);
235
+ if (messages.length === 0 && channelName && api.channels?.[channelName]?.messages) {
236
+ messages = collectMessages(
237
+ Object.values(api.channels[channelName].messages)
238
+ );
239
+ }
227
240
  const replyMessages = collectMessages(op.reply?.messages);
241
+ const rawReplyChannel = rawOp?.reply?.channel;
242
+ const replyChannelName = resolveChannelName(
243
+ rawReplyChannel,
244
+ op.reply?.channel,
245
+ addressToName
246
+ );
228
247
  const raw = op;
248
+ const reply = replyMessages.length > 0 || op.reply?.address || replyChannelName ? {
249
+ messages: replyMessages,
250
+ address: op.reply?.address,
251
+ channelName: replyChannelName
252
+ } : void 0;
229
253
  const operation = {
230
254
  action: op.action,
255
+ // 3.x has no operationId field; the operations-map key is the id.
256
+ operationId: opKey,
257
+ title: op.title,
231
258
  summary: op.summary,
232
259
  description: op.description,
233
260
  messages,
234
261
  message: messages[0],
235
262
  tags: op.tags,
236
263
  bindings: op.bindings,
264
+ externalDocs: op.externalDocs,
237
265
  securityNames: deriveSecurityNames(rawOp?.security, op.security),
238
- reply: replyMessages.length > 0 ? { messages: replyMessages } : void 0,
266
+ securityRequirements: deriveSecurityRequirements(rawOp?.security, op.security, true),
267
+ reply,
239
268
  xBadges: raw["x-badges"],
240
269
  xInternal: raw["x-internal"]
241
270
  };
242
271
  if (operation.xInternal) continue;
243
272
  if (channelName && channelMap.has(channelName)) {
244
273
  channelMap.get(channelName).operations.push(operation);
274
+ } else {
275
+ orphanOperations.push(operation);
245
276
  }
246
277
  }
247
278
  }
248
- return Array.from(channelMap.values());
279
+ const channels = Array.from(channelMap.values());
280
+ if (orphanOperations.length > 0) {
281
+ channels.push({
282
+ name: "__unassigned__",
283
+ address: "Unassigned operations",
284
+ description: "These operations reference a channel that is not defined in this document.",
285
+ operations: orphanOperations
286
+ });
287
+ }
288
+ return channels;
249
289
  }
250
- function convertMessage(rawMsg) {
251
- const msg = applyMessageTraits(rawMsg);
290
+ function convertMessage(rawMsg, isV3, defaultContentType) {
291
+ const msg = applyMessageTraits(rawMsg, isV3);
292
+ const hasOwnContentType = typeof msg.contentType === "string" && msg.contentType.length > 0;
293
+ const contentType = hasOwnContentType ? msg.contentType : defaultContentType ?? "application/json";
252
294
  return {
253
295
  name: msg.name,
254
296
  title: msg.title,
255
297
  summary: msg.summary,
256
298
  description: msg.description,
257
- contentType: msg.contentType,
299
+ contentType,
300
+ contentTypeInherited: hasOwnContentType ? void 0 : true,
258
301
  schemaFormat: msg.schemaFormat,
259
302
  payload: msg.payload,
260
303
  headers: msg.headers,
261
304
  correlationId: msg.correlationId,
262
305
  tags: msg.tags,
263
306
  examples: msg.examples,
264
- bindings: msg.bindings
307
+ bindings: msg.bindings,
308
+ externalDocs: msg.externalDocs
265
309
  };
266
310
  }
267
- function extractComponents(api) {
311
+ function extractComponents(api, isV3, defaultContentType) {
268
312
  const components = api.components;
269
313
  const rawMessages = api.components?.messages ?? {};
270
314
  const messages = {};
271
315
  for (const [name, msg] of Object.entries(rawMessages)) {
272
- messages[name] = convertMessage(msg);
316
+ messages[name] = convertMessage(msg, isV3, defaultContentType);
273
317
  }
274
318
  return {
275
319
  schemas: api.components?.schemas ?? {},
@@ -298,6 +342,40 @@ function deriveSecurityNames(raw, resolved) {
298
342
  }
299
343
  return names.length > 0 ? names : void 0;
300
344
  }
345
+ function deriveSecurityRequirements(raw, resolved, isV3) {
346
+ const rawArr = raw ?? [];
347
+ const resArr = resolved ?? [];
348
+ const count = Math.max(rawArr.length, resArr.length);
349
+ if (count === 0) return void 0;
350
+ const out = [];
351
+ for (let i = 0; i < count; i++) {
352
+ const rawEntry = rawArr[i];
353
+ const resEntry = resArr[i];
354
+ if (isV3) {
355
+ let name;
356
+ if (rawEntry && typeof rawEntry === "object" && typeof rawEntry.$ref === "string") {
357
+ name = decodeJsonPointerSegment(rawEntry.$ref.split("/").pop());
358
+ } else if (resEntry && typeof resEntry.type === "string") {
359
+ name = resEntry.type;
360
+ }
361
+ if (name === void 0) continue;
362
+ const rawScopes = rawEntry?.scopes;
363
+ const resScopes = resEntry?.scopes;
364
+ const scopesSource = Array.isArray(rawScopes) ? rawScopes : Array.isArray(resScopes) ? resScopes : [];
365
+ const scopes = scopesSource.map(String);
366
+ out.push([{ name, scopes }]);
367
+ } else {
368
+ const map = rawEntry ?? resEntry;
369
+ if (!map || typeof map !== "object") continue;
370
+ const inner = Object.entries(map).map(([name, scopes]) => ({
371
+ name,
372
+ scopes: Array.isArray(scopes) ? scopes.map(String) : []
373
+ }));
374
+ if (inner.length > 0) out.push(inner);
375
+ }
376
+ }
377
+ return out.length > 0 ? out : void 0;
378
+ }
301
379
  function parseSpecString(input) {
302
380
  const trimmed = input.trim();
303
381
  if (trimmed.startsWith("{")) {
@@ -316,6 +394,38 @@ function useAsyncApiSpec(spec) {
316
394
  return useSpecFetcher(spec, parser);
317
395
  }
318
396
 
397
+ function ExternalDocsLink({ externalDocs, context, className }) {
398
+ const label = externalDocs.description ?? "External docs";
399
+ const ariaLabel = `${context ? `${context} external docs` : "External docs"}, opens in new tab`;
400
+ return /* @__PURE__ */ jsxs(
401
+ "a",
402
+ {
403
+ href: externalDocs.url,
404
+ target: "_blank",
405
+ rel: "noopener noreferrer",
406
+ "aria-label": ariaLabel,
407
+ className: cx(linkStyle$1, className),
408
+ children: [
409
+ label,
410
+ /* @__PURE__ */ jsx(Icon, { name: "external-link", size: "0.875em" })
411
+ ]
412
+ }
413
+ );
414
+ }
415
+ const linkStyle$1 = css({
416
+ display: "inline-flex",
417
+ alignItems: "center",
418
+ gap: "0.25rem",
419
+ fontSize: "var(--omnispec-font-size-xs)",
420
+ color: "var(--omnispec-fg-link)",
421
+ textDecoration: "none",
422
+ minWidth: 0,
423
+ overflowWrap: "anywhere",
424
+ "&:hover": {
425
+ textDecoration: "underline"
426
+ }
427
+ });
428
+
319
429
  const containerStyle$4 = css({
320
430
  marginBottom: "2rem",
321
431
  paddingBottom: "1.5rem",
@@ -386,7 +496,7 @@ function AsyncOverview({ spec }) {
386
496
  "License: ",
387
497
  spec.license.url ? /* @__PURE__ */ jsx("a", { href: spec.license.url, target: "_blank", rel: "noopener noreferrer", className: linkStyle, children: spec.license.name }) : spec.license.name
388
498
  ] }),
389
- spec.externalDocs && /* @__PURE__ */ jsx("div", { className: metaStyle, children: /* @__PURE__ */ jsx("a", { href: spec.externalDocs.url, target: "_blank", rel: "noopener noreferrer", className: linkStyle, children: spec.externalDocs.description ?? "External Documentation" }) })
499
+ spec.externalDocs && /* @__PURE__ */ jsx("div", { className: metaStyle, children: /* @__PURE__ */ jsx(ExternalDocsLink, { externalDocs: spec.externalDocs, context: spec.title ?? "API" }) })
390
500
  ] });
391
501
  }
392
502
 
@@ -434,16 +544,91 @@ function ProtocolBadge({ protocol, version }) {
434
544
  }
435
545
 
436
546
  function humanizeField(field) {
547
+ if (/^x-/i.test(field)) return field;
437
548
  const spaced = field.replace(/[_-]+/g, " ").replace(/([a-z0-9])([A-Z])/g, "$1 $2").trim();
438
549
  return spaced.charAt(0).toUpperCase() + spaced.slice(1);
439
550
  }
551
+ function isPlainObject(value) {
552
+ return typeof value === "object" && value !== null && !Array.isArray(value);
553
+ }
554
+ const JSON_SCHEMA_TYPES = /* @__PURE__ */ new Set([
555
+ "string",
556
+ "number",
557
+ "integer",
558
+ "boolean",
559
+ "object",
560
+ "array",
561
+ "null"
562
+ ]);
563
+ function hasSchemaType(value) {
564
+ const t = value.type;
565
+ if (typeof t === "string") return JSON_SCHEMA_TYPES.has(t);
566
+ if (Array.isArray(t)) return t.every((x) => typeof x === "string" && JSON_SCHEMA_TYPES.has(x));
567
+ return false;
568
+ }
569
+ function isJsonSchema(value) {
570
+ return "properties" in value || "enum" in value || "items" in value || hasSchemaType(value);
571
+ }
572
+ function isScalarArray(value) {
573
+ return value.every(
574
+ (item) => item === null || typeof item !== "object"
575
+ );
576
+ }
440
577
  function renderValue(value) {
441
578
  if (value === null) return /* @__PURE__ */ jsx("span", { className: mutedStyle, children: "null" });
442
579
  if (typeof value === "boolean") return /* @__PURE__ */ jsx("code", { className: codeStyle, children: value ? "true" : "false" });
443
580
  if (typeof value === "number") return /* @__PURE__ */ jsx("code", { className: codeStyle, children: String(value) });
444
581
  if (typeof value === "string") return /* @__PURE__ */ jsx("span", { children: value });
582
+ if (Array.isArray(value)) {
583
+ if (value.length === 0) return /* @__PURE__ */ jsx("span", { className: mutedStyle, children: "none" });
584
+ if (isScalarArray(value)) {
585
+ return /* @__PURE__ */ jsx("span", { children: value.map((item) => String(item)).join(", ") });
586
+ }
587
+ return /* @__PURE__ */ jsx("code", { className: jsonStyle, children: JSON.stringify(value, null, 2) });
588
+ }
589
+ if (isPlainObject(value)) {
590
+ if (isJsonSchema(value)) {
591
+ return /* @__PURE__ */ jsx(SchemaValue, { schema: value });
592
+ }
593
+ const nested = Object.entries(value).filter(([, v]) => v !== void 0);
594
+ if (nested.length === 0) return /* @__PURE__ */ jsx("span", { className: mutedStyle, children: "none" });
595
+ return /* @__PURE__ */ jsx("div", { className: nestedStyle, children: /* @__PURE__ */ jsx(FieldRows, { fields: nested }) });
596
+ }
445
597
  return /* @__PURE__ */ jsx("code", { className: jsonStyle, children: JSON.stringify(value) });
446
598
  }
599
+ function SchemaValue({ schema }) {
600
+ const properties = isPlainObject(schema.properties) ? schema.properties : void 0;
601
+ if (properties && Object.keys(properties).length > 0) {
602
+ return /* @__PURE__ */ jsx("div", { className: schemaTableStyle, children: Object.entries(properties).map(([name, propSchema]) => /* @__PURE__ */ jsx(
603
+ SchemaRow,
604
+ {
605
+ name,
606
+ schema: isPlainObject(propSchema) ? propSchema : {}
607
+ },
608
+ name
609
+ )) });
610
+ }
611
+ return /* @__PURE__ */ jsx("div", { className: schemaTableStyle, children: /* @__PURE__ */ jsx(SchemaLeaf, { schema }) });
612
+ }
613
+ function SchemaRow({ name, schema }) {
614
+ return /* @__PURE__ */ jsxs("div", { className: schemaRowStyle, children: [
615
+ /* @__PURE__ */ jsx("code", { className: schemaNameStyle$1, children: name }),
616
+ /* @__PURE__ */ jsx(SchemaLeaf, { schema })
617
+ ] });
618
+ }
619
+ function SchemaLeaf({ schema }) {
620
+ const type = typeof schema.type === "string" ? schema.type : void 0;
621
+ const description = typeof schema.description === "string" ? schema.description : void 0;
622
+ const enumValues = Array.isArray(schema.enum) ? schema.enum : void 0;
623
+ return /* @__PURE__ */ jsxs("div", { className: schemaLeafStyle, children: [
624
+ type && /* @__PURE__ */ jsx("span", { className: schemaTypeStyle, children: type }),
625
+ description && /* @__PURE__ */ jsx("span", { className: schemaDescStyle, children: description }),
626
+ enumValues && enumValues.length > 0 && /* @__PURE__ */ jsxs("span", { className: enumWrapStyle, children: [
627
+ /* @__PURE__ */ jsx("span", { className: enumLabelStyle, children: "Allowed:" }),
628
+ enumValues.map((v, i) => /* @__PURE__ */ jsx("code", { className: enumItemStyle, children: String(v) }, i))
629
+ ] })
630
+ ] });
631
+ }
447
632
  function FieldRows({ fields }) {
448
633
  if (fields.length === 0) return null;
449
634
  return /* @__PURE__ */ jsx("dl", { className: listStyle$1, children: fields.map(([field, value]) => /* @__PURE__ */ jsxs("div", { className: rowStyle$1, children: [
@@ -455,7 +640,8 @@ const listStyle$1 = css({
455
640
  display: "grid",
456
641
  gridTemplateColumns: "max-content 1fr",
457
642
  gap: "0.25rem 1rem",
458
- margin: "0.25rem 0 0"
643
+ margin: "0.25rem 0 0",
644
+ minWidth: 0
459
645
  });
460
646
  const rowStyle$1 = css({ display: "contents" });
461
647
  const nameStyle$1 = css({
@@ -468,6 +654,7 @@ const valueStyle = css({
468
654
  color: "var(--omnispec-fg-primary)",
469
655
  margin: 0,
470
656
  minWidth: 0,
657
+ overflowWrap: "anywhere",
471
658
  wordBreak: "break-word"
472
659
  });
473
660
  const codeStyle = css({
@@ -475,14 +662,82 @@ const codeStyle = css({
475
662
  fontSize: "var(--omnispec-font-size-xs)"
476
663
  });
477
664
  const jsonStyle = css({
665
+ display: "block",
478
666
  fontFamily: "var(--omnispec-font-mono)",
479
667
  fontSize: "var(--omnispec-font-size-xs)",
480
668
  color: "var(--omnispec-fg-code)",
481
- wordBreak: "break-all"
669
+ margin: 0,
670
+ whiteSpace: "pre",
671
+ overflowX: "auto",
672
+ maxWidth: "100%",
673
+ overflowWrap: "anywhere"
482
674
  });
483
675
  const mutedStyle = css({
484
676
  color: "var(--omnispec-fg-muted)"
485
677
  });
678
+ const nestedStyle = css({
679
+ minWidth: 0,
680
+ paddingLeft: "0.5rem",
681
+ marginTop: "0.125rem",
682
+ boxShadow: "inset 2px 0 0 0 var(--omnispec-border-color)"
683
+ });
684
+ const schemaTableStyle = css({
685
+ display: "flex",
686
+ flexDirection: "column",
687
+ gap: "0.25rem",
688
+ minWidth: 0
689
+ });
690
+ const schemaRowStyle = css({
691
+ display: "flex",
692
+ flexDirection: "column",
693
+ gap: "0.125rem",
694
+ minWidth: 0
695
+ });
696
+ const schemaNameStyle$1 = css({
697
+ fontFamily: "var(--omnispec-font-mono)",
698
+ fontSize: "var(--omnispec-font-size-xs)",
699
+ fontWeight: 600,
700
+ color: "var(--omnispec-fg-primary)",
701
+ overflowWrap: "anywhere"
702
+ });
703
+ const schemaLeafStyle = css({
704
+ display: "flex",
705
+ flexWrap: "wrap",
706
+ alignItems: "baseline",
707
+ gap: "0.375rem",
708
+ minWidth: 0
709
+ });
710
+ const schemaTypeStyle = css({
711
+ fontFamily: "var(--omnispec-font-mono)",
712
+ fontSize: "var(--omnispec-font-size-xs)",
713
+ color: "var(--omnispec-fg-code)"
714
+ });
715
+ const schemaDescStyle = css({
716
+ fontSize: "var(--omnispec-font-size-xs)",
717
+ color: "var(--omnispec-fg-secondary)",
718
+ overflowWrap: "anywhere",
719
+ wordBreak: "break-word"
720
+ });
721
+ const enumWrapStyle = css({
722
+ display: "flex",
723
+ flexWrap: "wrap",
724
+ alignItems: "baseline",
725
+ gap: "0.25rem",
726
+ minWidth: 0
727
+ });
728
+ const enumLabelStyle = css({
729
+ fontSize: "var(--omnispec-font-size-xs)",
730
+ color: "var(--omnispec-fg-muted)"
731
+ });
732
+ const enumItemStyle = css({
733
+ fontFamily: "var(--omnispec-font-mono)",
734
+ fontSize: "var(--omnispec-font-size-xs)",
735
+ color: "var(--omnispec-fg-code)",
736
+ backgroundColor: "var(--omnispec-bg-tertiary)",
737
+ borderRadius: "var(--omnispec-border-radius)",
738
+ padding: "0.02rem 0.3rem",
739
+ overflowWrap: "anywhere"
740
+ });
486
741
 
487
742
  const HIDDEN_KEYS = /* @__PURE__ */ new Set(["bindingVersion"]);
488
743
  function BindingsSection({ bindings, title = "Bindings" }) {
@@ -533,14 +788,21 @@ const emptyStyle = css({
533
788
  color: "var(--omnispec-fg-muted)"
534
789
  });
535
790
 
536
- function SecurityRequirementBadges({ names, label = "Security" }) {
537
- if (!names || names.length === 0) return null;
791
+ function SecurityRequirementBadges({ requirements, label = "Security" }) {
792
+ if (!requirements || requirements.length === 0) return null;
538
793
  return /* @__PURE__ */ jsxs("div", { className: rowStyle, children: [
539
794
  /* @__PURE__ */ jsx("span", { className: labelStyle, children: label }),
540
- names.map((name) => /* @__PURE__ */ jsxs("a", { href: `#security-${name}`, className: badgeStyle, children: [
541
- /* @__PURE__ */ jsx(Icon, { name: "lock", size: "0.625rem", strokeWidth: 2.5 }),
542
- name
543
- ] }, name))
795
+ requirements.map((alternative, altIndex) => /* @__PURE__ */ jsxs(Fragment, { children: [
796
+ altIndex > 0 && /* @__PURE__ */ jsx("span", { className: orStyle, children: "OR" }),
797
+ alternative.map((scheme) => /* @__PURE__ */ jsxs("a", { href: `#security-${scheme.name}`, className: badgeStyle, children: [
798
+ /* @__PURE__ */ jsx(Icon, { name: "lock", size: "0.625rem", strokeWidth: 2.5 }),
799
+ scheme.name,
800
+ scheme.scopes.length > 0 && /* @__PURE__ */ jsxs("span", { className: scopesStyle$1, children: [
801
+ /* @__PURE__ */ jsx("span", { className: scopeSepStyle, children: "\xB7" }),
802
+ scheme.scopes.join(", ")
803
+ ] })
804
+ ] }, scheme.name))
805
+ ] }, altIndex))
544
806
  ] });
545
807
  }
546
808
  const rowStyle = css({
@@ -552,11 +814,20 @@ const rowStyle = css({
552
814
  });
553
815
  const labelStyle = css({
554
816
  fontSize: "var(--omnispec-font-size-xxs)",
817
+ lineHeight: 1.5,
555
818
  fontWeight: 600,
556
819
  textTransform: "uppercase",
557
820
  letterSpacing: "0.05em",
558
821
  color: "var(--omnispec-fg-muted)"
559
822
  });
823
+ const orStyle = css({
824
+ fontSize: "var(--omnispec-font-size-xxs)",
825
+ lineHeight: 1.5,
826
+ fontWeight: 700,
827
+ textTransform: "uppercase",
828
+ letterSpacing: "0.05em",
829
+ color: "var(--omnispec-fg-muted)"
830
+ });
560
831
  const badgeStyle = css({
561
832
  display: "inline-flex",
562
833
  alignItems: "center",
@@ -573,6 +844,15 @@ const badgeStyle = css({
573
844
  textDecoration: "underline"
574
845
  }
575
846
  });
847
+ const scopesStyle$1 = css({
848
+ display: "inline-flex",
849
+ alignItems: "center",
850
+ gap: "0.3125rem",
851
+ color: "var(--omnispec-fg-secondary)"
852
+ });
853
+ const scopeSepStyle = css({
854
+ color: "var(--omnispec-fg-muted)"
855
+ });
576
856
 
577
857
  const containerStyle$2 = css({
578
858
  marginBottom: "1.5rem"
@@ -675,9 +955,9 @@ const varTokenStyle = css({
675
955
  "&::after": { content: '"}"' }
676
956
  });
677
957
  function highlightVariables(url) {
678
- const parts = url.split(/(\{[^}]+\})/g);
958
+ const parts = url.split(/(\{[^{}]+\})/g);
679
959
  return parts.map(
680
- (part, i) => /^\{[^}]+\}$/.test(part) ? /* @__PURE__ */ jsx("span", { className: varTokenStyle, children: part.slice(1, -1) }, i) : /* @__PURE__ */ jsx("span", { children: part }, i)
960
+ (part, i) => /^\{[^{}]+\}$/.test(part) ? /* @__PURE__ */ jsx("span", { className: varTokenStyle, children: part.slice(1, -1) }, i) : /* @__PURE__ */ jsx("span", { children: part }, i)
681
961
  );
682
962
  }
683
963
  function ServerCard({ server }) {
@@ -700,7 +980,7 @@ function ServerCard({ server }) {
700
980
  ] }),
701
981
  variable.description && /* @__PURE__ */ jsx("span", { className: varDescStyle, children: variable.description })
702
982
  ] }, name)) }),
703
- /* @__PURE__ */ jsx(SecurityRequirementBadges, { names: server.securityNames }),
983
+ /* @__PURE__ */ jsx(SecurityRequirementBadges, { requirements: server.securityRequirements ?? [] }),
704
984
  /* @__PURE__ */ jsx(BindingsSection, { bindings: server.bindings, title: "Server Bindings" })
705
985
  ] });
706
986
  }
@@ -710,7 +990,7 @@ function ServerList({ servers }) {
710
990
  const activeIndex = Math.min(selected, servers.length - 1);
711
991
  return /* @__PURE__ */ jsxs("div", { className: cx("omnispec-async-servers", containerStyle$2), children: [
712
992
  /* @__PURE__ */ jsx("h3", { className: titleStyle$3, children: "Servers" }),
713
- servers.length > 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
993
+ servers.length > 1 ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
714
994
  /* @__PURE__ */ jsx("div", { className: tabStripStyle, role: "tablist", "aria-label": "Servers", children: servers.map((server, idx) => /* @__PURE__ */ jsx(
715
995
  "button",
716
996
  {
@@ -805,7 +1085,15 @@ function primitive(name) {
805
1085
 
806
1086
  function MessagePayload({ message, idx }) {
807
1087
  const rawPayload = message.payload;
808
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1088
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
1089
+ message.tags && message.tags.length > 0 && /* @__PURE__ */ jsx("div", { className: tagChipsStyle$2, children: message.tags.map((tag) => /* @__PURE__ */ jsx("span", { className: tagChipStyle$2, title: tag.description, children: tag.name }, tag.name)) }),
1090
+ message.externalDocs && /* @__PURE__ */ jsx("div", { className: externalDocsStyle, children: /* @__PURE__ */ jsx(
1091
+ ExternalDocsLink,
1092
+ {
1093
+ externalDocs: message.externalDocs,
1094
+ context: message.name ?? message.title ?? "message"
1095
+ }
1096
+ ) }),
809
1097
  message.schemaFormat && /* @__PURE__ */ jsx("span", { className: schemaFormatBadgeStyle, children: message.schemaFormat }),
810
1098
  rawPayload && /* @__PURE__ */ jsx(PayloadBody, { rawPayload, schemaFormat: message.schemaFormat, message, idx })
811
1099
  ] });
@@ -825,7 +1113,14 @@ function PayloadBody({
825
1113
  ] })
826
1114
  ] });
827
1115
  }
828
- const schema = detectSchemaFormat(schemaFormat) === "avro" ? avroToJsonSchema(rawPayload) : rawPayload;
1116
+ const format = detectSchemaFormat(schemaFormat);
1117
+ if (format === "protobuf") {
1118
+ return /* @__PURE__ */ jsxs("div", { children: [
1119
+ /* @__PURE__ */ jsx(CodeBlock, { code: JSON.stringify(rawPayload, null, 2), language: "json" }),
1120
+ /* @__PURE__ */ jsx("p", { className: proNoteStyle, children: "Full Protobuf schema rendering is available in Pro." })
1121
+ ] });
1122
+ }
1123
+ const schema = format === "avro" ? avroToJsonSchema(rawPayload) : rawPayload;
829
1124
  return /* @__PURE__ */ jsx(
830
1125
  Tabs,
831
1126
  {
@@ -854,11 +1149,28 @@ function MessageExample({ message, schema }) {
854
1149
  const active = named.find((ex) => ex.name === selectedName) ?? named[0];
855
1150
  const exampleSchema = schema ?? message.payload;
856
1151
  const code = active?.value !== void 0 ? JSON.stringify(active.value, null, 2) : exampleSchema ? JSON.stringify(generateExample(exampleSchema), null, 2) : "{}";
857
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1152
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
858
1153
  /* @__PURE__ */ jsx(ExampleSelector, { examples: named, selectedName: selectedName || (named[0]?.name ?? ""), onSelect: setSelectedName }),
859
1154
  /* @__PURE__ */ jsx(CodeBlock, { code, language: "json" })
860
1155
  ] });
861
1156
  }
1157
+ const tagChipsStyle$2 = css({
1158
+ display: "flex",
1159
+ flexWrap: "wrap",
1160
+ gap: "0.25rem",
1161
+ marginBottom: "0.5rem"
1162
+ });
1163
+ const tagChipStyle$2 = css({
1164
+ fontSize: "var(--omnispec-font-size-xxs)",
1165
+ fontFamily: "var(--omnispec-font-mono)",
1166
+ color: "var(--omnispec-fg-secondary)",
1167
+ backgroundColor: "var(--omnispec-bg-tertiary)",
1168
+ padding: "1px 0.5rem",
1169
+ borderRadius: "0.625rem"
1170
+ });
1171
+ const externalDocsStyle = css({
1172
+ marginBottom: "0.5rem"
1173
+ });
862
1174
  const schemaFormatBadgeStyle = css({
863
1175
  display: "inline-block",
864
1176
  fontFamily: "var(--omnispec-font-mono)",
@@ -869,6 +1181,12 @@ const schemaFormatBadgeStyle = css({
869
1181
  borderRadius: "var(--omnispec-border-radius)",
870
1182
  marginBottom: "0.5rem"
871
1183
  });
1184
+ const proNoteStyle = css({
1185
+ margin: "0.375rem 0 0",
1186
+ fontSize: "var(--omnispec-font-size-xxs)",
1187
+ color: "var(--omnispec-fg-muted)",
1188
+ fontStyle: "italic"
1189
+ });
872
1190
  const unresolvedRefStyle = css({
873
1191
  display: "flex",
874
1192
  alignItems: "center",
@@ -884,22 +1202,22 @@ const unresolvedRefCodeStyle = css({
884
1202
  fontSize: "var(--omnispec-font-size-xs)"
885
1203
  });
886
1204
 
887
- const actionLabels = {
1205
+ const actionLabels$1 = {
888
1206
  publish: "PUB",
889
1207
  subscribe: "SUB",
890
1208
  send: "SEND",
891
1209
  receive: "RECV"
892
1210
  };
893
- const actionColors = {
1211
+ const actionColors$1 = {
894
1212
  publish: "var(--omnispec-color-publish)",
895
1213
  subscribe: "var(--omnispec-color-subscribe)",
896
1214
  send: "var(--omnispec-color-publish)",
897
1215
  receive: "var(--omnispec-color-subscribe)"
898
1216
  };
899
- function ChannelDetail({ channel, id, expandAll, expandGeneration }) {
1217
+ function ChannelDetail({ channel, id, expandAll, expandGeneration, onTagClick }) {
900
1218
  const primaryAction = channel.operations[0]?.action;
901
- const primaryLabel = actionLabels[primaryAction] ?? primaryAction?.toUpperCase() ?? "";
902
- const primaryColor = actionColors[primaryAction] ?? "var(--omnispec-fg-muted)";
1219
+ const primaryLabel = actionLabels$1[primaryAction] ?? primaryAction?.toUpperCase() ?? "";
1220
+ const primaryColor = actionColors$1[primaryAction] ?? "var(--omnispec-fg-muted)";
903
1221
  return /* @__PURE__ */ jsxs(
904
1222
  ExpandableCard,
905
1223
  {
@@ -911,21 +1229,22 @@ function ChannelDetail({ channel, id, expandAll, expandGeneration }) {
911
1229
  children: [
912
1230
  /* @__PURE__ */ jsx(MethodBar, { label: primaryLabel, path: channel.address, color: primaryColor }),
913
1231
  /* @__PURE__ */ jsxs("div", { className: bodyStyle, children: [
914
- channel.description && /* @__PURE__ */ jsx("div", { className: sectionStyle, children: /* @__PURE__ */ jsx(MarkdownRenderer, { content: channel.description }) }),
915
- channel.parameters && Object.keys(channel.parameters).length > 0 && /* @__PURE__ */ jsxs("div", { className: sectionStyle, children: [
916
- /* @__PURE__ */ jsx("h4", { className: sectionTitleStyle, children: "Parameters" }),
917
- /* @__PURE__ */ jsx("div", { className: paramListStyle, children: Object.entries(channel.parameters).map(([name, param]) => {
1232
+ channel.description && /* @__PURE__ */ jsx("div", { className: sectionStyle$1, children: /* @__PURE__ */ jsx(MarkdownRenderer, { content: channel.description }) }),
1233
+ channel.externalDocs && /* @__PURE__ */ jsx("div", { className: sectionStyle$1, children: /* @__PURE__ */ jsx(ExternalDocsLink, { externalDocs: channel.externalDocs, context: channel.address }) }),
1234
+ channel.parameters && Object.keys(channel.parameters).length > 0 && /* @__PURE__ */ jsxs("div", { className: sectionStyle$1, children: [
1235
+ /* @__PURE__ */ jsx("h4", { className: sectionTitleStyle$1, children: "Parameters" }),
1236
+ /* @__PURE__ */ jsx("div", { className: paramListStyle$1, children: Object.entries(channel.parameters).map(([name, param]) => {
918
1237
  const schema = param.schema ?? {};
919
1238
  const paramType = schema.type;
920
1239
  const paramFormat = schema.format;
921
1240
  const paramEnum = schema.enum;
922
1241
  const constraintBadges = buildConstraints(schema);
923
- return /* @__PURE__ */ jsxs("div", { className: paramRowStyle, children: [
924
- /* @__PURE__ */ jsxs("div", { className: paramHeaderStyle, children: [
925
- /* @__PURE__ */ jsx("span", { className: paramNameStyle, children: name }),
926
- paramType && /* @__PURE__ */ jsx("pre", { className: typeBadgeStyle$1, children: paramType })
1242
+ return /* @__PURE__ */ jsxs("div", { className: paramRowStyle$1, children: [
1243
+ /* @__PURE__ */ jsxs("div", { className: paramHeaderStyle$1, children: [
1244
+ /* @__PURE__ */ jsx("span", { className: paramNameStyle$1, children: name }),
1245
+ paramType && /* @__PURE__ */ jsx("pre", { className: typeBadgeStyle$2, children: paramType })
927
1246
  ] }),
928
- (paramFormat || constraintBadges.length > 0 || paramEnum && paramEnum.length > 0) && /* @__PURE__ */ jsxs("div", { className: paramConstraintsStyle, children: [
1247
+ (paramFormat || constraintBadges.length > 0 || paramEnum && paramEnum.length > 0) && /* @__PURE__ */ jsxs("div", { className: paramConstraintsStyle$1, children: [
929
1248
  paramFormat && /* @__PURE__ */ jsx(SchemaBadge, { variant: "constraint", children: paramFormat }),
930
1249
  constraintBadges.map((c) => /* @__PURE__ */ jsx(SchemaBadge, { variant: "constraint", children: c }, c)),
931
1250
  paramEnum && paramEnum.length > 0 && /* @__PURE__ */ jsxs(SchemaBadge, { variant: "enum", children: [
@@ -933,31 +1252,60 @@ function ChannelDetail({ channel, id, expandAll, expandGeneration }) {
933
1252
  paramEnum.map(String).join(" | ")
934
1253
  ] })
935
1254
  ] }),
936
- param.description && /* @__PURE__ */ jsx("p", { className: paramDescStyle, children: param.description })
1255
+ param.description && /* @__PURE__ */ jsx("p", { className: paramDescStyle$1, children: param.description })
937
1256
  ] }, name);
938
1257
  }) })
939
1258
  ] }),
940
1259
  /* @__PURE__ */ jsx(BindingsSection, { bindings: channel.bindings, title: "Channel Bindings" }),
941
1260
  channel.operations.map((op, idx) => /* @__PURE__ */ jsxs("div", { id: id ? `${id}-op-${idx}` : void 0, className: operationStyle, children: [
942
- /* @__PURE__ */ jsxs("div", { className: opHeaderStyle, children: [
1261
+ /* @__PURE__ */ jsxs("div", { className: opHeaderStyle$1, children: [
943
1262
  /* @__PURE__ */ jsx(
944
1263
  "span",
945
1264
  {
946
- className: cx(actionBadgeBase, css({
947
- backgroundColor: actionColors[op.action] ?? "var(--omnispec-fg-muted)"
1265
+ className: cx(actionBadgeBase$1, css({
1266
+ backgroundColor: actionColors$1[op.action] ?? "var(--omnispec-fg-muted)"
948
1267
  })),
949
- children: actionLabels[op.action] ?? op.action.toUpperCase()
1268
+ children: actionLabels$1[op.action] ?? op.action.toUpperCase()
950
1269
  }
951
1270
  ),
952
- op.operationId && /* @__PURE__ */ jsx("span", { className: opIdStyle, children: op.operationId }),
953
- op.summary && /* @__PURE__ */ jsx("span", { className: opSummaryStyle, children: op.summary })
1271
+ op.operationId && /* @__PURE__ */ jsx("span", { className: opIdStyle$1, children: op.operationId }),
1272
+ op.title && /* @__PURE__ */ jsx("span", { className: opTitleStyle$1, children: op.title }),
1273
+ op.summary && /* @__PURE__ */ jsx("span", { className: opSummaryStyle$1, children: op.summary })
954
1274
  ] }),
955
- op.tags && op.tags.length > 0 && /* @__PURE__ */ jsx("div", { className: tagChipsStyle, children: op.tags.map((tag) => /* @__PURE__ */ jsx("span", { className: tagChipStyle, title: tag.description, children: tag.name }, tag.name)) }),
956
- op.description && /* @__PURE__ */ jsx("div", { className: sectionStyle, children: /* @__PURE__ */ jsx(MarkdownRenderer, { content: op.description }) }),
957
- /* @__PURE__ */ jsx(SecurityRequirementBadges, { names: op.securityNames }),
1275
+ op.tags && op.tags.length > 0 && /* @__PURE__ */ jsx("div", { className: tagChipsStyle$1, children: op.tags.map(
1276
+ (tag) => onTagClick ? /* @__PURE__ */ jsx(
1277
+ "button",
1278
+ {
1279
+ type: "button",
1280
+ className: tagChipButtonStyle$1,
1281
+ title: tag.description,
1282
+ onClick: () => onTagClick(tag.name),
1283
+ children: tag.name
1284
+ },
1285
+ tag.name
1286
+ ) : /* @__PURE__ */ jsx("span", { className: tagChipStyle$1, title: tag.description, children: tag.name }, tag.name)
1287
+ ) }),
1288
+ op.description && /* @__PURE__ */ jsx("div", { className: sectionStyle$1, children: /* @__PURE__ */ jsx(MarkdownRenderer, { content: op.description }) }),
1289
+ op.externalDocs && /* @__PURE__ */ jsx("div", { className: opExternalDocsStyle, children: /* @__PURE__ */ jsx(
1290
+ ExternalDocsLink,
1291
+ {
1292
+ externalDocs: op.externalDocs,
1293
+ context: op.operationId ?? op.summary ?? "operation"
1294
+ }
1295
+ ) }),
1296
+ /* @__PURE__ */ jsx(SecurityRequirementBadges, { requirements: op.securityRequirements ?? [] }),
958
1297
  /* @__PURE__ */ jsx(OperationMessages, { operation: op, idx }),
959
- op.reply && op.reply.messages.length > 0 && /* @__PURE__ */ jsxs("div", { className: replyStyle, children: [
1298
+ op.reply && (op.reply.messages.length > 0 || op.reply.address || op.reply.channelName) && /* @__PURE__ */ jsxs("div", { className: replyStyle$1, children: [
960
1299
  /* @__PURE__ */ jsx("h4", { className: replyTitleStyle, children: "Reply" }),
1300
+ op.reply.channelName && /* @__PURE__ */ jsxs("div", { className: replyMetaRowStyle, children: [
1301
+ /* @__PURE__ */ jsx("span", { className: replyMetaLabelStyle, children: "channel" }),
1302
+ /* @__PURE__ */ jsx("code", { className: replyMetaValueStyle, children: op.reply.channelName })
1303
+ ] }),
1304
+ op.reply.address && (op.reply.address.location || op.reply.address.description) && /* @__PURE__ */ jsxs("div", { className: replyMetaRowStyle, children: [
1305
+ /* @__PURE__ */ jsx("span", { className: replyMetaLabelStyle, children: "address" }),
1306
+ op.reply.address.location && /* @__PURE__ */ jsx("code", { className: replyMetaValueStyle, children: op.reply.address.location }),
1307
+ op.reply.address.description && /* @__PURE__ */ jsx("span", { className: replyMetaDescStyle, children: op.reply.address.description })
1308
+ ] }),
961
1309
  op.reply.messages.map((replyMsg, i) => /* @__PURE__ */ jsx(MessageView, { message: replyMsg, idx: `${idx}-reply-${i}` }, i))
962
1310
  ] }),
963
1311
  /* @__PURE__ */ jsx(BindingsSection, { bindings: op.bindings, title: "Operation Bindings" })
@@ -975,7 +1323,7 @@ function OperationMessages({ operation, idx }) {
975
1323
  const [selectedIndex, setSelectedIndex] = useState(0);
976
1324
  if (messages.length === 0) return null;
977
1325
  const active = messages[Math.min(selectedIndex, messages.length - 1)];
978
- return /* @__PURE__ */ jsxs("div", { className: sectionStyle, children: [
1326
+ return /* @__PURE__ */ jsxs("div", { className: sectionStyle$1, children: [
979
1327
  messages.length > 1 && /* @__PURE__ */ jsxs("div", { className: messageSelectorStyle, children: [
980
1328
  /* @__PURE__ */ jsx("label", { htmlFor: `msg-select-${idx}`, className: messageSelectorLabelStyle, children: "Message" }),
981
1329
  /* @__PURE__ */ jsx(
@@ -998,23 +1346,23 @@ function OperationMessages({ operation, idx }) {
998
1346
  }
999
1347
  function MessageView({ message, idx }) {
1000
1348
  return /* @__PURE__ */ jsxs("div", { children: [
1001
- /* @__PURE__ */ jsxs("h4", { className: sectionTitleStyle, children: [
1349
+ /* @__PURE__ */ jsxs("h4", { className: sectionTitleStyle$1, children: [
1002
1350
  "Message",
1003
- (message.title ?? message.name) && /* @__PURE__ */ jsxs("span", { className: messageTitleStyle, children: [
1351
+ (message.title ?? message.name) && /* @__PURE__ */ jsxs("span", { className: messageTitleStyle$1, children: [
1004
1352
  " \u2014 ",
1005
1353
  message.title ?? message.name
1006
1354
  ] })
1007
1355
  ] }),
1008
1356
  message.summary && /* @__PURE__ */ jsx("p", { className: messageSummaryStyle$1, children: message.summary }),
1009
- message.contentType && /* @__PURE__ */ jsx("code", { className: contentTypeStyle$1, children: message.contentType }),
1357
+ message.contentType && /* @__PURE__ */ jsx("code", { className: contentTypeStyle$2, children: message.contentType }),
1010
1358
  /* @__PURE__ */ jsx(MessagePayload, { message, idx }),
1011
1359
  message.correlationId && /* @__PURE__ */ jsxs("div", { className: correlationIdStyle, children: [
1012
1360
  /* @__PURE__ */ jsx("span", { className: correlationIdLabelStyle, children: "correlationId" }),
1013
1361
  /* @__PURE__ */ jsx("code", { className: correlationIdLocationStyle, children: message.correlationId.location }),
1014
1362
  message.correlationId.description && /* @__PURE__ */ jsx("span", { className: correlationIdDescStyle, children: message.correlationId.description })
1015
1363
  ] }),
1016
- message.headers && /* @__PURE__ */ jsxs("div", { className: headersWrapStyle, children: [
1017
- /* @__PURE__ */ jsx("h4", { className: sectionTitleStyle, children: "Headers" }),
1364
+ message.headers && /* @__PURE__ */ jsxs("div", { className: headersWrapStyle$1, children: [
1365
+ /* @__PURE__ */ jsx("h4", { className: sectionTitleStyle$1, children: "Headers" }),
1018
1366
  /* @__PURE__ */ jsx(SchemaTree, { nodes: schemaToNodes(message.headers) })
1019
1367
  ] }),
1020
1368
  /* @__PURE__ */ jsx(BindingsSection, { bindings: message.bindings, title: "Message Bindings" })
@@ -1026,46 +1374,46 @@ const bodyStyle = css({
1026
1374
  padding: "1rem 1.25rem"
1027
1375
  }
1028
1376
  });
1029
- const sectionStyle = css({
1377
+ const sectionStyle$1 = css({
1030
1378
  marginBottom: "1.5rem"
1031
1379
  });
1032
- const sectionTitleStyle = css({
1380
+ const sectionTitleStyle$1 = css({
1033
1381
  margin: "0 0 0.75rem",
1034
1382
  fontSize: "var(--omnispec-font-size-md)",
1035
1383
  fontWeight: 700,
1036
1384
  color: "var(--omnispec-fg-primary)",
1037
1385
  letterSpacing: "0.02em"
1038
1386
  });
1039
- const paramListStyle = css({
1387
+ const paramListStyle$1 = css({
1040
1388
  display: "flex",
1041
1389
  flexDirection: "column"
1042
1390
  });
1043
- const paramRowStyle = css({
1391
+ const paramRowStyle$1 = css({
1044
1392
  padding: "0.75rem 0"
1045
1393
  });
1046
- const paramHeaderStyle = css({
1394
+ const paramHeaderStyle$1 = css({
1047
1395
  display: "flex",
1048
1396
  alignItems: "center",
1049
1397
  gap: "0.5rem",
1050
1398
  flexWrap: "wrap"
1051
1399
  });
1052
- const paramNameStyle = css({
1400
+ const paramNameStyle$1 = css({
1053
1401
  fontSize: "var(--omnispec-font-size-sm)",
1054
1402
  fontWeight: 700,
1055
1403
  backgroundColor: "transparent",
1056
1404
  padding: 0
1057
1405
  });
1058
- const typeBadgeStyle$1 = css({
1406
+ const typeBadgeStyle$2 = css({
1059
1407
  fontSize: "var(--omnispec-font-size-xs)",
1060
1408
  fontWeight: 400
1061
1409
  });
1062
- const paramDescStyle = css({
1410
+ const paramDescStyle$1 = css({
1063
1411
  margin: "0.25rem 0 0",
1064
1412
  fontSize: "var(--omnispec-font-size-base)",
1065
1413
  color: "var(--omnispec-fg-secondary)",
1066
1414
  lineHeight: 1.5
1067
1415
  });
1068
- const paramConstraintsStyle = css({
1416
+ const paramConstraintsStyle$1 = css({
1069
1417
  display: "flex",
1070
1418
  flexWrap: "wrap",
1071
1419
  gap: "0.375rem",
@@ -1075,13 +1423,13 @@ const operationStyle = css({
1075
1423
  padding: "0.75rem 0",
1076
1424
  borderTop: "1px solid var(--omnispec-border-color)"
1077
1425
  });
1078
- const opHeaderStyle = css({
1426
+ const opHeaderStyle$1 = css({
1079
1427
  display: "flex",
1080
1428
  alignItems: "center",
1081
1429
  gap: "0.5rem",
1082
1430
  marginBottom: "0.5rem"
1083
1431
  });
1084
- const actionBadgeBase = css({
1432
+ const actionBadgeBase$1 = css({
1085
1433
  display: "inline-block",
1086
1434
  padding: "0.125rem 0.375rem",
1087
1435
  borderRadius: "0.1875rem",
@@ -1091,17 +1439,25 @@ const actionBadgeBase = css({
1091
1439
  color: "#ffffff",
1092
1440
  letterSpacing: "0.0313rem"
1093
1441
  });
1094
- const opIdStyle = css({
1442
+ const opIdStyle$1 = css({
1095
1443
  fontSize: "var(--omnispec-font-size-sm)",
1096
1444
  fontWeight: 700,
1097
1445
  backgroundColor: "transparent",
1098
1446
  padding: 0
1099
1447
  });
1100
- const opSummaryStyle = css({
1448
+ const opTitleStyle$1 = css({
1449
+ fontSize: "var(--omnispec-font-size-sm)",
1450
+ fontWeight: 600,
1451
+ color: "var(--omnispec-fg-primary)"
1452
+ });
1453
+ const opSummaryStyle$1 = css({
1101
1454
  fontSize: "var(--omnispec-font-size-sm)",
1102
1455
  color: "var(--omnispec-fg-secondary)"
1103
1456
  });
1104
- const messageTitleStyle = css({
1457
+ const opExternalDocsStyle = css({
1458
+ marginBottom: "0.75rem"
1459
+ });
1460
+ const messageTitleStyle$1 = css({
1105
1461
  fontWeight: 400,
1106
1462
  color: "var(--omnispec-fg-primary)"
1107
1463
  });
@@ -1110,7 +1466,7 @@ const messageSummaryStyle$1 = css({
1110
1466
  fontSize: "var(--omnispec-font-size-base)",
1111
1467
  color: "var(--omnispec-fg-secondary)"
1112
1468
  });
1113
- const contentTypeStyle$1 = css({
1469
+ const contentTypeStyle$2 = css({
1114
1470
  fontFamily: "var(--omnispec-font-mono)",
1115
1471
  fontSize: "var(--omnispec-font-size-xs)",
1116
1472
  color: "var(--omnispec-fg-muted)",
@@ -1119,7 +1475,7 @@ const contentTypeStyle$1 = css({
1119
1475
  backgroundColor: "transparent",
1120
1476
  padding: 0
1121
1477
  });
1122
- const headersWrapStyle = css({
1478
+ const headersWrapStyle$1 = css({
1123
1479
  marginTop: "1rem"
1124
1480
  });
1125
1481
  const messageSelectorStyle = css({
@@ -1175,7 +1531,7 @@ const correlationIdDescStyle = css({
1175
1531
  fontSize: "var(--omnispec-font-size-xs)",
1176
1532
  color: "var(--omnispec-fg-secondary)"
1177
1533
  });
1178
- const replyStyle = css({
1534
+ const replyStyle$1 = css({
1179
1535
  marginTop: "1rem",
1180
1536
  paddingLeft: "0.75rem",
1181
1537
  borderLeft: "0.125rem solid var(--omnispec-border-color)"
@@ -1187,6 +1543,320 @@ const replyTitleStyle = css({
1187
1543
  color: "var(--omnispec-fg-primary)",
1188
1544
  letterSpacing: "0.02em"
1189
1545
  });
1546
+ const replyMetaRowStyle = css({
1547
+ display: "flex",
1548
+ alignItems: "center",
1549
+ gap: "0.5rem",
1550
+ flexWrap: "wrap",
1551
+ marginBottom: "0.5rem"
1552
+ });
1553
+ const replyMetaLabelStyle = css({
1554
+ fontSize: "var(--omnispec-font-size-xs)",
1555
+ fontWeight: 700,
1556
+ color: "var(--omnispec-fg-primary)",
1557
+ fontFamily: "var(--omnispec-font-mono)"
1558
+ });
1559
+ const replyMetaValueStyle = css({
1560
+ fontFamily: "var(--omnispec-font-mono)",
1561
+ fontSize: "var(--omnispec-font-size-xs)",
1562
+ color: "var(--omnispec-fg-code)",
1563
+ backgroundColor: "var(--omnispec-bg-tertiary)",
1564
+ padding: "1px 0.375rem",
1565
+ borderRadius: "0.1875rem"
1566
+ });
1567
+ const replyMetaDescStyle = css({
1568
+ fontSize: "var(--omnispec-font-size-xs)",
1569
+ color: "var(--omnispec-fg-secondary)"
1570
+ });
1571
+ const tagChipsStyle$1 = css({
1572
+ display: "flex",
1573
+ flexWrap: "wrap",
1574
+ gap: "0.25rem",
1575
+ marginBottom: "0.5rem"
1576
+ });
1577
+ const tagChipStyle$1 = css({
1578
+ fontSize: "var(--omnispec-font-size-xxs)",
1579
+ fontFamily: "var(--omnispec-font-mono)",
1580
+ color: "var(--omnispec-fg-secondary)",
1581
+ backgroundColor: "var(--omnispec-bg-tertiary)",
1582
+ padding: "1px 0.5rem",
1583
+ borderRadius: "0.625rem"
1584
+ });
1585
+ const tagChipButtonStyle$1 = css({
1586
+ fontSize: "var(--omnispec-font-size-xxs)",
1587
+ fontFamily: "var(--omnispec-font-mono)",
1588
+ color: "var(--omnispec-fg-secondary)",
1589
+ backgroundColor: "var(--omnispec-bg-tertiary)",
1590
+ padding: "1px 0.5rem",
1591
+ borderRadius: "0.625rem",
1592
+ border: "none",
1593
+ cursor: "pointer",
1594
+ "&:hover": {
1595
+ color: "var(--omnispec-fg-primary)"
1596
+ }
1597
+ });
1598
+
1599
+ const actionLabels = {
1600
+ publish: "PUB",
1601
+ subscribe: "SUB",
1602
+ send: "SEND",
1603
+ receive: "RECV"
1604
+ };
1605
+ const actionColors = {
1606
+ publish: "var(--omnispec-color-publish)",
1607
+ subscribe: "var(--omnispec-color-subscribe)",
1608
+ send: "var(--omnispec-color-publish)",
1609
+ receive: "var(--omnispec-color-subscribe)"
1610
+ };
1611
+ function ChannelReferenceDetail({ channel, id, expandAll, expandGeneration, onTagClick }) {
1612
+ const primaryAction = channel.operations[0]?.action;
1613
+ const primaryLabel = actionLabels[primaryAction] ?? primaryAction?.toUpperCase() ?? "";
1614
+ const primaryColor = actionColors[primaryAction] ?? "var(--omnispec-fg-muted)";
1615
+ return /* @__PURE__ */ jsxs(
1616
+ ExpandableCard,
1617
+ {
1618
+ id,
1619
+ title: channel.address,
1620
+ rightLabel: `${channel.operations.length} ${channel.operations.length === 1 ? "operation" : "operations"}`,
1621
+ expandAll,
1622
+ expandGeneration,
1623
+ children: [
1624
+ /* @__PURE__ */ jsx(MethodBar, { label: primaryLabel, path: channel.address, color: primaryColor }),
1625
+ channel.description && /* @__PURE__ */ jsx("div", { className: channelMetaStyle, children: /* @__PURE__ */ jsx(MarkdownRenderer, { content: channel.description }) }),
1626
+ channel.externalDocs && /* @__PURE__ */ jsx("div", { className: channelMetaStyle, children: /* @__PURE__ */ jsx(ExternalDocsLink, { externalDocs: channel.externalDocs, context: channel.address }) }),
1627
+ channel.operations.map((op, idx) => /* @__PURE__ */ jsx("div", { id: id ? `${id}-op-${idx}` : void 0, className: operationWrapStyle, children: /* @__PURE__ */ jsx(
1628
+ ReferenceLayout,
1629
+ {
1630
+ operationId: op.operationId ?? `${channel.name}-op-${idx}`,
1631
+ schema: /* @__PURE__ */ jsx(
1632
+ OperationSchemaColumn,
1633
+ {
1634
+ channel,
1635
+ operation: op,
1636
+ onTagClick
1637
+ }
1638
+ ),
1639
+ samples: /* @__PURE__ */ jsx(OperationSamplesColumn, { operation: op, idx }),
1640
+ tryIt: /* @__PURE__ */ jsx("div", { className: tryItNaStyle, children: "Interactive testing is not available for AsyncAPI protocols." })
1641
+ }
1642
+ ) }, idx))
1643
+ ]
1644
+ }
1645
+ );
1646
+ }
1647
+ function OperationSchemaColumn({
1648
+ channel,
1649
+ operation,
1650
+ onTagClick
1651
+ }) {
1652
+ return /* @__PURE__ */ jsxs("div", { children: [
1653
+ /* @__PURE__ */ jsxs("div", { className: opHeaderStyle, children: [
1654
+ /* @__PURE__ */ jsx(
1655
+ "span",
1656
+ {
1657
+ className: cx(actionBadgeBase, css({
1658
+ backgroundColor: actionColors[operation.action] ?? "var(--omnispec-fg-muted)"
1659
+ })),
1660
+ children: actionLabels[operation.action] ?? operation.action.toUpperCase()
1661
+ }
1662
+ ),
1663
+ operation.operationId && /* @__PURE__ */ jsx("span", { className: opIdStyle, children: operation.operationId }),
1664
+ operation.title && /* @__PURE__ */ jsx("span", { className: opTitleStyle, children: operation.title }),
1665
+ operation.summary && /* @__PURE__ */ jsx("span", { className: opSummaryStyle, children: operation.summary })
1666
+ ] }),
1667
+ operation.tags && operation.tags.length > 0 && /* @__PURE__ */ jsx("div", { className: tagChipsStyle, children: operation.tags.map(
1668
+ (tag) => onTagClick ? /* @__PURE__ */ jsx(
1669
+ "button",
1670
+ {
1671
+ type: "button",
1672
+ className: tagChipButtonStyle,
1673
+ title: tag.description,
1674
+ onClick: () => onTagClick(tag.name),
1675
+ children: tag.name
1676
+ },
1677
+ tag.name
1678
+ ) : /* @__PURE__ */ jsx("span", { className: tagChipStyle, title: tag.description, children: tag.name }, tag.name)
1679
+ ) }),
1680
+ operation.description && /* @__PURE__ */ jsx("div", { className: sectionStyle, children: /* @__PURE__ */ jsx(MarkdownRenderer, { content: operation.description }) }),
1681
+ operation.externalDocs && /* @__PURE__ */ jsx("div", { className: sectionStyle, children: /* @__PURE__ */ jsx(
1682
+ ExternalDocsLink,
1683
+ {
1684
+ externalDocs: operation.externalDocs,
1685
+ context: operation.operationId ?? operation.summary ?? "operation"
1686
+ }
1687
+ ) }),
1688
+ channel.parameters && Object.keys(channel.parameters).length > 0 && /* @__PURE__ */ jsxs("div", { className: sectionStyle, children: [
1689
+ /* @__PURE__ */ jsx("h4", { className: sectionTitleStyle, children: "Parameters" }),
1690
+ /* @__PURE__ */ jsx("div", { className: paramListStyle, children: Object.entries(channel.parameters).map(([name, param]) => {
1691
+ const schema = param.schema ?? {};
1692
+ const paramType = schema.type;
1693
+ const paramFormat = schema.format;
1694
+ const paramEnum = schema.enum;
1695
+ const constraintBadges = buildConstraints(schema);
1696
+ return /* @__PURE__ */ jsxs("div", { className: paramRowStyle, children: [
1697
+ /* @__PURE__ */ jsxs("div", { className: paramHeaderStyle, children: [
1698
+ /* @__PURE__ */ jsx("span", { className: paramNameStyle, children: name }),
1699
+ paramType && /* @__PURE__ */ jsx("pre", { className: typeBadgeStyle$1, children: paramType })
1700
+ ] }),
1701
+ (paramFormat || constraintBadges.length > 0 || paramEnum && paramEnum.length > 0) && /* @__PURE__ */ jsxs("div", { className: paramConstraintsStyle, children: [
1702
+ paramFormat && /* @__PURE__ */ jsx(SchemaBadge, { variant: "constraint", children: paramFormat }),
1703
+ constraintBadges.map((c) => /* @__PURE__ */ jsx(SchemaBadge, { variant: "constraint", children: c }, c)),
1704
+ paramEnum && paramEnum.length > 0 && /* @__PURE__ */ jsxs(SchemaBadge, { variant: "enum", children: [
1705
+ "enum: ",
1706
+ paramEnum.map(String).join(" | ")
1707
+ ] })
1708
+ ] }),
1709
+ param.description && /* @__PURE__ */ jsx("p", { className: paramDescStyle, children: param.description })
1710
+ ] }, name);
1711
+ }) })
1712
+ ] }),
1713
+ /* @__PURE__ */ jsx(SecurityRequirementBadges, { requirements: operation.securityRequirements ?? [] }),
1714
+ /* @__PURE__ */ jsx(BindingsSection, { bindings: operation.bindings, title: "Operation Bindings" }),
1715
+ /* @__PURE__ */ jsx(BindingsSection, { bindings: channel.bindings, title: "Channel Bindings" })
1716
+ ] });
1717
+ }
1718
+ function OperationSamplesColumn({ operation, idx }) {
1719
+ const messages = operation.messages ?? [];
1720
+ const replyMessages = operation.reply?.messages ?? [];
1721
+ if (messages.length === 0 && replyMessages.length === 0) {
1722
+ return /* @__PURE__ */ jsx("div", { className: emptySamplesStyle, children: "No message payload is defined for this operation." });
1723
+ }
1724
+ return /* @__PURE__ */ jsxs("div", { className: samplesColumnStyle, children: [
1725
+ messages.map((message, i) => /* @__PURE__ */ jsxs("div", { children: [
1726
+ /* @__PURE__ */ jsxs("h4", { className: sectionTitleStyle, children: [
1727
+ "Message",
1728
+ (message.title ?? message.name) && /* @__PURE__ */ jsxs("span", { className: messageTitleStyle, children: [
1729
+ " \u2014 ",
1730
+ message.title ?? message.name
1731
+ ] })
1732
+ ] }),
1733
+ message.contentType && /* @__PURE__ */ jsx("code", { className: contentTypeStyle$1, children: message.contentType }),
1734
+ /* @__PURE__ */ jsx(MessagePayload, { message, idx: `${idx}-msg-${i}` })
1735
+ ] }, i)),
1736
+ replyMessages.length > 0 && /* @__PURE__ */ jsxs("div", { className: replyStyle, children: [
1737
+ /* @__PURE__ */ jsx("h4", { className: sectionTitleStyle, children: "Reply" }),
1738
+ replyMessages.map((message, i) => /* @__PURE__ */ jsx(MessagePayload, { message, idx: `${idx}-reply-${i}` }, i))
1739
+ ] })
1740
+ ] });
1741
+ }
1742
+ const channelMetaStyle = css({
1743
+ padding: "0.75rem 1rem 0",
1744
+ [mq.desktop]: {
1745
+ padding: "1rem 1.25rem 0"
1746
+ }
1747
+ });
1748
+ const operationWrapStyle = css({
1749
+ borderTop: "1px solid var(--omnispec-border-color)"
1750
+ });
1751
+ const tryItNaStyle = css({
1752
+ fontSize: "var(--omnispec-font-size-sm)",
1753
+ color: "var(--omnispec-fg-muted)",
1754
+ fontStyle: "italic",
1755
+ padding: "0.5rem 0"
1756
+ });
1757
+ const samplesColumnStyle = css({
1758
+ display: "flex",
1759
+ flexDirection: "column",
1760
+ gap: "1.5rem"
1761
+ });
1762
+ const emptySamplesStyle = css({
1763
+ fontSize: "var(--omnispec-font-size-sm)",
1764
+ color: "var(--omnispec-fg-muted)",
1765
+ fontStyle: "italic"
1766
+ });
1767
+ const sectionStyle = css({
1768
+ marginBottom: "1.5rem"
1769
+ });
1770
+ const sectionTitleStyle = css({
1771
+ margin: "0 0 0.75rem",
1772
+ fontSize: "var(--omnispec-font-size-md)",
1773
+ fontWeight: 700,
1774
+ color: "var(--omnispec-fg-primary)",
1775
+ letterSpacing: "0.02em"
1776
+ });
1777
+ const paramListStyle = css({
1778
+ display: "flex",
1779
+ flexDirection: "column"
1780
+ });
1781
+ const paramRowStyle = css({
1782
+ padding: "0.75rem 0"
1783
+ });
1784
+ const paramHeaderStyle = css({
1785
+ display: "flex",
1786
+ alignItems: "center",
1787
+ gap: "0.5rem",
1788
+ flexWrap: "wrap"
1789
+ });
1790
+ const paramNameStyle = css({
1791
+ fontSize: "var(--omnispec-font-size-sm)",
1792
+ fontWeight: 700,
1793
+ backgroundColor: "transparent",
1794
+ padding: 0
1795
+ });
1796
+ const typeBadgeStyle$1 = css({
1797
+ fontSize: "var(--omnispec-font-size-xs)",
1798
+ fontWeight: 400
1799
+ });
1800
+ const paramDescStyle = css({
1801
+ margin: "0.25rem 0 0",
1802
+ fontSize: "var(--omnispec-font-size-base)",
1803
+ color: "var(--omnispec-fg-secondary)",
1804
+ lineHeight: 1.5
1805
+ });
1806
+ const paramConstraintsStyle = css({
1807
+ display: "flex",
1808
+ flexWrap: "wrap",
1809
+ gap: "0.375rem",
1810
+ marginTop: "0.375rem"
1811
+ });
1812
+ const opHeaderStyle = css({
1813
+ display: "flex",
1814
+ alignItems: "center",
1815
+ gap: "0.5rem",
1816
+ marginBottom: "0.5rem"
1817
+ });
1818
+ const actionBadgeBase = css({
1819
+ display: "inline-block",
1820
+ padding: "0.125rem 0.375rem",
1821
+ borderRadius: "0.1875rem",
1822
+ fontSize: "0.5625rem",
1823
+ fontWeight: 700,
1824
+ fontFamily: "var(--omnispec-font-mono)",
1825
+ color: "#ffffff",
1826
+ letterSpacing: "0.0313rem"
1827
+ });
1828
+ const opIdStyle = css({
1829
+ fontSize: "var(--omnispec-font-size-sm)",
1830
+ fontWeight: 700,
1831
+ backgroundColor: "transparent",
1832
+ padding: 0
1833
+ });
1834
+ const opTitleStyle = css({
1835
+ fontSize: "var(--omnispec-font-size-sm)",
1836
+ fontWeight: 600,
1837
+ color: "var(--omnispec-fg-primary)"
1838
+ });
1839
+ const opSummaryStyle = css({
1840
+ fontSize: "var(--omnispec-font-size-sm)",
1841
+ color: "var(--omnispec-fg-secondary)"
1842
+ });
1843
+ const messageTitleStyle = css({
1844
+ fontWeight: 400,
1845
+ color: "var(--omnispec-fg-primary)"
1846
+ });
1847
+ const contentTypeStyle$1 = css({
1848
+ fontFamily: "var(--omnispec-font-mono)",
1849
+ fontSize: "var(--omnispec-font-size-xs)",
1850
+ color: "var(--omnispec-fg-muted)",
1851
+ display: "block",
1852
+ marginBottom: "0.5rem",
1853
+ backgroundColor: "transparent",
1854
+ padding: 0
1855
+ });
1856
+ const replyStyle = css({
1857
+ paddingLeft: "0.75rem",
1858
+ borderLeft: "0.125rem solid var(--omnispec-border-color)"
1859
+ });
1190
1860
  const tagChipsStyle = css({
1191
1861
  display: "flex",
1192
1862
  flexWrap: "wrap",
@@ -1201,12 +1871,25 @@ const tagChipStyle = css({
1201
1871
  padding: "1px 0.5rem",
1202
1872
  borderRadius: "0.625rem"
1203
1873
  });
1874
+ const tagChipButtonStyle = css({
1875
+ fontSize: "var(--omnispec-font-size-xxs)",
1876
+ fontFamily: "var(--omnispec-font-mono)",
1877
+ color: "var(--omnispec-fg-secondary)",
1878
+ backgroundColor: "var(--omnispec-bg-tertiary)",
1879
+ padding: "1px 0.5rem",
1880
+ borderRadius: "0.625rem",
1881
+ border: "none",
1882
+ cursor: "pointer",
1883
+ "&:hover": {
1884
+ color: "var(--omnispec-fg-primary)"
1885
+ }
1886
+ });
1204
1887
 
1205
1888
  function ComponentsSection({ components }) {
1206
1889
  const schemas = Object.entries(components.schemas);
1207
1890
  const messages = Object.entries(components.messages ?? {});
1208
1891
  if (schemas.length === 0 && messages.length === 0) return null;
1209
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1892
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
1210
1893
  messages.length > 0 && /* @__PURE__ */ jsxs("div", { className: `omnispec-async-messages ${containerStyle$1}`, id: "messages", children: [
1211
1894
  /* @__PURE__ */ jsx("h2", { className: titleStyle$2, children: "Messages" }),
1212
1895
  /* @__PURE__ */ jsx("div", { className: schemaWrapperStyle, children: messages.map(([name, message]) => /* @__PURE__ */ jsx("div", { className: schemaStyle, id: `message-${name}`, children: /* @__PURE__ */ jsxs(
@@ -1217,9 +1900,15 @@ function ComponentsSection({ components }) {
1217
1900
  children: [
1218
1901
  message.title && /* @__PURE__ */ jsx("p", { className: messageSummaryStyle, children: message.title }),
1219
1902
  message.summary && /* @__PURE__ */ jsx("p", { className: messageSummaryStyle, children: message.summary }),
1220
- message.contentType && /* @__PURE__ */ jsx("code", { className: contentTypeStyle, children: message.contentType }),
1903
+ message.contentType && /* @__PURE__ */ jsxs("code", { className: contentTypeStyle, children: [
1904
+ message.contentType,
1905
+ message.contentTypeInherited && /* @__PURE__ */ jsx("span", { className: contentTypeHintStyle, children: " (default)" })
1906
+ ] }),
1221
1907
  /* @__PURE__ */ jsx(MessagePayload, { message, idx: `message-${name}` }),
1222
- message.headers && /* @__PURE__ */ jsx(SchemaTree, { nodes: schemaToNodes(message.headers) })
1908
+ message.headers && /* @__PURE__ */ jsxs("div", { className: headersWrapStyle, children: [
1909
+ /* @__PURE__ */ jsx("h4", { className: headersTitleStyle, children: "Headers" }),
1910
+ /* @__PURE__ */ jsx(SchemaTree, { nodes: schemaToNodes(message.headers) })
1911
+ ] })
1223
1912
  ]
1224
1913
  }
1225
1914
  ) }, name)) })
@@ -1284,6 +1973,20 @@ const contentTypeStyle = css({
1284
1973
  color: "var(--omnispec-fg-muted)",
1285
1974
  marginBottom: "0.5rem"
1286
1975
  });
1976
+ const contentTypeHintStyle = css({
1977
+ fontStyle: "italic",
1978
+ color: "var(--omnispec-fg-muted)"
1979
+ });
1980
+ const headersWrapStyle = css({
1981
+ marginTop: "1rem"
1982
+ });
1983
+ const headersTitleStyle = css({
1984
+ margin: "0 0 0.75rem",
1985
+ fontSize: "var(--omnispec-font-size-md)",
1986
+ fontWeight: 700,
1987
+ color: "var(--omnispec-fg-primary)",
1988
+ letterSpacing: "0.02em"
1989
+ });
1287
1990
 
1288
1991
  const SPECIAL_KEYS = /* @__PURE__ */ new Set(["type", "description", "flows"]);
1289
1992
  function SecuritySchemesSection({ securitySchemes }) {
@@ -1432,10 +2135,11 @@ const scopeDescStyle = css({
1432
2135
 
1433
2136
  const UNTAGGED_LABEL = "Untagged";
1434
2137
  function slugify(value) {
1435
- return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "tag";
2138
+ return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "tag";
1436
2139
  }
1437
2140
  function channelTagNames(channel) {
1438
2141
  const names = /* @__PURE__ */ new Set();
2142
+ for (const tag of channel.tags ?? []) names.add(tag.name);
1439
2143
  for (const op of channel.operations) {
1440
2144
  for (const tag of op.tags ?? []) names.add(tag.name);
1441
2145
  }
@@ -1490,19 +2194,7 @@ function TagGroupHeader({ group }) {
1490
2194
  /* @__PURE__ */ jsx("span", { className: countStyle, children: group.channels.length })
1491
2195
  ] }),
1492
2196
  group.tag?.description && /* @__PURE__ */ jsx("div", { className: descStyle, children: /* @__PURE__ */ jsx(MarkdownRenderer, { content: group.tag.description }) }),
1493
- group.tag?.externalDocs && /* @__PURE__ */ jsxs(
1494
- "a",
1495
- {
1496
- href: group.tag.externalDocs.url,
1497
- target: "_blank",
1498
- rel: "noopener noreferrer",
1499
- className: docsStyle,
1500
- children: [
1501
- group.tag.externalDocs.description ?? "External docs",
1502
- /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: " \u2197" })
1503
- ]
1504
- }
1505
- )
2197
+ group.tag?.externalDocs && /* @__PURE__ */ jsx("div", { className: docsStyle, children: /* @__PURE__ */ jsx(ExternalDocsLink, { externalDocs: group.tag.externalDocs, context: group.label }) })
1506
2198
  ] });
1507
2199
  }
1508
2200
  const headerStyle = css({
@@ -1535,16 +2227,7 @@ const descStyle = css({
1535
2227
  lineHeight: 1.6
1536
2228
  });
1537
2229
  const docsStyle = css({
1538
- display: "inline-flex",
1539
- alignItems: "center",
1540
- gap: "0.25rem",
1541
- marginTop: "0.5rem",
1542
- fontSize: "var(--omnispec-font-size-xs)",
1543
- color: "var(--omnispec-fg-link)",
1544
- textDecoration: "none",
1545
- "&:hover": {
1546
- textDecoration: "underline"
1547
- }
2230
+ marginTop: "0.5rem"
1548
2231
  });
1549
2232
 
1550
2233
  function AsyncApiSpec({
@@ -1553,6 +2236,7 @@ function AsyncApiSpec({
1553
2236
  layout = "sidebar",
1554
2237
  sidebarPosition = "left",
1555
2238
  defaultExpandOperations = false,
2239
+ displayMode,
1556
2240
  downloadLink,
1557
2241
  sidebarNav,
1558
2242
  slots = {},
@@ -1562,6 +2246,7 @@ function AsyncApiSpec({
1562
2246
  className
1563
2247
  }) {
1564
2248
  const resolvedSchemaStyle = resolveSchemaStyle(schemaStyle, pro?.advancedSchemaStyles ?? false);
2249
+ const resolvedDisplayMode = displayMode ?? "compact";
1565
2250
  const { data: parsedSpec, state } = useAsyncApiSpec(spec);
1566
2251
  const [searchQuery, setSearchQuery] = useState("");
1567
2252
  const [allExpanded, setAllExpanded] = useState(defaultExpandOperations);
@@ -1628,12 +2313,15 @@ function AsyncApiSpec({
1628
2313
  if (!parsedSpec) return [];
1629
2314
  const actionLabel = (action) => action.toUpperCase();
1630
2315
  const actionColor = (action) => action === "subscribe" || action === "receive" ? "var(--omnispec-color-subscribe)" : "var(--omnispec-color-publish)";
1631
- const channelNavItem = (ch, idPrefix) => ({
1632
- id: `${idPrefix}channel-${ch.name}`,
1633
- label: ch.address,
1634
- badge: ch.operations.map((op) => actionLabel(op.action)).join("/") || void 0,
1635
- badgeColor: actionColor(ch.operations[0]?.action ?? "")
1636
- });
2316
+ const channelNavItem = (ch, idPrefix) => {
2317
+ const uniqueActions = [...new Set(ch.operations.map((op) => actionLabel(op.action)))];
2318
+ return {
2319
+ id: `${idPrefix}channel-${ch.name}`,
2320
+ label: ch.address,
2321
+ badge: uniqueActions.join("/") || void 0,
2322
+ badgeColor: actionColor(ch.operations[0]?.action ?? "")
2323
+ };
2324
+ };
1637
2325
  const operationNavItems = () => filteredChannels.flatMap(
1638
2326
  (ch) => ch.operations.map((op, idx) => ({
1639
2327
  id: operationDomId(ch.name, idx),
@@ -1653,11 +2341,15 @@ function AsyncApiSpec({
1653
2341
  if (parsedSpec.servers.length > 0) {
1654
2342
  items.push({ id: "servers", label: "Servers" });
1655
2343
  }
1656
- items.push({
1657
- id: "channels",
1658
- label: navGrouping === "operation" ? "Operations" : "Channels",
1659
- children: channelChildren
1660
- });
2344
+ const searchedToEmpty = channelChildren.length === 0 && searchQuery.trim().length > 0;
2345
+ const channelsChildren = searchedToEmpty ? [{ id: "channels-no-results", label: "No results", className: noResultsNavStyle }] : channelChildren;
2346
+ if (channelsChildren.length > 0) {
2347
+ items.push({
2348
+ id: "channels",
2349
+ label: navGrouping === "operation" ? "Operations" : "Channels",
2350
+ children: channelsChildren
2351
+ });
2352
+ }
1661
2353
  if (Object.keys(parsedSpec.components.messages ?? {}).length > 0) {
1662
2354
  items.push({
1663
2355
  id: "messages",
@@ -1682,7 +2374,7 @@ function AsyncApiSpec({
1682
2374
  items.push({ id: "security", label: "Security Schemes" });
1683
2375
  }
1684
2376
  return items;
1685
- }, [parsedSpec, grouped, tagGroups, filteredChannels, navGrouping, operationDomId]);
2377
+ }, [parsedSpec, grouped, tagGroups, filteredChannels, navGrouping, operationDomId, searchQuery]);
1686
2378
  const { navigateTo } = useHashScroll(filteredChannels.length);
1687
2379
  const handleNavSelect = useCallback((id) => {
1688
2380
  const cardId = opToCard.get(id);
@@ -1714,7 +2406,7 @@ function AsyncApiSpec({
1714
2406
  );
1715
2407
  }
1716
2408
  if (!parsedSpec) return null;
1717
- const specNav = /* @__PURE__ */ jsxs(Fragment, { children: [
2409
+ const specNav = /* @__PURE__ */ jsxs(Fragment$1, { children: [
1718
2410
  /* @__PURE__ */ jsx(
1719
2411
  SearchBar,
1720
2412
  {
@@ -1760,7 +2452,7 @@ function AsyncApiSpec({
1760
2452
  ] });
1761
2453
  const sidebar = buildSidebar(sidebarNav, specNav);
1762
2454
  const resolvedDownloadLink = resolveDownloadLink(downloadLink, spec);
1763
- return /* @__PURE__ */ jsx(ConfigProvider, { config: { allowTryIt: false, layout, sidebarPosition, defaultExpandOperations, schemaStyle: resolvedSchemaStyle, slots, proRenderers: pro?.renderers ?? /* @__PURE__ */ new Map(), premiumThemingEnabled: pro?.premiumThemingEnabled ?? false }, children: /* @__PURE__ */ jsx(ExpandProvider, { expandAll: allExpanded, expandGeneration, children: /* @__PURE__ */ jsx(ThemeProvider, { theme, children: /* @__PURE__ */ jsx("div", { className: `omnispec-asyncapi ${className ?? ""}`, children: /* @__PURE__ */ jsx(ErrorBoundary, { title: "Failed to render this API reference", children: /* @__PURE__ */ jsxs(
2455
+ return /* @__PURE__ */ jsx(ConfigProvider, { config: { allowTryIt: false, layout, sidebarPosition, defaultExpandOperations, displayMode: resolvedDisplayMode, schemaStyle: resolvedSchemaStyle, slots, proRenderers: pro?.renderers ?? /* @__PURE__ */ new Map(), premiumThemingEnabled: pro?.premiumThemingEnabled ?? false }, children: /* @__PURE__ */ jsx(ExpandProvider, { expandAll: allExpanded, expandGeneration, children: /* @__PURE__ */ jsx(ThemeProvider, { theme, children: /* @__PURE__ */ jsx("div", { className: `omnispec-asyncapi ${className ?? ""}`, children: /* @__PURE__ */ jsx(ErrorBoundary, { title: "Failed to render this API reference", children: /* @__PURE__ */ jsxs(
1764
2456
  DocLayout,
1765
2457
  {
1766
2458
  layout,
@@ -1787,22 +2479,26 @@ function AsyncApiSpec({
1787
2479
  filteredChannels.length === 0 ? /* @__PURE__ */ jsx("p", { className: emptyStateStyle, children: parsedSpec.channels.length === 0 ? "No channels are defined for this API." : "No channels match your filter." }) : grouped ? tagGroups.map((group) => /* @__PURE__ */ jsxs("section", { id: `taggroup-${group.id}`, className: tagSectionStyle, children: [
1788
2480
  /* @__PURE__ */ jsx(TagGroupHeader, { group }),
1789
2481
  group.channels.map((channel) => /* @__PURE__ */ jsx(
1790
- ChannelDetail,
2482
+ ChannelCard,
1791
2483
  {
1792
2484
  id: `${group.id}-channel-${channel.name}`,
1793
2485
  channel,
2486
+ displayMode: resolvedDisplayMode,
1794
2487
  expandAll: allExpanded,
1795
- expandGeneration
2488
+ expandGeneration,
2489
+ onTagClick: setSearchQuery
1796
2490
  },
1797
2491
  `${group.id}-${channel.name}`
1798
2492
  ))
1799
2493
  ] }, group.id)) : filteredChannels.map((channel) => /* @__PURE__ */ jsx(
1800
- ChannelDetail,
2494
+ ChannelCard,
1801
2495
  {
1802
2496
  id: `channel-${channel.name}`,
1803
2497
  channel,
2498
+ displayMode: resolvedDisplayMode,
1804
2499
  expandAll: allExpanded,
1805
- expandGeneration
2500
+ expandGeneration,
2501
+ onTagClick: setSearchQuery
1806
2502
  },
1807
2503
  channel.name
1808
2504
  ))
@@ -1813,6 +2509,26 @@ function AsyncApiSpec({
1813
2509
  }
1814
2510
  ) }) }) }) }) });
1815
2511
  }
2512
+ function ChannelCard({
2513
+ channel,
2514
+ id,
2515
+ displayMode,
2516
+ expandAll,
2517
+ expandGeneration,
2518
+ onTagClick
2519
+ }) {
2520
+ const Renderer = displayMode === "reference" ? ChannelReferenceDetail : ChannelDetail;
2521
+ return /* @__PURE__ */ jsx(
2522
+ Renderer,
2523
+ {
2524
+ id,
2525
+ channel,
2526
+ expandAll,
2527
+ expandGeneration,
2528
+ onTagClick
2529
+ }
2530
+ );
2531
+ }
1816
2532
  function nestByTagGroups(groups, xTagGroups, toNav) {
1817
2533
  if (!xTagGroups?.length) return groups.map(toNav);
1818
2534
  const byTagName = /* @__PURE__ */ new Map();
@@ -1822,7 +2538,7 @@ function nestByTagGroups(groups, xTagGroups, toNav) {
1822
2538
  const children = xg.tags.map((t) => byTagName.get(t)).filter((g) => !!g);
1823
2539
  children.forEach((g) => used.add(g));
1824
2540
  return {
1825
- id: `xtaggroup-${xg.name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "group"}`,
2541
+ id: `xtaggroup-${xg.name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "group"}`,
1826
2542
  label: xg.name,
1827
2543
  children: children.map(toNav)
1828
2544
  };
@@ -1835,6 +2551,11 @@ const emptyStateStyle = css({
1835
2551
  color: "var(--omnispec-fg-muted)",
1836
2552
  fontStyle: "italic"
1837
2553
  });
2554
+ const noResultsNavStyle = css({
2555
+ fontStyle: "italic",
2556
+ color: "var(--omnispec-fg-muted)",
2557
+ cursor: "default"
2558
+ });
1838
2559
  const groupToggleStyle = css({
1839
2560
  display: "flex",
1840
2561
  alignItems: "center",
@@ -1875,4 +2596,4 @@ const tagSectionStyle = css({
1875
2596
  });
1876
2597
 
1877
2598
  export { AsyncApiSpec };
1878
- //# sourceMappingURL=AsyncApiSpec-BPiA9b5T.js.map
2599
+ //# sourceMappingURL=AsyncApiSpec-B757IIHz.js.map