@clarify-labs/renderer 0.11.0 → 0.11.2

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 (61) hide show
  1. package/output/{ClarifyShell-BAjq876Z.cjs → ClarifyShell-Cn48irqj.cjs} +37 -21
  2. package/output/ClarifyShell-Cn48irqj.cjs.map +1 -0
  3. package/output/{ClarifyShell-GoSXvgMg.js → ClarifyShell-D_HluctW.js} +37 -21
  4. package/output/ClarifyShell-D_HluctW.js.map +1 -0
  5. package/output/{MermaidViewer-CkIxyqtf.js → MermaidViewer-Dby0ylNr.js} +2 -2
  6. package/output/{MermaidViewer-CkIxyqtf.js.map → MermaidViewer-Dby0ylNr.js.map} +1 -1
  7. package/output/{MermaidViewer-BZ8ghcFP.cjs → MermaidViewer-EZjolX08.cjs} +2 -2
  8. package/output/{MermaidViewer-BZ8ghcFP.cjs.map → MermaidViewer-EZjolX08.cjs.map} +1 -1
  9. package/output/{OpenApiOperation-C2vJztWZ.js → OpenApiOperation-Cr8TxLjl.js} +553 -125
  10. package/output/OpenApiOperation-Cr8TxLjl.js.map +1 -0
  11. package/output/{OpenApiOperation-D-5uE5v7.cjs → OpenApiOperation-bdALspAY.cjs} +553 -125
  12. package/output/OpenApiOperation-bdALspAY.cjs.map +1 -0
  13. package/output/{PageActions-bugd7GZh.js → PageActions-BLzCasvB.js} +47 -6
  14. package/output/PageActions-BLzCasvB.js.map +1 -0
  15. package/output/{PageActions-DJRXlGhz.cjs → PageActions-Bw9SAHLl.cjs} +46 -5
  16. package/output/PageActions-Bw9SAHLl.cjs.map +1 -0
  17. package/output/{SearchDialog-CBJjDs_9.js → SearchDialog-DWYp1c6c.js} +3 -3
  18. package/output/{SearchDialog-CBJjDs_9.js.map → SearchDialog-DWYp1c6c.js.map} +1 -1
  19. package/output/{SearchDialog-8AdCRp6K.cjs → SearchDialog-j_4Y9WY_.cjs} +3 -3
  20. package/output/{SearchDialog-8AdCRp6K.cjs.map → SearchDialog-j_4Y9WY_.cjs.map} +1 -1
  21. package/output/client.cjs +3 -3
  22. package/output/client.js +3 -3
  23. package/output/core/i18n.d.ts +1 -1
  24. package/output/core/types.d.ts +1 -1
  25. package/output/{i18n-BPrC45nD.js → i18n-DjRcGSuU.js} +23 -1
  26. package/output/i18n-DjRcGSuU.js.map +1 -0
  27. package/output/{i18n-wXINKKV0.cjs → i18n-L1XX-y6M.cjs} +23 -1
  28. package/output/i18n-L1XX-y6M.cjs.map +1 -0
  29. package/output/index.cjs +5 -5
  30. package/output/index.js +5 -5
  31. package/output/openapi/components/EndpointSections.d.ts +2 -0
  32. package/output/openapi/components/InlineListbox.d.ts +1 -0
  33. package/output/openapi/components/OpenApiAuthDocumentation.d.ts +7 -0
  34. package/output/openapi/components/OpenApiRequestBodyEditor.d.ts +14 -0
  35. package/output/openapi/components/OpenApiResponseViewer.d.ts +6 -0
  36. package/output/openapi/components/helpers.d.ts +1 -0
  37. package/output/openapi/components/useOpenApiRequestState.d.ts +9 -2
  38. package/output/openapi/lib/api-request.d.ts +1 -0
  39. package/output/openapi/lib/helpers.d.ts +8 -0
  40. package/output/openapi/types.d.ts +3 -0
  41. package/output/preview.cjs +14 -18
  42. package/output/preview.cjs.map +1 -1
  43. package/output/preview.js +14 -18
  44. package/output/preview.js.map +1 -1
  45. package/output/{render-XQiw_48i.js → render-CYQmEacg.js} +2 -2
  46. package/output/{render-XQiw_48i.js.map → render-CYQmEacg.js.map} +1 -1
  47. package/output/{render-FICIzeXz.cjs → render-hq20DPxe.cjs} +2 -2
  48. package/output/{render-FICIzeXz.cjs.map → render-hq20DPxe.cjs.map} +1 -1
  49. package/output/renderer.css +145 -48
  50. package/output/server.cjs +2 -2
  51. package/output/server.js +2 -2
  52. package/package.json +2 -1
  53. package/output/ClarifyShell-BAjq876Z.cjs.map +0 -1
  54. package/output/ClarifyShell-GoSXvgMg.js.map +0 -1
  55. package/output/OpenApiOperation-C2vJztWZ.js.map +0 -1
  56. package/output/OpenApiOperation-D-5uE5v7.cjs.map +0 -1
  57. package/output/PageActions-DJRXlGhz.cjs.map +0 -1
  58. package/output/PageActions-bugd7GZh.js.map +0 -1
  59. package/output/core/index.d.ts +0 -3
  60. package/output/i18n-BPrC45nD.js.map +0 -1
  61. package/output/i18n-wXINKKV0.cjs.map +0 -1
@@ -1,5 +1,5 @@
1
- import { a as useConfig, s as useLocale, t as useBuiltInText } from "./i18n-BPrC45nD.js";
2
- import { C as isExternalHref, E as copyTextToClipboard, c as lucideIconRegistry, h as useTheme, l as resolveLucideIconName, n as PageTitleActions, o as useSectionStore, s as remToPx, w as localizeHref } from "./PageActions-bugd7GZh.js";
1
+ import { a as useConfig, s as useLocale, t as useBuiltInText } from "./i18n-DjRcGSuU.js";
2
+ import { C as isExternalHref, E as copyTextToClipboard, c as lucideIconRegistry, h as useTheme, l as resolveLucideIconName, n as PageTitleActions, o as useSectionStore, s as remToPx, w as localizeHref } from "./PageActions-BLzCasvB.js";
3
3
  import { t as markdownRemarkPlugins } from "./remark-C9iRQM0R.js";
4
4
  import clsx from "clsx";
5
5
  import { Children, Suspense, cloneElement, createContext, createElement, forwardRef, isValidElement, lazy, useContext, useEffect, useId, useLayoutEffect, useRef, useState } from "react";
@@ -14,6 +14,7 @@ import rehypeRaw from "rehype-raw";
14
14
  import { slug } from "github-slugger";
15
15
  import { codeToTokens, createCssVariablesTheme } from "shiki";
16
16
  import { snippetz } from "@scalar/snippetz";
17
+ import { parse, stringify } from "yaml";
17
18
  //#region \0rolldown/runtime.js
18
19
  var __defProp = Object.defineProperty;
19
20
  var __exportAll = (all, no_symbols) => {
@@ -252,7 +253,7 @@ function Card(arg0) {
252
253
  }
253
254
  //#endregion
254
255
  //#region source/components/Mermaid.tsx
255
- var MermaidViewer = lazy(() => import("./MermaidViewer-CkIxyqtf.js"));
256
+ var MermaidViewer = lazy(() => import("./MermaidViewer-Dby0ylNr.js"));
256
257
  var mermaidModulePromise;
257
258
  async function loadMermaid() {
258
259
  mermaidModulePromise = mermaidModulePromise ?? import("mermaid").then((module) => module.default);
@@ -1454,6 +1455,31 @@ function resolveSchema(spec, schema, seen = /* @__PURE__ */ new Set()) {
1454
1455
  seen.add(schema.$ref);
1455
1456
  return resolveSchema(spec, resolveOpenApiRef$1(spec, schema.$ref), seen) ?? schema;
1456
1457
  }
1458
+ function mergeAllOfSchemas(spec, schemas) {
1459
+ const merged = {};
1460
+ const properties = {};
1461
+ const required = /* @__PURE__ */ new Set();
1462
+ for (const schema of schemas) {
1463
+ const resolved = resolveRequestSchema(spec, schema);
1464
+ if (!isRecord$1(resolved)) continue;
1465
+ Object.assign(merged, resolved);
1466
+ if (isRecord$1(resolved.properties)) Object.assign(properties, resolved.properties);
1467
+ if (Array.isArray(resolved.required)) resolved.required.forEach((name) => required.add(String(name)));
1468
+ }
1469
+ if (Object.keys(properties).length > 0) merged.properties = properties;
1470
+ if (required.size > 0) merged.required = [...required];
1471
+ delete merged.allOf;
1472
+ return merged;
1473
+ }
1474
+ function resolveRequestSchema(spec, schema) {
1475
+ const resolved = resolveSchema(spec, schema);
1476
+ if (!isRecord$1(resolved)) return resolved;
1477
+ const ownSchema = { ...resolved };
1478
+ const allOf = Array.isArray(ownSchema.allOf) ? ownSchema.allOf : [];
1479
+ if (allOf.length === 0) return ownSchema;
1480
+ delete ownSchema.allOf;
1481
+ return mergeAllOfSchemas(spec, [...allOf, ownSchema]);
1482
+ }
1457
1483
  function getPathItem$1(spec, path) {
1458
1484
  return resolveObjectRef(spec, spec.paths?.[path]);
1459
1485
  }
@@ -1473,6 +1499,7 @@ function resolveObjectRef(spec, value) {
1473
1499
  }
1474
1500
  function schemaHasType(schema, type) {
1475
1501
  if (!isRecord$1(schema)) return false;
1502
+ if (type === "null" && schema.nullable === true) return true;
1476
1503
  return schema.type === type || Array.isArray(schema.type) && schema.type.includes(type);
1477
1504
  }
1478
1505
  function getOperationParameters(spec, path, operation, source = "path") {
@@ -1542,7 +1569,7 @@ function getExampleEntries(mediaType, spec) {
1542
1569
  title: "Example",
1543
1570
  value: mediaType.example
1544
1571
  }];
1545
- const generated = schemaToExample(spec ? resolveSchema(spec, mediaType.schema) : mediaType.schema);
1572
+ const generated = schemaToExample(spec ? resolveRequestSchema(spec, mediaType.schema) : mediaType.schema);
1546
1573
  return typeof generated === "undefined" ? [] : [{
1547
1574
  key: "schema",
1548
1575
  title: "schema",
@@ -1550,6 +1577,34 @@ function getExampleEntries(mediaType, spec) {
1550
1577
  generated: true
1551
1578
  }];
1552
1579
  }
1580
+ function getParameterExampleEntries(parameter) {
1581
+ if (isRecord$1(parameter.examples)) {
1582
+ const examples = [];
1583
+ for (const [key, example] of Object.entries(parameter.examples)) {
1584
+ const value = getExampleValue(example);
1585
+ if (typeof value === "undefined") continue;
1586
+ const { title, summary } = getExampleTitle(key, example);
1587
+ examples.push({
1588
+ key,
1589
+ title,
1590
+ summary,
1591
+ value
1592
+ });
1593
+ }
1594
+ if (examples.length > 0) return examples;
1595
+ }
1596
+ return typeof parameter.example === "undefined" ? [] : [{
1597
+ key: "default",
1598
+ title: "Example",
1599
+ value: parameter.example
1600
+ }];
1601
+ }
1602
+ function getRequestExampleEntries(parameters, mediaType) {
1603
+ const entries = /* @__PURE__ */ new Map();
1604
+ for (const example of getExampleEntries(mediaType).filter((entry) => !entry.generated)) entries.set(example.key, example);
1605
+ for (const parameter of parameters) for (const example of getParameterExampleEntries(parameter)) if (!entries.has(example.key)) entries.set(example.key, example);
1606
+ return [...entries.values()];
1607
+ }
1553
1608
  function getContentExample(mediaType) {
1554
1609
  return getExampleEntries(mediaType)[0]?.value;
1555
1610
  }
@@ -1563,7 +1618,8 @@ function schemaToType(schema) {
1563
1618
  if (Array.isArray(schema.allOf)) return schema.allOf.map((branch) => schemaToType(branch)).filter(Boolean).join(" & ");
1564
1619
  if (schemaHasType(schema, "array")) return `${schemaToType(schema.items) ?? "unknown"}[]`;
1565
1620
  const type = Array.isArray(schema.type) ? schema.type.map(String).join(" | ") : schema.type;
1566
- return typeof type === "string" ? [type, typeof schema.format === "string" ? `<${schema.format}>` : void 0].filter(Boolean).join("") : void 0;
1621
+ const nullableType = schema.nullable === true && type !== "null" ? [type, "null"].filter(Boolean).join(" | ") : type;
1622
+ return typeof nullableType === "string" ? [nullableType, typeof schema.format === "string" ? `<${schema.format}>` : void 0].filter(Boolean).join("") : void 0;
1567
1623
  }
1568
1624
  function schemaToExample(schema, depth = 0) {
1569
1625
  if (!isRecord$1(schema) || depth > 3) return void 0;
@@ -1571,10 +1627,12 @@ function schemaToExample(schema, depth = 0) {
1571
1627
  if (typeof schema.default !== "undefined") return schema.default;
1572
1628
  if (Array.isArray(schema.enum)) return schema.enum[0];
1573
1629
  if (isReference(schema)) return { id: resolveReferenceName(schema.$ref) };
1630
+ const variant = Array.isArray(schema.oneOf) ? schema.oneOf[0] : Array.isArray(schema.anyOf) ? schema.anyOf[0] : void 0;
1631
+ if (typeof variant !== "undefined") return schemaToExample(variant, depth + 1);
1574
1632
  if (schemaHasType(schema, "array")) return [schemaToExample(schema.items, depth + 1) ?? "string"];
1575
1633
  if (schemaHasType(schema, "object") || isRecord$1(schema.properties)) {
1576
1634
  const properties = isRecord$1(schema.properties) ? schema.properties : {};
1577
- return Object.fromEntries(Object.entries(properties).slice(0, 8).map(([name, propertySchema]) => [name, schemaToExample(propertySchema, depth + 1) ?? exampleForType(schemaToType(propertySchema))]));
1635
+ return Object.fromEntries(Object.entries(properties).filter(([, propertySchema]) => !isRecord$1(propertySchema) || propertySchema.readOnly !== true).slice(0, 8).map(([name, propertySchema]) => [name, schemaToExample(propertySchema, depth + 1) ?? exampleForType(schemaToType(propertySchema))]));
1578
1636
  }
1579
1637
  return exampleForType(schemaToType(schema));
1580
1638
  }
@@ -1812,10 +1870,10 @@ function getQueryString(parameters, auth = []) {
1812
1870
  });
1813
1871
  return queryString;
1814
1872
  }
1815
- function isFormMediaType(mediaType) {
1873
+ function isFormMediaType$1(mediaType) {
1816
1874
  return mediaType.includes("multipart/form-data") || mediaType.includes("application/x-www-form-urlencoded");
1817
1875
  }
1818
- function isBinarySchema(schema) {
1876
+ function isBinarySchema$1(schema) {
1819
1877
  return isRecord$1(schema) && schema.type === "string" && schema.format === "binary";
1820
1878
  }
1821
1879
  function getSchemaProperties(schema) {
@@ -1823,7 +1881,7 @@ function getSchemaProperties(schema) {
1823
1881
  }
1824
1882
  function getFieldValue(name, value, schema) {
1825
1883
  if (isRecord$1(value) && typeof value[name] !== "undefined") return value[name];
1826
- if (isBinarySchema(schema)) return `@${name}`;
1884
+ if (isBinarySchema$1(schema)) return `@${name}`;
1827
1885
  }
1828
1886
  function getFormParams(value, requestContent) {
1829
1887
  const properties = getSchemaProperties(requestContent.value.schema);
@@ -1845,7 +1903,7 @@ function getBodySize(requestBody) {
1845
1903
  function getRequestBody(requestContent) {
1846
1904
  const value = getContentExample(requestContent?.value);
1847
1905
  if (!requestContent || typeof value === "undefined") return void 0;
1848
- if (isFormMediaType(requestContent.mediaType)) {
1906
+ if (isFormMediaType$1(requestContent.mediaType)) {
1849
1907
  const params = getFormParams(value, requestContent);
1850
1908
  return params.length > 0 ? { params } : void 0;
1851
1909
  }
@@ -2350,7 +2408,8 @@ function getAuthOptions(spec, operation) {
2350
2408
  return getSecurityRequirements(spec, operation).map((requirement, index) => {
2351
2409
  const requirementSchemes = Object.keys(requirement).map((name) => ({
2352
2410
  name,
2353
- scheme: schemes[name]
2411
+ scheme: schemes[name],
2412
+ scopes: requirement[name] ?? []
2354
2413
  })).filter((option) => Boolean(option.scheme));
2355
2414
  return {
2356
2415
  key: `requirement:${index}`,
@@ -2657,6 +2716,84 @@ function ResponseExamplesPanel(arg0) {
2657
2716
  });
2658
2717
  }
2659
2718
  //#endregion
2719
+ //#region source/openapi/components/OpenApiAuthDocumentation.tsx
2720
+ function authSchemeType(option, apiKeyLabel) {
2721
+ const { scheme } = option;
2722
+ if (scheme.type === "http") return scheme.scheme?.toUpperCase() || "HTTP";
2723
+ if (scheme.type === "apiKey") return apiKeyLabel;
2724
+ if (scheme.type === "oauth2") return "OAUTH 2.0";
2725
+ if (scheme.type === "openIdConnect") return "OPENID CONNECT";
2726
+ return scheme.type?.toUpperCase() || "AUTH";
2727
+ }
2728
+ function OpenApiAuthDocumentation({ options }) {
2729
+ const t = useBuiltInText();
2730
+ if (options.length === 0) return null;
2731
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", { children: t("openapi.authentication") }), /* @__PURE__ */ jsx("div", {
2732
+ className: "not-prose my-6 border-y border-(--clarify-theme-tokens-colors-border)",
2733
+ children: options.map((option, index) => /* @__PURE__ */ jsxs("div", { children: [index > 0 ? /* @__PURE__ */ jsxs("div", {
2734
+ className: "flex items-center gap-3 py-1",
2735
+ "aria-label": t("openapi.authOr"),
2736
+ children: [
2737
+ /* @__PURE__ */ jsx("span", { className: "h-px flex-1 bg-(--clarify-theme-tokens-colors-border)" }),
2738
+ /* @__PURE__ */ jsx("span", {
2739
+ className: "text-2xs font-semibold text-(--clarify-ui-text-faint)",
2740
+ children: t("openapi.authOr")
2741
+ }),
2742
+ /* @__PURE__ */ jsx("span", { className: "h-px flex-1 bg-(--clarify-theme-tokens-colors-border)" })
2743
+ ]
2744
+ }) : null, option.schemes.length === 0 ? /* @__PURE__ */ jsx("div", {
2745
+ className: "py-4 text-sm/6 font-medium text-(--clarify-theme-tokens-colors-foreground)",
2746
+ children: t("openapi.authNoAuth")
2747
+ }) : /* @__PURE__ */ jsx("div", {
2748
+ className: "divide-y divide-(--clarify-theme-tokens-colors-border)",
2749
+ children: option.schemes.map((schemeOption, schemeIndex) => {
2750
+ const { scheme } = schemeOption;
2751
+ const details = [
2752
+ scheme.type === "apiKey" && scheme.in && scheme.name ? t("openapi.authLocation", {
2753
+ in: scheme.in,
2754
+ name: scheme.name
2755
+ }) : void 0,
2756
+ scheme.type === "http" && scheme.bearerFormat ? t("openapi.authBearerFormat", { format: scheme.bearerFormat }) : void 0,
2757
+ scheme.type === "openIdConnect" ? scheme.openIdConnectUrl : void 0,
2758
+ schemeOption.scopes.length > 0 ? t("openapi.authScopes", { scopes: schemeOption.scopes.join(", ") }) : void 0
2759
+ ].filter((value) => Boolean(value));
2760
+ return /* @__PURE__ */ jsxs("div", { children: [schemeIndex > 0 ? /* @__PURE__ */ jsx("div", {
2761
+ className: "relative h-0",
2762
+ children: /* @__PURE__ */ jsx("span", {
2763
+ className: "absolute top-0 left-4 -translate-y-1/2 bg-(--clarify-theme-tokens-colors-background) px-1.5 text-2xs font-semibold text-(--clarify-ui-text-faint)",
2764
+ children: t("openapi.authAnd")
2765
+ })
2766
+ }) : null, /* @__PURE__ */ jsxs("div", {
2767
+ className: "py-4",
2768
+ children: [
2769
+ /* @__PURE__ */ jsxs("div", {
2770
+ className: "flex flex-wrap items-center gap-2",
2771
+ children: [/* @__PURE__ */ jsx("span", {
2772
+ className: "font-mono text-sm/6 font-semibold text-(--clarify-theme-tokens-colors-foreground)",
2773
+ children: schemeOption.name
2774
+ }), /* @__PURE__ */ jsx("span", {
2775
+ className: "rounded bg-(--clarify-ui-subtle-background) px-1.5 py-0.5 text-2xs font-semibold text-(--clarify-ui-text-soft)",
2776
+ children: authSchemeType(schemeOption, t("openapi.authApiKey"))
2777
+ })]
2778
+ }),
2779
+ scheme.description ? /* @__PURE__ */ jsx(Markdown, {
2780
+ className: "mt-2 text-sm/6 text-(--clarify-ui-text-soft) *:first:mt-0 *:last:mb-0",
2781
+ children: scheme.description
2782
+ }) : null,
2783
+ details.length > 0 ? /* @__PURE__ */ jsx("div", {
2784
+ className: "mt-2 flex min-w-0 flex-wrap gap-x-4 gap-y-1 text-xs/5 text-(--clarify-ui-text-faint)",
2785
+ children: details.map((detail) => /* @__PURE__ */ jsx("span", {
2786
+ className: "min-w-0 break-all font-mono",
2787
+ children: detail
2788
+ }, detail))
2789
+ }) : null
2790
+ ]
2791
+ })] }, schemeOption.name);
2792
+ })
2793
+ })] }, option.key))
2794
+ })] });
2795
+ }
2796
+ //#endregion
2660
2797
  //#region source/openapi/components/SchemaProperties.tsx
2661
2798
  function getEnumDescriptions(schema) {
2662
2799
  const descriptions = schema["x-enumDescriptions"];
@@ -3046,7 +3183,7 @@ function ResponseList(arg0) {
3046
3183
  //#endregion
3047
3184
  //#region source/openapi/components/EndpointSections.tsx
3048
3185
  function EndpointRequest(arg0) {
3049
- const { spec, path, method, operationSource = "path", description, groupedParameters, parameters, requestBody, requestContents, requestSchema, selectedRequestMediaType, onSelectRequestMediaType, selectedServer, serverVariables, auth, sharedExampleKey, onSelectExampleKey } = arg0;
3186
+ const { spec, path, method, operationSource = "path", description, groupedParameters, parameters, requestBody, requestContents, requestSchema, selectedRequestMediaType, onSelectRequestMediaType, selectedServer, serverVariables, authOptions, auth, sharedExampleKey, onSelectExampleKey } = arg0;
3050
3187
  const t = useBuiltInText();
3051
3188
  const hasRequestBody = Boolean(requestBody && requestContents.length > 0);
3052
3189
  const renderDescription = () => {
@@ -3069,6 +3206,7 @@ function EndpointRequest(arg0) {
3069
3206
  children: [/* @__PURE__ */ jsx(Col, { children: /* @__PURE__ */ jsxs("div", {
3070
3207
  className: "w-full",
3071
3208
  children: [
3209
+ /* @__PURE__ */ jsx(OpenApiAuthDocumentation, { options: authOptions }),
3072
3210
  /* @__PURE__ */ jsx(ParameterList, {
3073
3211
  title: t("openapi.pathParameters"),
3074
3212
  parameters: groupedParameters.path
@@ -3164,7 +3302,7 @@ function OptionContent(arg0) {
3164
3302
  })] });
3165
3303
  }
3166
3304
  function InlineListbox(arg0) {
3167
- const { label, value, options, onChange, compact = false, buttonContent, buttonClassName, className, invalid, describedBy, disabled = false } = arg0;
3305
+ const { label, value, options, onChange, compact = false, buttonContent, buttonClassName, className, invalid, describedBy, disabled = false, title } = arg0;
3168
3306
  const selected = options.find((option) => option.value === value);
3169
3307
  return /* @__PURE__ */ jsx(Listbox, {
3170
3308
  value,
@@ -3176,6 +3314,7 @@ function InlineListbox(arg0) {
3176
3314
  "aria-label": label,
3177
3315
  "aria-invalid": invalid || void 0,
3178
3316
  "aria-describedby": describedBy,
3317
+ title,
3179
3318
  className: clsx(buttonClassName ?? defaultButtonClassName, buttonClassName ? null : compact ? "min-h-7 max-w-32 px-2 py-0.5 text-xs" : "min-h-8 w-full px-2 text-xs"),
3180
3319
  children: buttonContent ?? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
3181
3320
  className: "truncate",
@@ -3353,7 +3492,8 @@ function parseBodyObject(body) {
3353
3492
  return;
3354
3493
  }
3355
3494
  }
3356
- function buildRequestBody(body, mediaType) {
3495
+ function buildRequestBody(body, mediaType, files) {
3496
+ if (files[""] && !mediaType.includes("multipart/form-data")) return files[""];
3357
3497
  const values = parseBodyObject(body);
3358
3498
  if (mediaType.includes("application/x-www-form-urlencoded") && values) {
3359
3499
  const params = new URLSearchParams();
@@ -3362,7 +3502,18 @@ function buildRequestBody(body, mediaType) {
3362
3502
  }
3363
3503
  if (mediaType.includes("multipart/form-data") && values) {
3364
3504
  const form = new FormData();
3365
- Object.entries(values).forEach(([name, value]) => form.append(name, typeof value === "string" ? value : JSON.stringify(value)));
3505
+ Object.entries(values).forEach(([name, value]) => {
3506
+ const file = files[name];
3507
+ form.append(name, file ?? (typeof value === "string" ? value : JSON.stringify(value)));
3508
+ });
3509
+ Object.entries(files).forEach(([name, file]) => {
3510
+ if (name && !(name in values)) form.append(name, file);
3511
+ });
3512
+ return form;
3513
+ }
3514
+ if (mediaType.includes("multipart/form-data") && Object.keys(files).length > 0) {
3515
+ const form = new FormData();
3516
+ Object.entries(files).forEach(([name, file]) => form.append(name, file));
3366
3517
  return form;
3367
3518
  }
3368
3519
  return body;
@@ -3465,9 +3616,9 @@ function buildApiRequest(input) {
3465
3616
  }
3466
3617
  const url = new URL(joinPath(expandServerUrl(input.server, input.serverVariables ?? {}), path), input.baseUrl);
3467
3618
  query.forEach((value, key) => url.searchParams.append(key, value));
3468
- const body = input.body?.trim();
3619
+ const body = input.body?.trim() ?? "";
3469
3620
  const mediaType = input.mediaType || "application/json";
3470
- const requestBody = body && input.method.toUpperCase() !== "GET" && input.method.toUpperCase() !== "HEAD" ? buildRequestBody(body, mediaType) : void 0;
3621
+ const requestBody = (Boolean(body) || Object.keys(input.bodyFiles ?? {}).length > 0) && input.method.toUpperCase() !== "GET" && input.method.toUpperCase() !== "HEAD" ? buildRequestBody(body, mediaType, input.bodyFiles ?? {}) : void 0;
3471
3622
  if (requestBody && !(requestBody instanceof FormData)) headers.set("Content-Type", mediaType);
3472
3623
  return {
3473
3624
  url: url.toString(),
@@ -3526,6 +3677,157 @@ function OpenApiAuthPanel(arg0) {
3526
3677
  });
3527
3678
  }
3528
3679
  //#endregion
3680
+ //#region source/openapi/components/OpenApiRequestBodyEditor.tsx
3681
+ function parseBodyRecord(body) {
3682
+ try {
3683
+ const value = JSON.parse(body);
3684
+ return isRecord$1(value) ? value : {};
3685
+ } catch {
3686
+ return {};
3687
+ }
3688
+ }
3689
+ function isBinarySchema(schema) {
3690
+ return isRecord$1(schema) && schema.format === "binary";
3691
+ }
3692
+ function isTextMediaType(mediaType) {
3693
+ return mediaType.startsWith("text/") || mediaType.includes("json") || mediaType.includes("xml") || mediaType.includes("yaml") || mediaType.includes("javascript") || mediaType.includes("form");
3694
+ }
3695
+ function isFormMediaType(mediaType) {
3696
+ const normalized = mediaType.split(";", 1)[0].trim().toLowerCase();
3697
+ return normalized === "application/x-www-form-urlencoded" || normalized === "multipart/form-data";
3698
+ }
3699
+ function valueFromInput(schema, value) {
3700
+ if (!isRecord$1(schema)) return value;
3701
+ if (schemaHasType(schema, "integer")) return value === "" ? "" : Number.parseInt(value, 10);
3702
+ if (schemaHasType(schema, "number")) return value === "" ? "" : Number(value);
3703
+ if (schemaHasType(schema, "boolean")) return value === "true";
3704
+ if (schemaHasType(schema, "array") || schemaHasType(schema, "object")) try {
3705
+ return JSON.parse(value);
3706
+ } catch {
3707
+ return value;
3708
+ }
3709
+ return value;
3710
+ }
3711
+ function OpenApiRequestBodyEditor(arg0) {
3712
+ const { spec, mediaType, content, body, files, onBodyChange, onFileChange } = arg0;
3713
+ const schema = resolveSchema(spec, content?.schema);
3714
+ const schemaRecord = isRecord$1(schema) ? schema : void 0;
3715
+ const properties = isRecord$1(schemaRecord?.properties) ? schemaRecord.properties : void 0;
3716
+ const required = new Set(Array.isArray(schemaRecord?.required) ? schemaRecord.required.map(String) : []);
3717
+ const values = parseBodyRecord(body);
3718
+ function updateProperty(name, propertySchema, value) {
3719
+ onBodyChange(JSON.stringify({
3720
+ ...values,
3721
+ [name]: valueFromInput(propertySchema, value)
3722
+ }, null, 2));
3723
+ }
3724
+ function renderProperty(name, unresolvedSchema) {
3725
+ const propertySchema = resolveSchema(spec, unresolvedSchema);
3726
+ const propertyRecord = isRecord$1(propertySchema) ? propertySchema : void 0;
3727
+ const type = schemaToType(propertySchema) ?? "string";
3728
+ const value = values[name];
3729
+ const fieldId = `openapi-request-body-${name}`.replace(/[^a-zA-Z0-9_-]/g, "-");
3730
+ const options = Array.isArray(propertyRecord?.enum) ? propertyRecord.enum : [];
3731
+ const structured = schemaHasType(propertySchema, "array") || schemaHasType(propertySchema, "object");
3732
+ const serializedValue = structured && typeof value !== "undefined" ? JSON.stringify(value, null, 2) : String(value ?? "");
3733
+ let control;
3734
+ if (isBinarySchema(propertySchema)) control = /* @__PURE__ */ jsx("input", {
3735
+ id: fieldId,
3736
+ "aria-label": name,
3737
+ type: "file",
3738
+ required: required.has(name),
3739
+ onChange: (event) => onFileChange(name, event.target.files?.[0]),
3740
+ className: "min-h-8 w-full px-2 py-1 text-xs text-(--clarify-theme-tokens-colors-foreground) file:mr-2 file:rounded-(--clarify-theme-tokens-radius-md) file:border file:border-(--clarify-theme-tokens-colors-border) file:bg-(--clarify-ui-subtle-background) file:px-2 file:py-1 file:text-xs file:text-(--clarify-ui-text-strong)"
3741
+ });
3742
+ else if (options.length > 0) control = /* @__PURE__ */ jsxs("select", {
3743
+ id: fieldId,
3744
+ "aria-label": name,
3745
+ value: serializedValue,
3746
+ required: required.has(name),
3747
+ onChange: (event) => updateProperty(name, propertySchema, event.target.value),
3748
+ className: "h-8 w-full border-0 bg-transparent px-2 font-mono text-xs text-(--clarify-theme-tokens-colors-foreground) outline-hidden focus:bg-(--clarify-ui-hover-background)",
3749
+ children: [!required.has(name) ? /* @__PURE__ */ jsx("option", { value: "" }) : null, options.map((option) => /* @__PURE__ */ jsx("option", {
3750
+ value: String(option),
3751
+ children: String(option)
3752
+ }, String(option)))]
3753
+ });
3754
+ else if (schemaHasType(propertySchema, "boolean")) control = /* @__PURE__ */ jsx("input", {
3755
+ id: fieldId,
3756
+ "aria-label": name,
3757
+ type: "checkbox",
3758
+ checked: value === true,
3759
+ onChange: (event) => updateProperty(name, propertySchema, String(event.target.checked)),
3760
+ className: "size-4 accent-(--clarify-theme-tokens-colors-primary)"
3761
+ });
3762
+ else if (structured) control = /* @__PURE__ */ jsx("textarea", {
3763
+ id: fieldId,
3764
+ "aria-label": name,
3765
+ value: serializedValue,
3766
+ required: required.has(name),
3767
+ rows: 3,
3768
+ spellCheck: false,
3769
+ onChange: (event) => updateProperty(name, propertySchema, event.target.value),
3770
+ className: "w-full resize-y border-0 bg-transparent p-2 font-mono text-xs/5 text-(--clarify-theme-tokens-colors-foreground) outline-hidden focus:bg-(--clarify-ui-hover-background)"
3771
+ });
3772
+ else control = /* @__PURE__ */ jsx("input", {
3773
+ id: fieldId,
3774
+ "aria-label": name,
3775
+ value: serializedValue,
3776
+ type: schemaHasType(propertySchema, "integer") || schemaHasType(propertySchema, "number") ? "number" : propertyRecord?.format === "date" ? "date" : propertyRecord?.format === "date-time" ? "datetime-local" : "text",
3777
+ required: required.has(name),
3778
+ onChange: (event) => updateProperty(name, propertySchema, event.target.value),
3779
+ className: "h-8 w-full border-0 bg-transparent px-2 font-mono text-xs text-(--clarify-theme-tokens-colors-foreground) outline-hidden focus:bg-(--clarify-ui-hover-background)"
3780
+ });
3781
+ return /* @__PURE__ */ jsxs("div", {
3782
+ className: "grid min-w-0 grid-cols-[minmax(0,1fr)_minmax(0,1.3fr)]",
3783
+ children: [/* @__PURE__ */ jsxs("label", {
3784
+ htmlFor: fieldId,
3785
+ className: "flex min-h-8 min-w-0 items-center gap-1.5 border-r border-(--clarify-theme-tokens-colors-border) px-2 text-xs text-(--clarify-ui-text-strong)",
3786
+ children: [
3787
+ /* @__PURE__ */ jsx("span", {
3788
+ className: "truncate font-mono",
3789
+ children: name
3790
+ }),
3791
+ /* @__PURE__ */ jsx("span", {
3792
+ className: "font-mono text-2xs text-(--clarify-ui-text-faint)",
3793
+ children: type
3794
+ }),
3795
+ required.has(name) ? /* @__PURE__ */ jsx("span", {
3796
+ className: "text-(--clarify-error-accent-text)",
3797
+ children: "*"
3798
+ }) : null
3799
+ ]
3800
+ }), /* @__PURE__ */ jsxs("div", {
3801
+ className: "flex min-w-0 items-center",
3802
+ children: [control, files[name] ? /* @__PURE__ */ jsx("span", {
3803
+ className: "sr-only",
3804
+ children: files[name].name
3805
+ }) : null]
3806
+ })]
3807
+ }, name);
3808
+ }
3809
+ if (properties && isFormMediaType(mediaType)) return /* @__PURE__ */ jsx("div", {
3810
+ className: "divide-y divide-(--clarify-theme-tokens-colors-border)",
3811
+ children: Object.entries(properties).map(([name, propertySchema]) => renderProperty(name, propertySchema))
3812
+ });
3813
+ if (isBinarySchema(schema) || !isTextMediaType(mediaType)) return /* @__PURE__ */ jsx("div", {
3814
+ className: "flex min-h-44 items-start p-3",
3815
+ children: /* @__PURE__ */ jsx("input", {
3816
+ "aria-label": mediaType,
3817
+ type: "file",
3818
+ onChange: (event) => onFileChange("", event.target.files?.[0]),
3819
+ className: "w-full text-xs text-(--clarify-theme-tokens-colors-foreground) file:mr-2 file:rounded-(--clarify-theme-tokens-radius-md) file:border file:border-(--clarify-theme-tokens-colors-border) file:bg-(--clarify-ui-subtle-background) file:px-2 file:py-1 file:text-xs file:text-(--clarify-ui-text-strong)"
3820
+ })
3821
+ });
3822
+ return /* @__PURE__ */ jsx("textarea", {
3823
+ "aria-label": mediaType,
3824
+ value: body,
3825
+ onChange: (event) => onBodyChange(event.target.value),
3826
+ spellCheck: false,
3827
+ className: "block h-full min-h-44 w-full resize-none border-0 bg-(--clarify-code-background) p-3 font-mono text-xs/5 text-(--clarify-code-text) outline-hidden focus:ring-2 focus:ring-inset focus:ring-(--clarify-theme-tokens-colors-primary)"
3828
+ });
3829
+ }
3830
+ //#endregion
3529
3831
  //#region source/openapi/components/OpenApiRequestFields.tsx
3530
3832
  function RequestField(arg0) {
3531
3833
  const { spec, parameter, value, enabled, onChange, onEnabledChange, issue } = arg0;
@@ -3562,7 +3864,7 @@ function RequestField(arg0) {
3562
3864
  children: description
3563
3865
  }),
3564
3866
  side: "bottom",
3565
- className: "mr-1 shrink-0 [&>[role=tooltip]]:w-80 [&>[role=tooltip]]:max-w-[min(20rem,calc(100vw-2rem))] [&>[role=tooltip]]:border [&>[role=tooltip]]:border-(--clarify-theme-tokens-colors-border) [&>[role=tooltip]]:bg-(--clarify-theme-tokens-colors-surface) [&>[role=tooltip]]:p-3 [&>[role=tooltip]]:text-(--clarify-ui-text) [&>[role=tooltip]]:shadow-xl",
3867
+ className: "mr-1 shrink-0 *:[[role=tooltip]]:w-80 *:[[role=tooltip]]:max-w-[min(20rem,calc(100vw-2rem))] *:[[role=tooltip]]:border *:[[role=tooltip]]:border-(--clarify-theme-tokens-colors-border) *:[[role=tooltip]]:bg-(--clarify-theme-tokens-colors-surface) *:[[role=tooltip]]:p-3 *:[[role=tooltip]]:text-(--clarify-ui-text) *:[[role=tooltip]]:shadow-xl",
3566
3868
  triggerClassName: "clarify-field-description-trigger clarify-ui-control inline-flex size-7 items-center justify-center rounded-md !border-b-0 text-(--clarify-ui-text-faint) transition-colors",
3567
3869
  children: [/* @__PURE__ */ jsx(InfoIcon, {
3568
3870
  className: "size-4",
@@ -3608,7 +3910,7 @@ function RequestField(arg0) {
3608
3910
  })
3609
3911
  }),
3610
3912
  /* @__PURE__ */ jsxs("div", {
3611
- className: clsx("col-start-2 flex min-w-0 items-center border-t border-(--clarify-theme-tokens-colors-border) sm:col-start-3 sm:row-start-1 sm:border-t-0", !enabled && "opacity-45"),
3913
+ className: clsx("col-start-2 flex min-w-0 items-center border-t border-(--clarify-theme-tokens-colors-border) sm:col-start-3 sm:row-start-1 sm:border-t-0", !enabled && "bg-(--clarify-ui-subtle-background)"),
3612
3914
  children: [/* @__PURE__ */ jsx("div", {
3613
3915
  className: "min-w-0 flex-1",
3614
3916
  children: itemOptions.length > 0 ? /* @__PURE__ */ jsx(MultiInlineListbox, {
@@ -3721,6 +4023,57 @@ function parseJson(value) {
3721
4023
  return;
3722
4024
  }
3723
4025
  }
4026
+ var textLanguages = {
4027
+ "application/graphql": "graphql",
4028
+ "application/javascript": "javascript",
4029
+ "application/sql": "sql",
4030
+ "application/typescript": "typescript",
4031
+ "application/xml": "xml",
4032
+ "application/x-httpd-php": "php",
4033
+ "application/x-sh": "shellscript",
4034
+ "application/xhtml+xml": "html",
4035
+ "application/x-www-form-urlencoded": "http",
4036
+ "text/css": "css",
4037
+ "text/csv": "csv",
4038
+ "text/html": "html",
4039
+ "text/javascript": "javascript",
4040
+ "text/markdown": "markdown",
4041
+ "text/plain": "text",
4042
+ "text/xml": "xml"
4043
+ };
4044
+ function normalizedMediaType(contentType) {
4045
+ return contentType.split(";", 1)[0].trim().toLowerCase();
4046
+ }
4047
+ function getResponseTextPreview(contentType, body) {
4048
+ const mediaType = normalizedMediaType(contentType);
4049
+ if (mediaType === "application/json" || mediaType.endsWith("+json")) {
4050
+ const parsed = parseJson(body);
4051
+ return {
4052
+ code: typeof parsed === "undefined" ? body : JSON.stringify(parsed, null, 2),
4053
+ language: "json"
4054
+ };
4055
+ }
4056
+ if (mediaType === "application/yaml" || mediaType === "application/x-yaml" || mediaType === "text/yaml" || mediaType === "text/x-yaml" || mediaType.endsWith("+yaml")) try {
4057
+ return {
4058
+ code: stringify(parse(body)).trimEnd(),
4059
+ language: "yaml"
4060
+ };
4061
+ } catch {
4062
+ return {
4063
+ code: body,
4064
+ language: "yaml"
4065
+ };
4066
+ }
4067
+ const language = textLanguages[mediaType] ?? (mediaType.startsWith("text/") ? mediaType.slice(5) || "text" : void 0);
4068
+ return language ? {
4069
+ code: body,
4070
+ language
4071
+ } : void 0;
4072
+ }
4073
+ function canPreviewResponse(contentType) {
4074
+ const mediaType = normalizedMediaType(contentType);
4075
+ return Boolean(getResponseTextPreview(contentType, "") || mediaType.startsWith("image/") || mediaType.startsWith("audio/") || mediaType.startsWith("video/"));
4076
+ }
3724
4077
  function ResponseState(arg0) {
3725
4078
  const { icon: Icon, title, description, tone = "default" } = arg0;
3726
4079
  const error = tone === "error";
@@ -3749,38 +4102,6 @@ function ResponseState(arg0) {
3749
4102
  })
3750
4103
  });
3751
4104
  }
3752
- function JsonPreview(arg0) {
3753
- const { value } = arg0;
3754
- if (Array.isArray(value)) return /* @__PURE__ */ jsx("div", {
3755
- className: "space-y-1 border-l border-(--clarify-code-border) pl-3",
3756
- children: value.map((item, index) => /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("span", {
3757
- className: "mr-2 text-(--clarify-code-faint)",
3758
- children: index
3759
- }), /* @__PURE__ */ jsx(JsonPreview, { value: item })] }, index))
3760
- });
3761
- if (isRecord$1(value)) return /* @__PURE__ */ jsx("div", {
3762
- className: "space-y-1 border-l border-(--clarify-code-border) pl-3",
3763
- children: Object.entries(value).map(([key, item]) => /* @__PURE__ */ jsxs("div", {
3764
- className: "grid grid-cols-[minmax(5rem,auto)_1fr] gap-3",
3765
- children: [/* @__PURE__ */ jsx("span", {
3766
- className: "text-(--clarify-code-property)",
3767
- children: key
3768
- }), /* @__PURE__ */ jsx(JsonPreview, { value: item })]
3769
- }, key))
3770
- });
3771
- if (value === null) return /* @__PURE__ */ jsx("span", {
3772
- className: "text-(--clarify-code-faint)",
3773
- children: "null"
3774
- });
3775
- if (typeof value === "string") return /* @__PURE__ */ jsx("span", {
3776
- className: "wrap-break-word text-(--clarify-code-string)",
3777
- children: value
3778
- });
3779
- return /* @__PURE__ */ jsx("span", {
3780
- className: "text-(--clarify-code-number)",
3781
- children: String(value)
3782
- });
3783
- }
3784
4105
  function CopyButton(arg0) {
3785
4106
  const { value } = arg0;
3786
4107
  const t = useBuiltInText();
@@ -3837,22 +4158,12 @@ function ResponseMedia(arg0) {
3837
4158
  function ResponsePreview(arg0) {
3838
4159
  const { exchange } = arg0;
3839
4160
  const t = useBuiltInText();
3840
- const contentType = exchange.contentType.toLowerCase();
4161
+ const contentType = normalizedMediaType(exchange.contentType);
3841
4162
  if (!exchange.size) return /* @__PURE__ */ jsx(ResponseState, {
3842
4163
  icon: FileX2Icon,
3843
4164
  title: t("openapi.responseBodyEmptyTitle"),
3844
4165
  description: t("openapi.responseBodyEmpty")
3845
4166
  });
3846
- if (contentType.includes("json")) {
3847
- const parsed = parseJson(exchange.body);
3848
- return typeof parsed === "undefined" ? /* @__PURE__ */ jsx("pre", {
3849
- className: "whitespace-pre-wrap wrap-break-word font-mono text-xs/5",
3850
- children: exchange.body
3851
- }) : /* @__PURE__ */ jsx("div", {
3852
- className: "overflow-auto font-mono text-xs/5",
3853
- children: /* @__PURE__ */ jsx(JsonPreview, { value: parsed })
3854
- });
3855
- }
3856
4167
  if (contentType.startsWith("image/")) return /* @__PURE__ */ jsx(ResponseMedia, {
3857
4168
  blob: exchange.blob,
3858
4169
  type: "image"
@@ -3865,15 +4176,19 @@ function ResponsePreview(arg0) {
3865
4176
  blob: exchange.blob,
3866
4177
  type: "video"
3867
4178
  });
3868
- if (contentType.includes("html")) return /* @__PURE__ */ jsx("iframe", {
4179
+ if (contentType === "text/html" || contentType === "application/xhtml+xml") return /* @__PURE__ */ jsx("iframe", {
3869
4180
  srcDoc: exchange.body,
3870
4181
  sandbox: "",
3871
4182
  title: "Response preview",
3872
4183
  className: "h-96 w-full border-0 bg-white"
3873
4184
  });
3874
- if (contentType.startsWith("text/") || contentType.includes("xml") || contentType.includes("yaml")) return /* @__PURE__ */ jsx("pre", {
3875
- className: "whitespace-pre-wrap wrap-break-word font-mono text-xs/5",
3876
- children: exchange.body
4185
+ const textPreview = getResponseTextPreview(exchange.contentType, exchange.body);
4186
+ if (textPreview) return /* @__PURE__ */ jsx("pre", {
4187
+ className: "max-h-128 overflow-auto whitespace-pre-wrap wrap-break-word font-mono text-xs/5",
4188
+ children: /* @__PURE__ */ jsx(HighlightedCode, {
4189
+ code: textPreview.code,
4190
+ language: textPreview.language
4191
+ })
3877
4192
  });
3878
4193
  return /* @__PURE__ */ jsx("div", {
3879
4194
  className: "grid min-h-56 place-items-center text-xs text-(--clarify-code-faint)",
@@ -3980,7 +4295,10 @@ function HiddenCookies() {
3980
4295
  function OpenApiResponseViewer(arg0) {
3981
4296
  const { exchange, error } = arg0;
3982
4297
  const t = useBuiltInText();
3983
- const [bodyMode, setBodyMode] = useState("preview");
4298
+ const [bodyModeSelection, setBodyModeSelection] = useState();
4299
+ const previewAvailable = exchange ? canPreviewResponse(exchange.contentType) : false;
4300
+ const selectedBodyMode = bodyModeSelection && bodyModeSelection.exchange === exchange ? bodyModeSelection.mode : "preview";
4301
+ const activeBodyMode = previewAvailable ? selectedBodyMode : "raw";
3984
4302
  function downloadBody() {
3985
4303
  if (!exchange) return;
3986
4304
  const url = URL.createObjectURL(exchange.blob);
@@ -4062,12 +4380,15 @@ function OpenApiResponseViewer(arg0) {
4062
4380
  children: [/* @__PURE__ */ jsx("div", {
4063
4381
  role: "tablist",
4064
4382
  className: "flex",
4065
- children: ["preview", "raw"].map((mode) => /* @__PURE__ */ jsx("button", {
4383
+ children: ["preview", "raw"].filter((mode) => mode === "raw" || previewAvailable).map((mode) => /* @__PURE__ */ jsx("button", {
4066
4384
  type: "button",
4067
4385
  role: "tab",
4068
- "aria-selected": bodyMode === mode,
4069
- onClick: () => setBodyMode(mode),
4070
- className: clsx("border-b-2 px-2.5 py-1 text-2xs font-semibold", bodyMode === mode ? "border-(--clarify-theme-tokens-colors-primary) text-(--clarify-code-text)" : "border-transparent text-(--clarify-code-muted)"),
4386
+ "aria-selected": activeBodyMode === mode,
4387
+ onClick: () => setBodyModeSelection({
4388
+ exchange,
4389
+ mode
4390
+ }),
4391
+ className: clsx("border-b-2 px-2.5 py-1 text-2xs font-semibold", activeBodyMode === mode ? "border-(--clarify-theme-tokens-colors-primary) text-(--clarify-code-text)" : "border-transparent text-(--clarify-code-muted)"),
4071
4392
  children: mode === "preview" ? t("openapi.preview") : t("openapi.raw")
4072
4393
  }, mode))
4073
4394
  }), /* @__PURE__ */ jsxs("div", {
@@ -4086,7 +4407,7 @@ function OpenApiResponseViewer(arg0) {
4086
4407
  })]
4087
4408
  }), /* @__PURE__ */ jsx("div", {
4088
4409
  className: "p-4",
4089
- children: bodyMode === "preview" ? /* @__PURE__ */ jsx(ResponsePreview, { exchange }) : exchange.size ? /* @__PURE__ */ jsx("pre", {
4410
+ children: activeBodyMode === "preview" ? /* @__PURE__ */ jsx(ResponsePreview, { exchange }) : exchange.size ? /* @__PURE__ */ jsx("pre", {
4090
4411
  className: "max-h-128 overflow-auto whitespace-pre-wrap wrap-break-word font-mono text-xs/5",
4091
4412
  children: exchange.body
4092
4413
  }) : /* @__PURE__ */ jsx("div", {
@@ -4208,6 +4529,23 @@ function validateRequestParameters(spec, parameters, values) {
4208
4529
  }
4209
4530
  //#endregion
4210
4531
  //#region source/openapi/components/useOpenApiRequestState.ts
4532
+ function initialRequestBody(spec, content) {
4533
+ const example = getExampleEntries(content, spec)[0];
4534
+ if (!example?.generated) return stringifyExample(example?.value);
4535
+ const schema = resolveSchema(spec, content?.schema);
4536
+ if (isRecord$1(schema) && schema.format === "binary") return "";
4537
+ if (!isRecord$1(example.value) || !isRecord$1(schema) || !isRecord$1(schema.properties)) return stringifyExample(example.value);
4538
+ const value = { ...example.value };
4539
+ Object.entries(schema.properties).forEach(([name, propertySchema]) => {
4540
+ const resolved = resolveSchema(spec, propertySchema);
4541
+ if (isRecord$1(resolved) && resolved.format === "binary") delete value[name];
4542
+ });
4543
+ return stringifyExample(value);
4544
+ }
4545
+ function requestBodyForExample(spec, content, exampleKey) {
4546
+ const example = getExampleEntries(content, spec).find((entry) => !entry.generated && entry.key === exampleKey);
4547
+ return example ? stringifyExample(example.value) : initialRequestBody(spec, content);
4548
+ }
4211
4549
  function useOpenApiRequestTarget(spec, path, operation, operationSource) {
4212
4550
  const servers = getServers(spec, operation, path, operationSource);
4213
4551
  const [selectedServerKey, setSelectedServerKey] = useState(getServerKey(servers[0], 0));
@@ -4222,7 +4560,9 @@ function useOpenApiRequestTarget(spec, path, operation, operationSource) {
4222
4560
  const clearCredential = useOpenApiStore((state) => state.clearCredential);
4223
4561
  const requestContents = getMediaTypeEntries(getRequestBody$1(spec, operation)?.content, spec);
4224
4562
  const [mediaType, setMediaType] = useState(requestContents[0]?.mediaType ?? "");
4225
- const [body, setBody] = useState(stringifyExample(getExampleEntries((requestContents.find((entry) => entry.mediaType === mediaType) ?? requestContents[0])?.value, spec)[0]?.value));
4563
+ const selectedContent = requestContents.find((entry) => entry.mediaType === mediaType) ?? requestContents[0];
4564
+ const [body, setBody] = useState(initialRequestBody(spec, selectedContent?.value));
4565
+ const [bodyFiles, setBodyFiles] = useState({});
4226
4566
  function selectServer(value) {
4227
4567
  const nextServer = servers.find((server, index) => getServerKey(server, index) === value) ?? servers[0];
4228
4568
  setSelectedServerKey(value);
@@ -4231,7 +4571,20 @@ function useOpenApiRequestTarget(spec, path, operation, operationSource) {
4231
4571
  function selectMediaType(value) {
4232
4572
  const content = requestContents.find((entry) => entry.mediaType === value)?.value;
4233
4573
  setMediaType(value);
4234
- setBody(stringifyExample(getExampleEntries(content, spec)[0]?.value));
4574
+ setBody(initialRequestBody(spec, content));
4575
+ setBodyFiles({});
4576
+ }
4577
+ function applyBodyExample(exampleKey) {
4578
+ setBody(requestBodyForExample(spec, selectedContent?.value, exampleKey));
4579
+ setBodyFiles({});
4580
+ }
4581
+ function setBodyFile(name, file) {
4582
+ setBodyFiles((current) => {
4583
+ const next = { ...current };
4584
+ if (file) next[name] = file;
4585
+ else delete next[name];
4586
+ return next;
4587
+ });
4235
4588
  }
4236
4589
  return {
4237
4590
  servers,
@@ -4251,13 +4604,20 @@ function useOpenApiRequestTarget(spec, path, operation, operationSource) {
4251
4604
  clearCredential,
4252
4605
  requestContents,
4253
4606
  mediaType,
4607
+ selectedContent,
4254
4608
  body,
4255
4609
  setBody,
4610
+ bodyFiles,
4611
+ setBodyFile,
4612
+ applyBodyExample,
4256
4613
  selectMediaType
4257
4614
  };
4258
4615
  }
4259
- function useOpenApiParameterState(spec, parameters, initialParameterValue) {
4260
- const [parameterValues, setParameterValues] = useState(() => Object.fromEntries(parameters.map((parameter) => [parameterKey(parameter), initialParameterValue(parameter)])));
4616
+ function useOpenApiParameterState(spec, parameters, initialParameterValue, initialExampleKey = "") {
4617
+ const [parameterValues, setParameterValues] = useState(() => Object.fromEntries(parameters.map((parameter) => {
4618
+ const example = getParameterExampleEntries(parameter).find((entry) => entry.key === initialExampleKey);
4619
+ return [parameterKey(parameter), example ? stringifyExample(example.value) : initialParameterValue(parameter)];
4620
+ })));
4261
4621
  const [parameterEnabled, setParameterEnabled] = useState(() => Object.fromEntries(parameters.map((parameter) => [parameterKey(parameter), true])));
4262
4622
  const [parameterIssues, setParameterIssues] = useState({});
4263
4623
  function setParameterGroupValues(grouped, mode) {
@@ -4292,6 +4652,13 @@ function useOpenApiParameterState(spec, parameters, initialParameterValue) {
4292
4652
  return next;
4293
4653
  });
4294
4654
  }
4655
+ function applyParameterExample(exampleKey) {
4656
+ setParameterValues(Object.fromEntries(parameters.map((parameter) => {
4657
+ const example = getParameterExampleEntries(parameter).find((entry) => entry.key === exampleKey);
4658
+ return [parameterKey(parameter), example ? stringifyExample(example.value) : initialParameterValue(parameter)];
4659
+ })));
4660
+ setParameterIssues({});
4661
+ }
4295
4662
  function validate(parametersToValidate) {
4296
4663
  const issues = validateRequestParameters(spec, parametersToValidate, parameterValues);
4297
4664
  setParameterIssues(issues);
@@ -4304,6 +4671,7 @@ function useOpenApiParameterState(spec, parameters, initialParameterValue) {
4304
4671
  setParameterGroupValues,
4305
4672
  setParameterIncluded,
4306
4673
  updateParameterValue,
4674
+ applyParameterExample,
4307
4675
  validate
4308
4676
  };
4309
4677
  }
@@ -4343,6 +4711,7 @@ function useOpenApiRequestExecution() {
4343
4711
  //#endregion
4344
4712
  //#region source/openapi/components/OpenApiRequest.tsx
4345
4713
  function initialParameterValue(spec, parameter) {
4714
+ if (typeof parameter.example !== "undefined") return stringifyExample(parameter.example);
4346
4715
  const schema = resolveSchema(spec, parameter.schema);
4347
4716
  if (!isRecord$1(schema)) return "";
4348
4717
  return stringifyExample(schema.example ?? schema.default ?? (Array.isArray(schema.enum) ? schema.enum[0] : void 0));
@@ -4357,9 +4726,12 @@ function OpenApiRequestWorkbench(arg0) {
4357
4726
  const { spec, path, method, operation, operationSource = "path", compact = false, onClose } = arg0;
4358
4727
  const t = useBuiltInText();
4359
4728
  const parameters = getOperationParameters(spec, path, operation, operationSource);
4360
- const { servers, selectedServer, selectedServerKey, serverVariables, setServerVariables, serverVariableEntries, selectServer, authOptions, selectedAuthName, setSelectedAuthName, selectedAuth, credentialScope, credentials, setCredential, clearCredential, requestContents, mediaType, body, setBody, selectMediaType } = useOpenApiRequestTarget(spec, path, operation, operationSource);
4361
- const parameterState = useOpenApiParameterState(spec, parameters, (parameter) => initialParameterValue(spec, parameter));
4362
- const { parameterValues, parameterEnabled, parameterIssues, setParameterGroupValues, setParameterIncluded, updateParameterValue } = parameterState;
4729
+ const { servers, selectedServer, selectedServerKey, serverVariables, setServerVariables, serverVariableEntries, selectServer, authOptions, selectedAuthName, setSelectedAuthName, selectedAuth, credentialScope, credentials, setCredential, clearCredential, requestContents, mediaType, selectedContent, body, setBody, bodyFiles, setBodyFile, applyBodyExample, selectMediaType } = useOpenApiRequestTarget(spec, path, operation, operationSource);
4730
+ const requestExamples = getRequestExampleEntries(parameters, selectedContent?.value);
4731
+ const [selectedRequestExampleKey, setSelectedRequestExampleKey] = useState(requestExamples[0]?.key ?? "");
4732
+ const currentRequestExampleKey = requestExamples.some((example) => example.key === selectedRequestExampleKey) ? selectedRequestExampleKey : requestExamples[0]?.key ?? "";
4733
+ const parameterState = useOpenApiParameterState(spec, parameters, (parameter) => initialParameterValue(spec, parameter), currentRequestExampleKey);
4734
+ const { parameterValues, parameterEnabled, parameterIssues, setParameterGroupValues, setParameterIncluded, updateParameterValue, applyParameterExample } = parameterState;
4363
4735
  const { exchange, error, sending, execute } = useOpenApiRequestExecution();
4364
4736
  const parameterGroups = [
4365
4737
  "cookie",
@@ -4371,6 +4743,18 @@ function OpenApiRequestWorkbench(arg0) {
4371
4743
  })).filter((group) => group.parameters.length > 0);
4372
4744
  const pathParameters = parameters.filter((parameter) => parameter.in === "path");
4373
4745
  const hasRequestConfiguration = authOptions.length > 0 || serverVariableEntries.length > 0 || parameters.length > 0 || requestContents.length > 0;
4746
+ function applyRequestExample(exampleKey) {
4747
+ setSelectedRequestExampleKey(exampleKey);
4748
+ applyParameterExample(exampleKey);
4749
+ applyBodyExample(exampleKey);
4750
+ }
4751
+ function selectRequestMediaType(value) {
4752
+ const content = requestContents.find((entry) => entry.mediaType === value)?.value;
4753
+ const nextExampleKey = getRequestExampleEntries(parameters, content)[0]?.key ?? "";
4754
+ selectMediaType(value);
4755
+ setSelectedRequestExampleKey(nextExampleKey);
4756
+ applyParameterExample(nextExampleKey);
4757
+ }
4374
4758
  async function sendRequest() {
4375
4759
  const enabledParameters = parameters.filter((parameter) => parameterEnabled[parameterKey(parameter)] !== false);
4376
4760
  const issues = parameterState.validate(enabledParameters);
@@ -4389,6 +4773,7 @@ function OpenApiRequestWorkbench(arg0) {
4389
4773
  })),
4390
4774
  mediaType,
4391
4775
  body,
4776
+ bodyFiles,
4392
4777
  baseUrl: window.location.href
4393
4778
  }), t("openapi.requestCorsHint"));
4394
4779
  }
@@ -4439,44 +4824,84 @@ function OpenApiRequestWorkbench(arg0) {
4439
4824
  }, location);
4440
4825
  }
4441
4826
  function renderHeader() {
4442
- return /* @__PURE__ */ jsxs("div", {
4443
- className: "flex min-w-0 items-center gap-1.5 border-b border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-surface) px-2.5 py-2",
4444
- children: [
4445
- /* @__PURE__ */ jsx(EndpointMethodBadge, { method: method.toUpperCase() }),
4446
- servers.length > 0 ? /* @__PURE__ */ jsx(InlineListbox, {
4447
- label: t("openapi.server"),
4448
- value: selectedServerKey,
4449
- options: servers.map((server, index) => ({
4450
- value: getServerKey(server, index),
4451
- label: server.url ?? `Server ${index + 1}`,
4452
- description: server.description
4453
- })),
4454
- onChange: selectServer,
4455
- className: "min-w-0 max-w-48 shrink sm:max-w-48",
4456
- buttonClassName: "flex h-8 min-w-0 max-w-full items-center gap-1 rounded-(--clarify-theme-tokens-radius-md) px-2 text-xs font-medium text-(--clarify-ui-text-strong) outline-hidden transition hover:bg-(--clarify-ui-hover-background) focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-(--clarify-theme-tokens-colors-primary)"
4457
- }) : null,
4458
- /* @__PURE__ */ jsx("span", {
4459
- className: "min-w-0 flex-1 overflow-x-auto border-l border-(--clarify-theme-tokens-colors-border) pl-2 font-mono text-xs text-(--clarify-theme-tokens-colors-foreground)",
4460
- children: path || "/"
4461
- }),
4462
- /* @__PURE__ */ jsx(SendRequestButton, {
4463
- label: sending ? t("openapi.sendingRequest") : t("openapi.sendRequest"),
4464
- busy: sending,
4465
- text: t("openapi.sendRequest"),
4466
- onClick: sendRequest
4467
- }),
4468
- onClose ? /* @__PURE__ */ jsx("button", {
4469
- type: "button",
4470
- onClick: onClose,
4471
- "aria-label": t("openapi.closeRequest"),
4472
- title: t("openapi.closeRequest"),
4473
- className: "grid size-8 shrink-0 place-items-center rounded-(--clarify-theme-tokens-radius-md) text-(--clarify-ui-text-soft) transition hover:bg-(--clarify-ui-hover-background) hover:text-(--clarify-theme-tokens-colors-foreground) focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-(--clarify-theme-tokens-colors-primary)",
4474
- children: /* @__PURE__ */ jsx(XIcon, {
4475
- className: "size-4",
4476
- "aria-hidden": "true"
4477
- })
4478
- }) : null
4479
- ]
4827
+ return /* @__PURE__ */ jsx("div", {
4828
+ className: "border-b border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-surface)",
4829
+ children: /* @__PURE__ */ jsxs("div", {
4830
+ className: "grid min-w-0 grid-cols-[auto_auto_minmax(0,1fr)_auto_auto] items-center gap-1.5 px-2.5 py-2 lg:grid-cols-[auto_auto_minmax(0,1fr)_minmax(0,14rem)_auto_auto]",
4831
+ children: [
4832
+ /* @__PURE__ */ jsx("div", {
4833
+ className: "col-start-1 row-start-1",
4834
+ children: /* @__PURE__ */ jsx(EndpointMethodBadge, { method: method.toUpperCase() })
4835
+ }),
4836
+ servers.length > 0 ? /* @__PURE__ */ jsx(InlineListbox, {
4837
+ label: t("openapi.server"),
4838
+ value: selectedServerKey,
4839
+ options: servers.map((server, index) => ({
4840
+ value: getServerKey(server, index),
4841
+ label: server.url ?? `Server ${index + 1}`,
4842
+ description: server.description
4843
+ })),
4844
+ onChange: selectServer,
4845
+ title: selectedServer.url ?? t("openapi.server"),
4846
+ buttonContent: /* @__PURE__ */ jsx(ServerIcon, {
4847
+ className: "size-4",
4848
+ "aria-hidden": "true"
4849
+ }),
4850
+ className: "col-start-2 row-start-1 size-8 shrink-0",
4851
+ buttonClassName: "grid size-8 place-items-center rounded-(--clarify-theme-tokens-radius-md) bg-(--clarify-ui-subtle-background) text-(--clarify-ui-text-soft) outline-hidden transition hover:bg-(--clarify-ui-hover-background) hover:text-(--clarify-ui-text-strong) focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-(--clarify-theme-tokens-colors-primary) data-open:bg-(--clarify-ui-active-background)"
4852
+ }) : null,
4853
+ /* @__PURE__ */ jsx("span", {
4854
+ className: "col-start-3 row-start-1 min-w-0 truncate border-l border-(--clarify-theme-tokens-colors-border) pl-2 font-mono text-xs text-(--clarify-theme-tokens-colors-foreground)",
4855
+ title: path || "/",
4856
+ children: path || "/"
4857
+ }),
4858
+ requestExamples.length > 1 ? /* @__PURE__ */ jsxs("div", {
4859
+ className: "col-span-full row-start-2 flex min-w-0 items-center gap-0.5 border-t border-(--clarify-theme-tokens-colors-border) pt-2 lg:col-span-1 lg:col-start-4 lg:row-start-1 lg:border-t-0 lg:pt-0",
4860
+ children: [/* @__PURE__ */ jsx(InlineListbox, {
4861
+ label: t("openapi.requestExample"),
4862
+ value: currentRequestExampleKey,
4863
+ options: requestExamples.map((example) => ({
4864
+ value: example.key,
4865
+ label: example.title,
4866
+ description: example.summary
4867
+ })),
4868
+ onChange: applyRequestExample,
4869
+ className: "min-w-0 flex-1",
4870
+ buttonClassName: "flex h-8 w-full min-w-0 max-w-full items-center gap-1 rounded-(--clarify-theme-tokens-radius-md) px-2 text-xs font-medium text-(--clarify-ui-text-strong) outline-hidden transition hover:bg-(--clarify-ui-hover-background) focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-(--clarify-theme-tokens-colors-primary)"
4871
+ }), /* @__PURE__ */ jsx("button", {
4872
+ type: "button",
4873
+ title: t("openapi.resetToExample"),
4874
+ "aria-label": t("openapi.resetToExample"),
4875
+ onClick: () => applyRequestExample(currentRequestExampleKey),
4876
+ className: "grid size-8 shrink-0 place-items-center rounded-(--clarify-theme-tokens-radius-md) text-(--clarify-ui-text-faint) hover:bg-(--clarify-ui-hover-background) hover:text-(--clarify-ui-text-strong) focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-(--clarify-theme-tokens-colors-primary)",
4877
+ children: /* @__PURE__ */ jsx(RotateCcwIcon, {
4878
+ className: "size-3.5",
4879
+ "aria-hidden": "true"
4880
+ })
4881
+ })]
4882
+ }) : null,
4883
+ /* @__PURE__ */ jsx("div", {
4884
+ className: "col-start-4 row-start-1 lg:col-start-5",
4885
+ children: /* @__PURE__ */ jsx(SendRequestButton, {
4886
+ label: sending ? t("openapi.sendingRequest") : t("openapi.sendRequest"),
4887
+ busy: sending,
4888
+ text: t("openapi.sendRequest"),
4889
+ onClick: sendRequest
4890
+ })
4891
+ }),
4892
+ onClose ? /* @__PURE__ */ jsx("button", {
4893
+ type: "button",
4894
+ onClick: onClose,
4895
+ "aria-label": t("openapi.closeRequest"),
4896
+ title: t("openapi.closeRequest"),
4897
+ className: "col-start-5 row-start-1 grid size-8 shrink-0 place-items-center rounded-(--clarify-theme-tokens-radius-md) text-(--clarify-ui-text-soft) transition hover:bg-(--clarify-ui-hover-background) hover:text-(--clarify-theme-tokens-colors-foreground) focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-(--clarify-theme-tokens-colors-primary) lg:col-start-6",
4898
+ children: /* @__PURE__ */ jsx(XIcon, {
4899
+ className: "size-4",
4900
+ "aria-hidden": "true"
4901
+ })
4902
+ }) : null
4903
+ ]
4904
+ })
4480
4905
  });
4481
4906
  }
4482
4907
  function renderVariables() {
@@ -4516,13 +4941,15 @@ function OpenApiRequestWorkbench(arg0) {
4516
4941
  value: entry.mediaType,
4517
4942
  label: entry.mediaType
4518
4943
  })),
4519
- onChange: selectMediaType
4520
- }) }) : null, /* @__PURE__ */ jsx("textarea", {
4521
- "aria-label": t("openapi.requestBody"),
4522
- value: body,
4523
- onChange: (event) => setBody(event.target.value),
4524
- spellCheck: false,
4525
- className: "block h-full min-h-44 w-full resize-none border-0 bg-(--clarify-code-background) p-3 font-mono text-xs/5 text-(--clarify-code-text) outline-hidden focus:ring-2 focus:ring-inset focus:ring-(--clarify-theme-tokens-colors-primary)"
4944
+ onChange: selectRequestMediaType
4945
+ }) }) : null, /* @__PURE__ */ jsx(OpenApiRequestBodyEditor, {
4946
+ spec,
4947
+ mediaType,
4948
+ content: selectedContent?.value,
4949
+ body,
4950
+ files: bodyFiles,
4951
+ onBodyChange: setBody,
4952
+ onFileChange: setBodyFile
4526
4953
  })]
4527
4954
  });
4528
4955
  }
@@ -4910,6 +5337,7 @@ function OpenApiOperation(arg0) {
4910
5337
  onSelectRequestMediaType: requestState.setSelectedRequestMediaType,
4911
5338
  selectedServer: serverState.selectedServer,
4912
5339
  serverVariables: serverState.serverVariables,
5340
+ authOptions: authState.authOptions,
4913
5341
  auth: authState.authInput,
4914
5342
  sharedExampleKey: linkedExampleKey,
4915
5343
  onSelectExampleKey: setLinkedExampleKey
@@ -4929,4 +5357,4 @@ function OpenApiOperation(arg0) {
4929
5357
  //#endregion
4930
5358
  export { Code as A, GridPattern as C, Tag as D, Heading as E, CardGroup as F, Callout as I, Button as L, Pre as M, Mermaid as N, Feedback as O, Card as P, Prose as S, Logo as T, WebFrame as _, ResponseExamplesPanel as a, Step as b, getAuthOptions as c, getOpenApiOperationEntry as d, listOpenApiOperations as f, primitives_exports as g, Markdown as h, RequestExamplesPanel as i, CodeGroup as j, Collapse as k, getServerKey as l, getRequestBody$1 as m, OpenApiOperation as n, authPlaceholder as o, getMediaTypeEntries as p, OpenApiRequestWorkbench as r, defaultServerVariables as s, EndpointIdentity as t, getServers as u, TabItem as v, HeroPattern as w, Steps as x, Tabs as y };
4931
5359
 
4932
- //# sourceMappingURL=OpenApiOperation-C2vJztWZ.js.map
5360
+ //# sourceMappingURL=OpenApiOperation-Cr8TxLjl.js.map