@clarify-labs/renderer 0.9.1 → 0.9.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 (48) hide show
  1. package/output/{ClarifyShell-291_IXxJ.js → ClarifyShell-BQ29N8P5.js} +223 -161
  2. package/output/ClarifyShell-BQ29N8P5.js.map +1 -0
  3. package/output/{ClarifyShell-DJ4fOVOd.cjs → ClarifyShell-Dm--LZco.cjs} +224 -162
  4. package/output/ClarifyShell-Dm--LZco.cjs.map +1 -0
  5. package/output/{OpenApiOperation-E8lSLsSK.js → OpenApiOperation-C9xyRo5a.js} +597 -292
  6. package/output/OpenApiOperation-C9xyRo5a.js.map +1 -0
  7. package/output/{OpenApiOperation-3DUVruIO.cjs → OpenApiOperation-DIWGdw29.cjs} +595 -290
  8. package/output/OpenApiOperation-DIWGdw29.cjs.map +1 -0
  9. package/output/{PageActions-DaXQgMYP.js → PageActions-B_tSec1f.js} +282 -197
  10. package/output/PageActions-B_tSec1f.js.map +1 -0
  11. package/output/{PageActions-GI1t-JrR.cjs → PageActions-DEuFHgyB.cjs} +280 -201
  12. package/output/PageActions-DEuFHgyB.cjs.map +1 -0
  13. package/output/app/SectionProvider.d.ts +1 -1
  14. package/output/client.cjs +3 -3
  15. package/output/client.js +3 -3
  16. package/output/components/Tabs.d.ts +16 -0
  17. package/output/components/index.d.ts +1 -0
  18. package/output/core/i18n.d.ts +1 -1
  19. package/output/core/types.d.ts +1 -0
  20. package/output/index.cjs +4 -4
  21. package/output/index.js +4 -4
  22. package/output/openapi/components/CodeDisplay.d.ts +25 -0
  23. package/output/openapi/components/EndpointSections.d.ts +6 -0
  24. package/output/openapi/components/ExamplePanels.d.ts +10 -17
  25. package/output/openapi/components/OpenApiOperation.d.ts +6 -0
  26. package/output/openapi/components/OpenApiOperation.state.d.ts +43 -0
  27. package/output/openapi/components/SchemaProperties.d.ts +2 -0
  28. package/output/openapi/components/SelectControl.d.ts +15 -0
  29. package/output/openapi/components/helpers.d.ts +22 -0
  30. package/output/preview.cjs +114 -67
  31. package/output/preview.cjs.map +1 -1
  32. package/output/preview.js +114 -67
  33. package/output/preview.js.map +1 -1
  34. package/output/{render-r9DclX3Y.cjs → render-BCGK1WpS.cjs} +2 -2
  35. package/output/{render-r9DclX3Y.cjs.map → render-BCGK1WpS.cjs.map} +1 -1
  36. package/output/{render-yBo2SUlA.js → render-CEWLJSmt.js} +2 -2
  37. package/output/{render-yBo2SUlA.js.map → render-CEWLJSmt.js.map} +1 -1
  38. package/output/renderer.css +207 -104
  39. package/output/server.cjs +2 -2
  40. package/output/server.js +2 -2
  41. package/output/shell/Header.d.ts +2 -0
  42. package/package.json +1 -1
  43. package/output/ClarifyShell-291_IXxJ.js.map +0 -1
  44. package/output/ClarifyShell-DJ4fOVOd.cjs.map +0 -1
  45. package/output/OpenApiOperation-3DUVruIO.cjs.map +0 -1
  46. package/output/OpenApiOperation-E8lSLsSK.js.map +0 -1
  47. package/output/PageActions-DaXQgMYP.js.map +0 -1
  48. package/output/PageActions-GI1t-JrR.cjs.map +0 -1
@@ -1,12 +1,12 @@
1
- import { D as copyTextToClipboard, M as useConfig, N as useLocale, O as useBuiltInText, T as localizeHref, c as remToPx, g as useTheme, l as lucideIconRegistry, n as PageTitleActions, s as useSectionStore, u as resolveLucideIconName, w as isExternalHref } from "./PageActions-DaXQgMYP.js";
1
+ import { C as isExternalHref, D as useBuiltInText, E as copyTextToClipboard, M as useLocale, c as lucideIconRegistry, h as useTheme, j as useConfig, l as resolveLucideIconName, n as PageTitleActions, o as useSectionStore, s as remToPx, w as localizeHref } from "./PageActions-B_tSec1f.js";
2
2
  import { t as markdownRemarkPlugins } from "./remark-Dd2WU50s.js";
3
3
  import clsx from "clsx";
4
4
  import { Children, createContext, createElement, forwardRef, isValidElement, useContext, useEffect, useId, useLayoutEffect, useRef, useState } from "react";
5
5
  import { Link } from "react-router-dom";
6
6
  import { Listbox, ListboxButton, ListboxOption, ListboxOptions, Tab, TabGroup, TabList, TabPanel, TabPanels, Transition } from "@headlessui/react";
7
- import { AlertTriangle, ArrowRight, Check, CheckCircle2, CheckIcon, ChevronDown, ChevronDownIcon, ChevronRight, ChevronsUpDownIcon, CircleCheck, Clipboard, ClipboardIcon, CodeIcon, Info, Lightbulb, LinkIcon, LockKeyholeIcon, Maximize2, PackageIcon, ServerIcon, UnlockKeyholeIcon, XCircle, ZoomIn, ZoomOut } from "lucide-react";
7
+ import { AlertTriangle, ArrowRight, Check, CheckCircle2, CheckIcon, ChevronDown, ChevronDownIcon, ChevronRight, ChevronsUpDownIcon, CircleCheck, Clipboard, ClipboardIcon, CodeIcon, CopyIcon, Info, Lightbulb, LinkIcon, LockKeyholeIcon, Maximize2, PackageIcon, ServerIcon, UnlockKeyholeIcon, XCircle, ZoomIn, ZoomOut } from "lucide-react";
8
8
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
- import { useInView } from "framer-motion";
9
+ import { motion, useInView } from "framer-motion";
10
10
  import { create } from "zustand";
11
11
  import { TransformComponent, TransformWrapper, useControls } from "react-zoom-pan-pinch";
12
12
  import ReactMarkdown from "react-markdown";
@@ -915,6 +915,44 @@ function Prose(arg0) {
915
915
  });
916
916
  }
917
917
  //#endregion
918
+ //#region source/components/Tabs.tsx
919
+ function Tabs(arg0) {
920
+ const { items, selectedIndex, onChange, className, listClassName, panelsClassName } = arg0;
921
+ const [internalIndex, setInternalIndex] = useState(0);
922
+ const resolvedIndex = typeof selectedIndex === "number" ? selectedIndex : internalIndex;
923
+ const indicatorLayoutId = useId();
924
+ const handleChange = (index) => {
925
+ if (typeof selectedIndex !== "number") setInternalIndex(index);
926
+ onChange?.(index);
927
+ };
928
+ return /* @__PURE__ */ jsxs(TabGroup, {
929
+ selectedIndex: resolvedIndex,
930
+ onChange: handleChange,
931
+ className,
932
+ children: [/* @__PURE__ */ jsx(TabList, {
933
+ className: clsx("flex flex-wrap items-center gap-6 border-b border-(--clarify-theme-tokens-colors-border) pb-0", listClassName),
934
+ children: items.map((item) => /* @__PURE__ */ jsx(Tab, {
935
+ className: ({ selected }) => clsx("clarify-ui-tab relative inline-flex h-10 shrink-0 items-center px-0 py-0 text-sm font-medium transition focus:outline-none", selected && "clarify-ui-tab-active"),
936
+ children: ({ selected }) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", { children: item.label }), selected ? /* @__PURE__ */ jsx(motion.span, {
937
+ layoutId: indicatorLayoutId,
938
+ className: "absolute inset-x-0 bottom-0 h-0.5 rounded-full bg-(--clarify-theme-tokens-colors-foreground)",
939
+ transition: {
940
+ type: "tween",
941
+ duration: .16,
942
+ ease: "easeOut"
943
+ }
944
+ }) : null] })
945
+ }, item.id))
946
+ }), /* @__PURE__ */ jsx(TabPanels, {
947
+ className: clsx("mt-4", panelsClassName),
948
+ children: items.map((item) => /* @__PURE__ */ jsx(TabPanel, {
949
+ className: "focus:outline-none",
950
+ children: item.panel
951
+ }, item.id))
952
+ })]
953
+ });
954
+ }
955
+ //#endregion
918
956
  //#region source/components/WebFrame.tsx
919
957
  function WebFrame(arg0) {
920
958
  const { src, title = "Embedded content", children, showWindow = true, className, iframeClassName, height = 420, style, ...props } = arg0;
@@ -1734,7 +1772,7 @@ function buildRequestCodeExamples(input) {
1734
1772
  }));
1735
1773
  }
1736
1774
  //#endregion
1737
- //#region source/openapi/components/ExamplePanels.tsx
1775
+ //#region source/openapi/components/SelectControl.tsx
1738
1776
  function SelectControl(arg0) {
1739
1777
  const { label, value, options, onChange, icon, compact = false } = arg0;
1740
1778
  const normalizedOptions = options.map((option) => typeof option === "string" ? {
@@ -1781,69 +1819,8 @@ function SelectControl(arg0) {
1781
1819
  })
1782
1820
  });
1783
1821
  }
1784
- function getExampleLabel(example, t) {
1785
- return example.generated && example.title === "schema" ? t("openapi.schemaExample") : example.title;
1786
- }
1787
- function getLanguageOptions(codeOptions) {
1788
- const languages = /* @__PURE__ */ new Map();
1789
- for (const option of codeOptions ?? []) languages.set(option.languageKey, option.title);
1790
- return Array.from(languages, ([value, label]) => ({
1791
- value,
1792
- label
1793
- }));
1794
- }
1795
- function getClientOptions(codeOptions, languageKey) {
1796
- return (codeOptions ?? []).filter((option) => option.languageKey === languageKey).map((option) => ({
1797
- value: option.clientKey,
1798
- label: option.clientTitle
1799
- }));
1800
- }
1801
- function getServers(spec, operation, path) {
1802
- const operationServers = operation.servers;
1803
- const pathServers = path ? getPathItem(spec, path)?.servers : void 0;
1804
- const servers = Array.isArray(operationServers) ? operationServers : Array.isArray(pathServers) ? pathServers : spec.servers;
1805
- if (!Array.isArray(servers)) return [{ url: "https://api.example.com" }];
1806
- const validServers = servers.filter((server) => isRecord(server) && typeof server.url === "string");
1807
- return validServers.length > 0 ? validServers : [{ url: "https://api.example.com" }];
1808
- }
1809
- function getServerKey(server, index) {
1810
- return `${index}:${server.url ?? ""}`;
1811
- }
1812
- function getServerLabel(server, index) {
1813
- return server.url ?? `Server ${index + 1}`;
1814
- }
1815
- function defaultServerVariables(server) {
1816
- return Object.fromEntries(Object.entries(server?.variables ?? {}).map(([name, variable]) => [name, variable.default ?? variable.enum?.[0] ?? ""]));
1817
- }
1818
- function getSecuritySchemes(spec) {
1819
- const schemes = spec.components;
1820
- if (!isRecord(schemes) || !isRecord(schemes.securitySchemes)) return {};
1821
- return Object.fromEntries(Object.entries(schemes.securitySchemes).filter((entry) => isRecord(entry[1])));
1822
- }
1823
- function getSecurityRequirements(spec, operation) {
1824
- const operationSecurity = operation.security;
1825
- if (Array.isArray(operationSecurity)) return operationSecurity.filter(isRecord);
1826
- const specSecurity = spec.security;
1827
- return Array.isArray(specSecurity) ? specSecurity.filter(isRecord) : [];
1828
- }
1829
- function getAuthOptions(spec, operation) {
1830
- const schemes = getSecuritySchemes(spec);
1831
- const requirements = getSecurityRequirements(spec, operation);
1832
- const names = new Set(requirements.flatMap((requirement) => Object.keys(requirement)));
1833
- return Array.from(names).map((name) => ({
1834
- name,
1835
- scheme: schemes[name]
1836
- })).filter((option) => Boolean(option.scheme));
1837
- }
1838
- function authPlaceholder(auth) {
1839
- if (!auth) return "";
1840
- if (auth.scheme.type === "apiKey") return "{api_key}";
1841
- if (auth.scheme.type === "http" && auth.scheme.scheme?.toLowerCase() === "basic") return "{base64_credentials}";
1842
- return "{token}";
1843
- }
1844
- function authLabel(name, scheme) {
1845
- return `${name}${scheme.type === "apiKey" && scheme.in && scheme.name ? ` · ${scheme.in}: ${scheme.name}` : ""}`;
1846
- }
1822
+ //#endregion
1823
+ //#region source/openapi/components/CodeDisplay.tsx
1847
1824
  function CopyCodeButton(arg0) {
1848
1825
  const { code } = arg0;
1849
1826
  const t = useBuiltInText();
@@ -1909,6 +1886,73 @@ function CodeToolbar(arg0) {
1909
1886
  }), /* @__PURE__ */ jsx(CopyCodeButton, { code })]
1910
1887
  });
1911
1888
  }
1889
+ //#endregion
1890
+ //#region source/openapi/components/helpers.ts
1891
+ function getServers(spec, operation, path) {
1892
+ const operationServers = operation.servers;
1893
+ const pathServers = path ? getPathItem(spec, path)?.servers : void 0;
1894
+ const servers = Array.isArray(operationServers) ? operationServers : Array.isArray(pathServers) ? pathServers : spec.servers;
1895
+ if (!Array.isArray(servers)) return [{ url: "https://api.example.com" }];
1896
+ const validServers = servers.filter((server) => isRecord(server) && typeof server.url === "string");
1897
+ return validServers.length > 0 ? validServers : [{ url: "https://api.example.com" }];
1898
+ }
1899
+ function getServerKey(server, index) {
1900
+ return `${index}:${server.url ?? ""}`;
1901
+ }
1902
+ function getServerLabel(server, index) {
1903
+ return server.url ?? `Server ${index + 1}`;
1904
+ }
1905
+ function defaultServerVariables(server) {
1906
+ return Object.fromEntries(Object.entries(server?.variables ?? {}).map(([name, variable]) => [name, variable.default ?? variable.enum?.[0] ?? ""]));
1907
+ }
1908
+ function getSecuritySchemes(spec) {
1909
+ const schemes = spec.components;
1910
+ if (!isRecord(schemes) || !isRecord(schemes.securitySchemes)) return {};
1911
+ return Object.fromEntries(Object.entries(schemes.securitySchemes).filter((entry) => isRecord(entry[1])));
1912
+ }
1913
+ function getSecurityRequirements(spec, operation) {
1914
+ const operationSecurity = operation.security;
1915
+ if (Array.isArray(operationSecurity)) return operationSecurity.filter(isRecord);
1916
+ const specSecurity = spec.security;
1917
+ return Array.isArray(specSecurity) ? specSecurity.filter(isRecord) : [];
1918
+ }
1919
+ function getAuthOptions(spec, operation) {
1920
+ const schemes = getSecuritySchemes(spec);
1921
+ const requirements = getSecurityRequirements(spec, operation);
1922
+ const names = new Set(requirements.flatMap((requirement) => Object.keys(requirement)));
1923
+ return Array.from(names).map((name) => ({
1924
+ name,
1925
+ scheme: schemes[name]
1926
+ })).filter((option) => Boolean(option.scheme));
1927
+ }
1928
+ function authPlaceholder(auth) {
1929
+ if (!auth) return "";
1930
+ if (auth.scheme.type === "apiKey") return "{api_key}";
1931
+ if (auth.scheme.type === "http" && auth.scheme.scheme?.toLowerCase() === "basic") return "{base64_credentials}";
1932
+ return "{token}";
1933
+ }
1934
+ function authLabel(name, scheme) {
1935
+ return `${name}${scheme.type === "apiKey" && scheme.in && scheme.name ? ` · ${scheme.in}: ${scheme.name}` : ""}`;
1936
+ }
1937
+ function getExampleLabel(example, t) {
1938
+ return example.generated && example.title === "schema" ? t("openapi.schemaExample") : example.title;
1939
+ }
1940
+ function getLanguageOptions(codeOptions) {
1941
+ const languages = /* @__PURE__ */ new Map();
1942
+ for (const option of codeOptions ?? []) languages.set(option.languageKey, option.title);
1943
+ return Array.from(languages, ([value, label]) => ({
1944
+ value,
1945
+ label
1946
+ }));
1947
+ }
1948
+ function getClientOptions(codeOptions, languageKey) {
1949
+ return (codeOptions ?? []).filter((option) => option.languageKey === languageKey).map((option) => ({
1950
+ value: option.clientKey,
1951
+ label: option.clientTitle
1952
+ }));
1953
+ }
1954
+ //#endregion
1955
+ //#region source/openapi/components/ExamplePanels.tsx
1912
1956
  function ApiExampleCodeGroup(arg0) {
1913
1957
  const { title, tag, tagOptions, onSelectTag, label, labelOptions, onSelectLabel, comfortableMeta = false, code, language, mediaTypes, selectedMediaType, onSelectMediaType, examples, selectedExampleKey, onSelectExample, languageOptions, selectedLanguageKey, onSelectLanguage, clientOptions, selectedClientKey, onSelectClient } = arg0;
1914
1958
  const t = useBuiltInText();
@@ -1985,15 +2029,18 @@ function ApiExampleCodeGroup(arg0) {
1985
2029
  })
1986
2030
  });
1987
2031
  }
1988
- function RequestExamplesPanel(arg0) {
1989
- const { spec, path, method, parameters, requestContents, selectedMediaType, onSelectMediaType, selectedServer, serverVariables, auth } = arg0;
1990
- const t = useBuiltInText();
2032
+ function firstExampleKeyForMediaType(requestContents, mediaType) {
2033
+ return getExampleEntries(requestContents.find((content) => content.mediaType === mediaType)?.value)[0]?.key ?? "";
2034
+ }
2035
+ function useRequestExamplesState(arg0) {
2036
+ const { spec, path, method, parameters, requestContents, selectedMediaType, onSelectMediaType, selectedServer, serverVariables, auth, sharedExampleKey, onSelectExampleKey } = arg0;
1991
2037
  const selectedContent = requestContents.find((content) => content.mediaType === selectedMediaType) ?? requestContents[0];
1992
2038
  const examples = getExampleEntries(selectedContent?.value);
1993
2039
  const [selectedExampleKey, setSelectedExampleKey] = useState(examples[0]?.key ?? "");
1994
2040
  const [selectedLanguageKey, setSelectedLanguageKey] = useState("shell");
1995
2041
  const [selectedClientKey, setSelectedClientKey] = useState("curl");
1996
- const selectedExample = examples.find((example) => example.key === selectedExampleKey) ?? examples[0];
2042
+ const currentExampleKey = (sharedExampleKey && examples.some((example) => example.key === sharedExampleKey) ? sharedExampleKey : void 0) ?? selectedExampleKey;
2043
+ const selectedExample = examples.find((example) => example.key === currentExampleKey) ?? examples[0];
1997
2044
  const codeOptions = buildRequestCodeExamples({
1998
2045
  spec,
1999
2046
  path,
@@ -2013,71 +2060,159 @@ function RequestExamplesPanel(arg0) {
2013
2060
  });
2014
2061
  const selectedLanguage = codeOptions.find((option) => option.languageKey === selectedLanguageKey) ?? codeOptions[0];
2015
2062
  const selectedCode = codeOptions.find((option) => option.languageKey === selectedLanguage.languageKey && option.clientKey === selectedClientKey) ?? selectedLanguage;
2016
- const languageOptions = getLanguageOptions(codeOptions);
2017
- const clientOptions = getClientOptions(codeOptions, selectedCode.languageKey);
2018
- return /* @__PURE__ */ jsx(ApiExampleCodeGroup, {
2019
- title: t("openapi.request"),
2020
- tag: method,
2021
- label: path,
2022
- code: selectedCode.code,
2023
- language: selectedCode.language,
2024
- mediaTypes: requestContents.map((content) => content.mediaType),
2025
- selectedMediaType: selectedContent?.mediaType,
2063
+ return {
2064
+ selectedContent,
2065
+ selectedExample,
2066
+ selectedCode,
2067
+ languageOptions: getLanguageOptions(codeOptions),
2068
+ clientOptions: getClientOptions(codeOptions, selectedCode.languageKey),
2069
+ examples,
2026
2070
  onSelectMediaType: (value) => {
2027
2071
  onSelectMediaType(value);
2028
- setSelectedExampleKey(getExampleEntries(requestContents.find((content) => content.mediaType === value)?.value)[0]?.key ?? "");
2072
+ setSelectedExampleKey(firstExampleKeyForMediaType(requestContents, value));
2073
+ },
2074
+ onSelectExample: (value) => {
2075
+ setSelectedExampleKey(value);
2076
+ onSelectExampleKey?.(value);
2029
2077
  },
2030
- examples,
2031
- selectedExampleKey: selectedExample?.key,
2032
- onSelectExample: setSelectedExampleKey,
2033
- languageOptions,
2034
- selectedLanguageKey: selectedCode.languageKey,
2035
2078
  onSelectLanguage: (value) => {
2036
2079
  const nextCode = codeOptions.find((option) => option.languageKey === value);
2037
2080
  setSelectedLanguageKey(nextCode?.languageKey ?? value);
2038
2081
  setSelectedClientKey(nextCode?.clientKey ?? "");
2039
2082
  },
2040
- clientOptions,
2041
- selectedClientKey: selectedCode.clientKey,
2042
2083
  onSelectClient: setSelectedClientKey
2043
- });
2084
+ };
2044
2085
  }
2045
- function ResponseExamplesPanel(arg0) {
2046
- const { operation, spec } = arg0;
2086
+ function RequestExamplesPanel(arg0) {
2087
+ const { spec, path, method, parameters, requestContents, selectedMediaType, onSelectMediaType, selectedServer, serverVariables, auth, sharedExampleKey, onSelectExampleKey } = arg0;
2047
2088
  const t = useBuiltInText();
2048
- const responses = getResponseEntries(operation, spec).filter(({ response }) => getMediaTypeEntries(response.content, spec).length > 0);
2049
- const [selectedStatus, setSelectedStatus] = useState(responses.find(({ status }) => status.startsWith("2"))?.status ?? responses[0]?.status ?? "");
2050
- const selectedResponse = responses.find(({ status }) => status === selectedStatus) ?? responses[0];
2089
+ const state = useRequestExamplesState({
2090
+ spec,
2091
+ path,
2092
+ method,
2093
+ parameters,
2094
+ requestContents,
2095
+ selectedMediaType,
2096
+ onSelectMediaType,
2097
+ selectedServer,
2098
+ serverVariables,
2099
+ auth,
2100
+ sharedExampleKey,
2101
+ onSelectExampleKey
2102
+ });
2103
+ return /* @__PURE__ */ jsx(ApiExampleCodeGroup, {
2104
+ title: t("openapi.request"),
2105
+ tag: method,
2106
+ label: path,
2107
+ code: state.selectedCode.code,
2108
+ language: state.selectedCode.language,
2109
+ mediaTypes: requestContents.map((content) => content.mediaType),
2110
+ selectedMediaType: state.selectedContent?.mediaType,
2111
+ onSelectMediaType: state.onSelectMediaType,
2112
+ examples: state.examples,
2113
+ selectedExampleKey: state.selectedExample?.key,
2114
+ onSelectExample: state.onSelectExample,
2115
+ languageOptions: state.languageOptions,
2116
+ selectedLanguageKey: state.selectedCode.languageKey,
2117
+ onSelectLanguage: state.onSelectLanguage,
2118
+ clientOptions: state.clientOptions,
2119
+ selectedClientKey: state.selectedCode.clientKey,
2120
+ onSelectClient: state.onSelectClient
2121
+ });
2122
+ }
2123
+ function firstExampleKeyForResponseContent(content) {
2124
+ return getExampleEntries(content?.value)[0]?.key ?? "";
2125
+ }
2126
+ function useResponseExamplesState(arg0) {
2127
+ const { operation, spec, sharedExampleKey, onSelectExampleKey, selectedStatus, onSelectStatus } = arg0;
2128
+ const orderedResponses = [...getResponseEntries(operation, spec).filter(({ response }) => getMediaTypeEntries(response.content, spec).length > 0)].sort((left, right) => {
2129
+ if (left.status === "default") return -1;
2130
+ if (right.status === "default") return 1;
2131
+ const leftCode = Number(left.status);
2132
+ const rightCode = Number(right.status);
2133
+ if (!Number.isNaN(leftCode) && !Number.isNaN(rightCode)) return leftCode - rightCode;
2134
+ return left.status.localeCompare(right.status);
2135
+ });
2136
+ const [internalSelectedStatus, setInternalSelectedStatus] = useState(orderedResponses.find(({ status }) => status === "default")?.status ?? orderedResponses.find(({ status }) => status.startsWith("2"))?.status ?? orderedResponses[0]?.status ?? "");
2137
+ const activeStatus = selectedStatus ?? internalSelectedStatus;
2138
+ const selectedResponse = orderedResponses.find(({ status }) => status === activeStatus) ?? orderedResponses[0];
2051
2139
  const responseContents = getMediaTypeEntries(selectedResponse?.response.content, spec);
2052
- const [selectedMediaType, setSelectedMediaType] = useState(responseContents[0]?.mediaType ?? "");
2053
- const selectedContent = responseContents.find((content) => content.mediaType === selectedMediaType) ?? responseContents[0];
2140
+ const [selection, setSelection] = useState(() => ({
2141
+ status: activeStatus,
2142
+ mediaType: responseContents[0]?.mediaType ?? "",
2143
+ exampleKey: firstExampleKeyForResponseContent(responseContents[0])
2144
+ }));
2145
+ const resolvedSelection = selection.status === activeStatus ? selection : {
2146
+ status: activeStatus,
2147
+ mediaType: responseContents[0]?.mediaType ?? "",
2148
+ exampleKey: firstExampleKeyForResponseContent(responseContents[0])
2149
+ };
2150
+ const selectedContent = responseContents.find((content) => content.mediaType === resolvedSelection.mediaType) ?? responseContents[0];
2054
2151
  const examples = getExampleEntries(selectedContent?.value);
2055
- const [selectedExampleKey, setSelectedExampleKey] = useState(examples[0]?.key ?? "");
2056
- const selectedExample = examples.find((example) => example.key === selectedExampleKey) ?? examples[0];
2057
- const responseCode = stringifyExample(selectedExample?.value);
2058
- if (!selectedResponse || !selectedContent || !responseCode) return null;
2059
- return /* @__PURE__ */ jsx(ApiExampleCodeGroup, {
2060
- title: t("openapi.response"),
2061
- tag: selectedResponse.status,
2062
- tagOptions: responses.map(({ status }) => status),
2063
- onSelectTag: (value) => {
2064
- const nextContents = getMediaTypeEntries(responses.find(({ status }) => status === value)?.response.content, spec);
2065
- setSelectedStatus(value);
2066
- setSelectedMediaType(nextContents[0]?.mediaType ?? "");
2067
- setSelectedExampleKey(getExampleEntries(nextContents[0]?.value)[0]?.key ?? "");
2152
+ const selectedExampleKey = examples.some((example) => example.key === resolvedSelection.exampleKey) ? resolvedSelection.exampleKey : examples[0]?.key ?? "";
2153
+ const currentExampleKey = (sharedExampleKey && examples.some((example) => example.key === sharedExampleKey) ? sharedExampleKey : void 0) ?? selectedExampleKey;
2154
+ const selectedExample = examples.find((example) => example.key === currentExampleKey) ?? examples[0];
2155
+ return {
2156
+ responses: orderedResponses,
2157
+ selectedResponse,
2158
+ responseContents,
2159
+ selectedContent,
2160
+ examples,
2161
+ selectedExample,
2162
+ responseCode: stringifyExample(selectedExample?.value),
2163
+ onSelectStatus: (value) => {
2164
+ const nextContents = getMediaTypeEntries(orderedResponses.find(({ status }) => status === value)?.response.content, spec);
2165
+ if (typeof selectedStatus === "undefined") setInternalSelectedStatus(value);
2166
+ onSelectStatus?.(value);
2167
+ setSelection({
2168
+ status: value,
2169
+ mediaType: nextContents[0]?.mediaType ?? "",
2170
+ exampleKey: firstExampleKeyForResponseContent(nextContents[0])
2171
+ });
2068
2172
  },
2069
- label: selectedContent.mediaType,
2070
- labelOptions: responseContents.map((content) => content.mediaType),
2071
- onSelectLabel: (value) => {
2072
- setSelectedMediaType(value);
2073
- setSelectedExampleKey(getExampleEntries(responseContents.find((content) => content.mediaType === value)?.value)[0]?.key ?? "");
2173
+ onSelectMediaType: (value) => {
2174
+ const nextContent = responseContents.find((content) => content.mediaType === value);
2175
+ setSelection((current) => ({
2176
+ ...current,
2177
+ mediaType: value,
2178
+ exampleKey: firstExampleKeyForResponseContent(nextContent)
2179
+ }));
2074
2180
  },
2181
+ onSelectExample: (value) => {
2182
+ setSelection((current) => ({
2183
+ ...current,
2184
+ exampleKey: value
2185
+ }));
2186
+ onSelectExampleKey?.(value);
2187
+ }
2188
+ };
2189
+ }
2190
+ function ResponseExamplesPanel(arg0) {
2191
+ const { operation, spec, sharedExampleKey, onSelectExampleKey, selectedStatus, onSelectStatus } = arg0;
2192
+ const t = useBuiltInText();
2193
+ const state = useResponseExamplesState({
2194
+ operation,
2195
+ spec,
2196
+ sharedExampleKey,
2197
+ onSelectExampleKey,
2198
+ selectedStatus,
2199
+ onSelectStatus
2200
+ });
2201
+ if (!state.selectedResponse || !state.selectedContent || !state.responseCode) return null;
2202
+ return /* @__PURE__ */ jsx(ApiExampleCodeGroup, {
2203
+ title: t("openapi.response"),
2204
+ tag: state.selectedResponse.status,
2205
+ tagOptions: state.responses.map(({ status }) => status),
2206
+ onSelectTag: state.onSelectStatus,
2207
+ label: state.selectedContent.mediaType,
2208
+ labelOptions: state.responseContents.map((content) => content.mediaType),
2209
+ onSelectLabel: state.onSelectMediaType,
2075
2210
  comfortableMeta: true,
2076
- code: responseCode,
2077
- language: codeLanguageForMediaType(selectedContent.mediaType),
2078
- examples,
2079
- selectedExampleKey: selectedExample?.key,
2080
- onSelectExample: setSelectedExampleKey
2211
+ code: state.responseCode,
2212
+ language: codeLanguageForMediaType(state.selectedContent.mediaType),
2213
+ examples: state.examples,
2214
+ selectedExampleKey: state.selectedExample?.key,
2215
+ onSelectExample: state.onSelectExample
2081
2216
  });
2082
2217
  }
2083
2218
  //#endregion
@@ -2311,111 +2446,292 @@ function SchemaProperties(arg0) {
2311
2446
  function ParameterList(arg0) {
2312
2447
  const { title, parameters } = arg0;
2313
2448
  const t = useBuiltInText();
2314
- if (parameters.length === 0) return null;
2315
- return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", { children: title }), /* @__PURE__ */ jsx(Properties, { children: parameters.map((parameter) => /* @__PURE__ */ jsx(Property, {
2449
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", { children: title }), /* @__PURE__ */ jsx(Properties, { children: parameters.length > 0 ? parameters.map((parameter) => /* @__PURE__ */ jsx(Property, {
2316
2450
  name: parameter.name ?? t("openapi.parameter"),
2317
2451
  type: [schemaToType(parameter.schema), parameter.required ? t("openapi.requiredBadge") : void 0].filter(Boolean).join(", ") || void 0,
2318
2452
  children: parameter.description ? /* @__PURE__ */ jsx(Markdown, {
2319
2453
  className: "*:first:mt-0 *:last:mb-0",
2320
2454
  children: parameter.description
2321
2455
  }) : t("openapi.operationParameter")
2322
- }, `${parameter.in}-${parameter.name}`)) })] });
2456
+ }, `${parameter.in}-${parameter.name}`)) : /* @__PURE__ */ jsx("span", {
2457
+ className: "text-sm/5 text-(--clarify-ui-text-soft)",
2458
+ children: t("openapi.none")
2459
+ }) })] });
2323
2460
  }
2324
2461
  function ResponseList(arg0) {
2325
- const { operation, spec } = arg0;
2462
+ const { operation, spec, selectedStatus, onSelectStatus } = arg0;
2326
2463
  const t = useBuiltInText();
2327
- const responses = getResponseEntries(operation, spec);
2328
- if (responses.length === 0) return null;
2329
- return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", { children: t("openapi.responses") }), /* @__PURE__ */ jsx(Properties, { children: responses.map(({ status, response }) => {
2330
- return /* @__PURE__ */ jsx(Property, {
2331
- name: status,
2332
- type: schemaToType(getJsonLikeContent(response.content, spec)?.value.schema),
2333
- children: response.description ? /* @__PURE__ */ jsx(Markdown, {
2334
- className: "*:first:mt-0 *:last:mb-0",
2335
- children: response.description
2336
- }) : `${t("openapi.response")}.`
2337
- }, status);
2338
- }) })] });
2464
+ const orderedResponses = [...getResponseEntries(operation, spec)].sort((left, right) => {
2465
+ if (left.status === "default") return -1;
2466
+ if (right.status === "default") return 1;
2467
+ const leftCode = Number(left.status);
2468
+ const rightCode = Number(right.status);
2469
+ if (!Number.isNaN(leftCode) && !Number.isNaN(rightCode)) return leftCode - rightCode;
2470
+ return left.status.localeCompare(right.status);
2471
+ });
2472
+ const activeStatus = selectedStatus ?? orderedResponses.find(({ status }) => status === "default")?.status ?? orderedResponses.find(({ status }) => status.startsWith("2"))?.status ?? orderedResponses[0]?.status ?? "";
2473
+ const selectedIndex = Math.max(0, orderedResponses.findIndex(({ status }) => status === activeStatus));
2474
+ if (orderedResponses.length === 0) return null;
2475
+ const renderResponsePanel = ({ status, response }) => {
2476
+ const responseSchema = getJsonLikeContent(response.content, spec)?.value.schema;
2477
+ const type = schemaToType(responseSchema);
2478
+ return /* @__PURE__ */ jsxs("div", {
2479
+ className: "rounded-(--clarify-theme-tokens-radius-xl) p-0",
2480
+ children: [
2481
+ /* @__PURE__ */ jsxs("div", {
2482
+ className: "flex flex-wrap items-center gap-2",
2483
+ children: [/* @__PURE__ */ jsx("span", {
2484
+ className: "text-sm/5 font-semibold text-(--clarify-theme-tokens-colors-foreground)",
2485
+ children: status
2486
+ }), type ? /* @__PURE__ */ jsx("span", {
2487
+ className: "text-xs text-(--clarify-theme-tokens-colors-muted)",
2488
+ children: type
2489
+ }) : null]
2490
+ }),
2491
+ /* @__PURE__ */ jsx("div", {
2492
+ className: "mt-3 text-sm/6 text-(--clarify-ui-text-soft) *:first:mt-0 *:last:mb-0",
2493
+ children: response.description ? /* @__PURE__ */ jsx(Markdown, {
2494
+ className: "*:first:mt-0 *:last:mb-0",
2495
+ children: response.description
2496
+ }) : `${t("openapi.response")}.`
2497
+ }),
2498
+ responseSchema && spec ? /* @__PURE__ */ jsx("div", {
2499
+ className: "mt-4",
2500
+ children: /* @__PURE__ */ jsx(SchemaProperties, {
2501
+ title: t("openapi.responseBodyProperties"),
2502
+ schema: responseSchema,
2503
+ spec
2504
+ })
2505
+ }) : null
2506
+ ]
2507
+ });
2508
+ };
2509
+ if (orderedResponses.length === 1) {
2510
+ const [{ status, response }] = orderedResponses;
2511
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", { children: t("openapi.responses") }), renderResponsePanel({
2512
+ status,
2513
+ response
2514
+ })] });
2515
+ }
2516
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", { children: t("openapi.responses") }), /* @__PURE__ */ jsx(Tabs, {
2517
+ selectedIndex,
2518
+ onChange: (index) => {
2519
+ onSelectStatus?.(orderedResponses[index]?.status ?? "");
2520
+ },
2521
+ items: orderedResponses.map(({ status, response }) => ({
2522
+ id: status,
2523
+ label: status,
2524
+ panel: renderResponsePanel({
2525
+ status,
2526
+ response
2527
+ })
2528
+ })),
2529
+ panelsClassName: "mt-4"
2530
+ })] });
2339
2531
  }
2340
2532
  //#endregion
2341
2533
  //#region source/openapi/components/EndpointSections.tsx
2342
2534
  function EndpointRequest(arg0) {
2343
- const { spec, path, method, description, groupedParameters, parameters, requestBody, requestContents, requestSchema, selectedRequestMediaType, onSelectRequestMediaType, selectedServer, serverVariables, auth } = arg0;
2535
+ const { spec, path, method, description, groupedParameters, parameters, requestBody, requestContents, requestSchema, selectedRequestMediaType, onSelectRequestMediaType, selectedServer, serverVariables, auth, sharedExampleKey, onSelectExampleKey } = arg0;
2344
2536
  const t = useBuiltInText();
2345
- return /* @__PURE__ */ jsxs(Row, {
2537
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [description ? /* @__PURE__ */ jsx(Markdown, { children: description }) : null, /* @__PURE__ */ jsxs(Row, {
2346
2538
  className: "relative mt-6",
2347
- children: [/* @__PURE__ */ jsxs(Col, { children: [
2348
- description ? /* @__PURE__ */ jsx(Markdown, { children: description }) : null,
2349
- /* @__PURE__ */ jsx(ParameterList, {
2350
- title: t("openapi.pathParameters"),
2351
- parameters: groupedParameters.path
2352
- }),
2353
- /* @__PURE__ */ jsx(ParameterList, {
2354
- title: t("openapi.queryParameters"),
2355
- parameters: groupedParameters.query
2356
- }),
2357
- /* @__PURE__ */ jsx(ParameterList, {
2358
- title: t("openapi.headers"),
2359
- parameters: groupedParameters.header
2360
- }),
2361
- requestBody && requestContents.length > 0 ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
2362
- /* @__PURE__ */ jsx("h3", { children: t("openapi.requestBody") }),
2363
- typeof requestBody.description === "string" ? /* @__PURE__ */ jsx(Markdown, { children: requestBody.description }) : null,
2364
- /* @__PURE__ */ jsx(SchemaProperties, {
2365
- title: t("openapi.bodyProperties"),
2366
- schema: requestSchema,
2367
- spec
2368
- })
2369
- ] }) : null
2370
- ] }), /* @__PURE__ */ jsx(Col, {
2539
+ children: [/* @__PURE__ */ jsx(Col, { children: /* @__PURE__ */ jsxs("div", {
2540
+ className: "w-full",
2541
+ children: [
2542
+ /* @__PURE__ */ jsx(ParameterList, {
2543
+ title: t("openapi.pathParameters"),
2544
+ parameters: groupedParameters.path
2545
+ }),
2546
+ /* @__PURE__ */ jsx(ParameterList, {
2547
+ title: t("openapi.queryParameters"),
2548
+ parameters: groupedParameters.query
2549
+ }),
2550
+ /* @__PURE__ */ jsx(ParameterList, {
2551
+ title: t("openapi.headers"),
2552
+ parameters: groupedParameters.header
2553
+ }),
2554
+ requestBody && requestContents.length > 0 ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
2555
+ /* @__PURE__ */ jsx("h3", { children: t("openapi.requestBody") }),
2556
+ typeof requestBody.description === "string" ? /* @__PURE__ */ jsx(Markdown, { children: requestBody.description }) : null,
2557
+ /* @__PURE__ */ jsx(SchemaProperties, {
2558
+ title: t("openapi.bodyProperties"),
2559
+ schema: requestSchema,
2560
+ spec
2561
+ })
2562
+ ] }) : null
2563
+ ]
2564
+ }) }), /* @__PURE__ */ jsx(Col, {
2371
2565
  sticky: true,
2372
- children: /* @__PURE__ */ jsx(RequestExamplesPanel, {
2373
- spec,
2374
- path,
2375
- method,
2376
- parameters,
2377
- requestContents,
2378
- selectedMediaType: selectedRequestMediaType,
2379
- onSelectMediaType: onSelectRequestMediaType,
2380
- selectedServer,
2381
- serverVariables,
2382
- auth
2566
+ children: /* @__PURE__ */ jsx("div", {
2567
+ className: "w-full",
2568
+ children: /* @__PURE__ */ jsx(RequestExamplesPanel, {
2569
+ spec,
2570
+ path,
2571
+ method,
2572
+ parameters,
2573
+ requestContents,
2574
+ selectedMediaType: selectedRequestMediaType,
2575
+ onSelectMediaType: onSelectRequestMediaType,
2576
+ selectedServer,
2577
+ serverVariables,
2578
+ auth,
2579
+ sharedExampleKey,
2580
+ onSelectExampleKey
2581
+ })
2383
2582
  })
2384
2583
  })]
2385
- });
2584
+ })] });
2386
2585
  }
2387
2586
  function EndpointResponse(arg0) {
2388
- const { spec, operation } = arg0;
2389
- return /* @__PURE__ */ jsxs(Row, {
2390
- className: "relative mt-6",
2391
- children: [/* @__PURE__ */ jsx(Col, { children: /* @__PURE__ */ jsx(ResponseList, {
2392
- operation,
2393
- spec
2394
- }) }), /* @__PURE__ */ jsx(Col, {
2395
- sticky: true,
2396
- children: /* @__PURE__ */ jsx(ResponseExamplesPanel, {
2397
- operation,
2398
- spec
2399
- })
2400
- })]
2587
+ const { spec, operation, sharedExampleKey, onSelectExampleKey, selectedStatus, onSelectStatus } = arg0;
2588
+ return /* @__PURE__ */ jsx("div", {
2589
+ className: "mt-6",
2590
+ children: /* @__PURE__ */ jsxs(Row, {
2591
+ className: "relative",
2592
+ children: [/* @__PURE__ */ jsx(Col, { children: /* @__PURE__ */ jsx("div", {
2593
+ className: "w-full",
2594
+ children: /* @__PURE__ */ jsx(ResponseList, {
2595
+ operation,
2596
+ spec,
2597
+ selectedStatus,
2598
+ onSelectStatus
2599
+ })
2600
+ }) }), /* @__PURE__ */ jsx(Col, {
2601
+ sticky: true,
2602
+ children: /* @__PURE__ */ jsx("div", {
2603
+ className: "w-full",
2604
+ children: /* @__PURE__ */ jsx(ResponseExamplesPanel, {
2605
+ operation,
2606
+ spec,
2607
+ sharedExampleKey,
2608
+ onSelectExampleKey,
2609
+ selectedStatus,
2610
+ onSelectStatus
2611
+ })
2612
+ })
2613
+ })]
2614
+ })
2401
2615
  });
2402
2616
  }
2403
2617
  //#endregion
2618
+ //#region source/openapi/components/OpenApiOperation.state.ts
2619
+ function useOperationRequestState(spec, path, operation) {
2620
+ const parameters = getOperationParameters(spec, path, operation);
2621
+ const requestBody = getRequestBody$1(spec, operation);
2622
+ const requestContents = getMediaTypeEntries(requestBody?.content, spec);
2623
+ const [selectedRequestMediaType, setSelectedRequestMediaType] = useState(requestContents[0]?.mediaType ?? "");
2624
+ const selectedRequestContent = requestContents.find((content) => content.mediaType === selectedRequestMediaType) ?? requestContents[0];
2625
+ const requestSchema = selectedRequestContent?.value.schema;
2626
+ const groupedParameters = {
2627
+ path: parameters.filter((parameter) => parameter.in === "path"),
2628
+ query: parameters.filter((parameter) => parameter.in === "query"),
2629
+ header: parameters.filter((parameter) => parameter.in === "header")
2630
+ };
2631
+ return {
2632
+ parameters,
2633
+ requestBody,
2634
+ requestContents,
2635
+ selectedRequestMediaType: selectedRequestContent?.mediaType ?? "",
2636
+ setSelectedRequestMediaType,
2637
+ requestSchema,
2638
+ groupedParameters
2639
+ };
2640
+ }
2641
+ function useOperationServerState(spec, operation, path) {
2642
+ const servers = getServers(spec, operation, path);
2643
+ const [selectedServerKey, setSelectedServerKey] = useState(getServerKey(servers[0], 0));
2644
+ const selectedServer = servers.find((server, index) => getServerKey(server, index) === selectedServerKey) ?? servers[0];
2645
+ const [serverVariables, setServerVariables] = useState(defaultServerVariables(selectedServer));
2646
+ const [serverOpen, setServerOpen] = useState(false);
2647
+ return {
2648
+ servers,
2649
+ selectedServerKey,
2650
+ selectedServer,
2651
+ serverVariables,
2652
+ serverOpen,
2653
+ onSelectServer: (value) => {
2654
+ const nextServer = servers.find((server, index) => getServerKey(server, index) === value) ?? servers[0];
2655
+ setSelectedServerKey(value);
2656
+ setServerVariables(defaultServerVariables(nextServer));
2657
+ },
2658
+ onChangeServerVariable: (name, value) => setServerVariables((current) => ({
2659
+ ...current,
2660
+ [name]: value
2661
+ })),
2662
+ onToggleServer: () => setServerOpen((current) => !current),
2663
+ closeServer: () => setServerOpen(false)
2664
+ };
2665
+ }
2666
+ function useOperationAuthState(spec, operation) {
2667
+ const authOptions = getAuthOptions(spec, operation);
2668
+ const [selectedAuthName, setSelectedAuthName] = useState(authOptions[0]?.name ?? "");
2669
+ const selectedAuth = authOptions.find((option) => option.name === selectedAuthName);
2670
+ const [authValues, setAuthValues] = useState({});
2671
+ const [authOpen, setAuthOpen] = useState(false);
2672
+ return {
2673
+ authOptions,
2674
+ selectedAuthName,
2675
+ selectedAuth,
2676
+ authValues,
2677
+ authOpen,
2678
+ authInput: selectedAuth ? {
2679
+ name: selectedAuth.name,
2680
+ scheme: selectedAuth.scheme,
2681
+ value: authValues[selectedAuth.name] ?? authPlaceholder(selectedAuth)
2682
+ } : void 0,
2683
+ onSelectAuth: setSelectedAuthName,
2684
+ onChangeAuthValue: (name, value) => setAuthValues((current) => ({
2685
+ ...current,
2686
+ [name]: value
2687
+ })),
2688
+ onToggleAuth: () => setAuthOpen((current) => !current),
2689
+ closeAuth: () => setAuthOpen(false)
2690
+ };
2691
+ }
2692
+ //#endregion
2404
2693
  //#region source/openapi/components/OpenApiOperation.tsx
2405
- var endpointMethodStyles = {
2406
- GET: "bg-emerald-400/15 text-emerald-600 dark:bg-emerald-400/20 dark:text-emerald-300",
2407
- POST: "bg-sky-400/15 text-sky-600 dark:bg-sky-400/20 dark:text-sky-300",
2408
- PUT: "bg-amber-400/15 text-amber-600 dark:bg-amber-400/20 dark:text-amber-300",
2409
- PATCH: "bg-amber-400/15 text-amber-600 dark:bg-amber-400/20 dark:text-amber-300",
2410
- DELETE: "bg-rose-400/15 text-rose-600 dark:bg-rose-400/20 dark:text-rose-300"
2694
+ var endpointMethodStyleVars = {
2695
+ GET: "bg-(--clarify-http-method-get-background) text-(--clarify-http-method-get-text)",
2696
+ POST: "bg-(--clarify-http-method-post-background) text-(--clarify-http-method-post-text)",
2697
+ PUT: "bg-(--clarify-http-method-put-background) text-(--clarify-http-method-put-text)",
2698
+ PATCH: "bg-(--clarify-http-method-patch-background) text-(--clarify-http-method-patch-text)",
2699
+ DELETE: "bg-(--clarify-http-method-delete-background) text-(--clarify-http-method-delete-text)"
2411
2700
  };
2412
2701
  function EndpointMethodBadge(arg0) {
2413
2702
  const { method } = arg0;
2414
2703
  return /* @__PURE__ */ jsx("span", {
2415
- className: clsx("rounded-(--clarify-theme-tokens-radius-md) px-2.5 py-0.5 text-xs/6 font-black tracking-wide", endpointMethodStyles[method] ?? "bg-zinc-400/15 text-zinc-700 dark:bg-zinc-400/20 dark:text-zinc-200"),
2704
+ className: clsx("rounded-(--clarify-theme-tokens-radius-md) px-2.5 py-0.5 text-xs/6 font-black tracking-wide", endpointMethodStyleVars[method] ?? "bg-(--clarify-http-method-default-background) text-(--clarify-http-method-default-text)"),
2416
2705
  children: method
2417
2706
  });
2418
2707
  }
2708
+ function EndpointPath(arg0) {
2709
+ const { path, copied = false, onCopy } = arg0;
2710
+ const t = useBuiltInText();
2711
+ return /* @__PURE__ */ jsxs("div", {
2712
+ className: "flex min-w-0 flex-1 items-center gap-2 overflow-hidden",
2713
+ children: [/* @__PURE__ */ jsx("div", {
2714
+ className: "min-w-0 flex-1 overflow-x-auto text-sm font-bold leading-6 whitespace-nowrap",
2715
+ children: /* @__PURE__ */ jsx("span", {
2716
+ className: "select-text font-mono text-(--clarify-theme-tokens-colors-foreground)",
2717
+ children: path || "/"
2718
+ })
2719
+ }), onCopy ? /* @__PURE__ */ jsx("button", {
2720
+ type: "button",
2721
+ "aria-label": copied ? t("actions.copied") : t("actions.copy"),
2722
+ title: copied ? t("actions.copied") : t("actions.copy"),
2723
+ onClick: onCopy,
2724
+ className: clsx("flex h-7 w-7 shrink-0 items-center justify-center rounded-md border border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-surface) text-(--clarify-ui-text-soft) transition hover:border-(--clarify-ui-text-faint) hover:bg-(--clarify-ui-hover-background) hover:text-(--clarify-theme-tokens-colors-foreground)", copied && "border-emerald-400/70 bg-emerald-50 text-emerald-700 dark:bg-emerald-400/10 dark:text-emerald-200"),
2725
+ children: copied ? /* @__PURE__ */ jsx(CheckIcon, {
2726
+ className: "h-3.5 w-3.5",
2727
+ "aria-hidden": "true"
2728
+ }) : /* @__PURE__ */ jsx(CopyIcon, {
2729
+ className: "h-3.5 w-3.5",
2730
+ "aria-hidden": "true"
2731
+ })
2732
+ }) : null]
2733
+ });
2734
+ }
2419
2735
  function InlineListbox(arg0) {
2420
2736
  const { label, value, options, onChange, compact = false } = arg0;
2421
2737
  const selected = options.find((option) => option.value === value) ?? options[0];
@@ -2461,6 +2777,22 @@ function InlineListbox(arg0) {
2461
2777
  function getServerPreviewUrl(server, variables) {
2462
2778
  return (server.url ?? "").replace(/\{([^}]+)\}/g, (_, name) => variables[name] ?? server.variables?.[name]?.default ?? `{${name}}`);
2463
2779
  }
2780
+ function getFullEndpointUrl(server, variables, path) {
2781
+ const base = getServerPreviewUrl(server, variables);
2782
+ if (!base) return path;
2783
+ return `${base.endsWith("/") ? base.slice(0, -1) : base}${path.startsWith("/") ? path : `/${path}`}`;
2784
+ }
2785
+ function getDefaultResponseStatus(operation, spec) {
2786
+ const orderedResponses = [...getResponseEntries(operation, spec).filter(({ response }) => getMediaTypeEntries(response.content, spec).length > 0)].sort((left, right) => {
2787
+ if (left.status === "default") return -1;
2788
+ if (right.status === "default") return 1;
2789
+ const leftCode = Number(left.status);
2790
+ const rightCode = Number(right.status);
2791
+ if (!Number.isNaN(leftCode) && !Number.isNaN(rightCode)) return leftCode - rightCode;
2792
+ return left.status.localeCompare(right.status);
2793
+ });
2794
+ return orderedResponses.find(({ status }) => status === "default")?.status ?? orderedResponses.find(({ status }) => status.startsWith("2"))?.status ?? orderedResponses[0]?.status ?? "";
2795
+ }
2464
2796
  function ServerUrlValue(arg0) {
2465
2797
  const { server, variables, open, interactive, onToggle } = arg0;
2466
2798
  const url = getServerPreviewUrl(server, variables);
@@ -2531,7 +2863,7 @@ function ServerPanel(arg0) {
2531
2863
  return /* @__PURE__ */ jsx("div", {
2532
2864
  className: "border-t border-(--clarify-theme-tokens-colors-border) bg-(--clarify-ui-subtle-background) p-3",
2533
2865
  children: /* @__PURE__ */ jsxs("div", {
2534
- className: "grid gap-3 sm:grid-cols-(--clarify-openapi-control-grid)",
2866
+ className: "flex flex-col gap-3",
2535
2867
  children: [servers.length > 1 ? /* @__PURE__ */ jsxs("label", {
2536
2868
  className: "flex min-w-0 flex-col gap-1.5",
2537
2869
  children: [/* @__PURE__ */ jsx("span", {
@@ -2547,18 +2879,21 @@ function ServerPanel(arg0) {
2547
2879
  })),
2548
2880
  onChange: onSelectServer
2549
2881
  })]
2550
- }) : null, variableEntries.map(([name, variable]) => /* @__PURE__ */ jsxs("label", {
2551
- className: "flex min-w-0 flex-col gap-1.5",
2552
- children: [/* @__PURE__ */ jsx("span", {
2553
- className: "text-2xs font-semibold text-(--clarify-ui-text-soft)",
2554
- children: name
2555
- }), /* @__PURE__ */ jsx(ServerVariableControl, {
2556
- name,
2557
- variable,
2558
- value: variables[name] ?? variable.default ?? "",
2559
- onChange: (value) => onChangeVariable(name, value)
2560
- })]
2561
- }, name))]
2882
+ }) : null, variableEntries.length > 0 ? /* @__PURE__ */ jsx("div", {
2883
+ className: "grid gap-3 sm:grid-cols-(--clarify-openapi-variable-grid)",
2884
+ children: variableEntries.map(([name, variable]) => /* @__PURE__ */ jsxs("label", {
2885
+ className: "flex min-w-0 flex-col gap-1.5",
2886
+ children: [/* @__PURE__ */ jsx("span", {
2887
+ className: "text-2xs font-semibold text-(--clarify-ui-text-soft)",
2888
+ children: name
2889
+ }), /* @__PURE__ */ jsx(ServerVariableControl, {
2890
+ name,
2891
+ variable,
2892
+ value: variables[name] ?? variable.default ?? "",
2893
+ onChange: (value) => onChangeVariable(name, value)
2894
+ })]
2895
+ }, name))
2896
+ }) : null]
2562
2897
  })
2563
2898
  });
2564
2899
  }
@@ -2606,8 +2941,17 @@ function AuthPanel(arg0) {
2606
2941
  }
2607
2942
  function EndpointIdentity(arg0) {
2608
2943
  const { method, path, servers, selectedServerKey, selectedServer, serverVariables, serverOpen, authOptions, selectedAuthName, selectedAuth, authValues, authOpen, onSelectServer, onChangeServerVariable, onToggleServer, onToggleAuth, onSelectAuth, onChangeAuthValue } = arg0;
2609
- const segments = path.split("/").filter(Boolean);
2610
2944
  const serverInteractive = servers.length > 1 || Object.keys(selectedServer.variables ?? {}).length > 0;
2945
+ const [copiedUrl, setCopiedUrl] = useState(false);
2946
+ const fullUrl = getFullEndpointUrl(selectedServer, serverVariables, path);
2947
+ useEffect(() => {
2948
+ if (!copiedUrl) return void 0;
2949
+ const timeout = window.setTimeout(() => setCopiedUrl(false), 1200);
2950
+ return () => window.clearTimeout(timeout);
2951
+ }, [copiedUrl]);
2952
+ async function handleCopyUrl() {
2953
+ if (await copyTextToClipboard(fullUrl)) setCopiedUrl(true);
2954
+ }
2611
2955
  return /* @__PURE__ */ jsxs("div", {
2612
2956
  className: "not-prose flex w-full flex-col overflow-hidden rounded-xl border border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-surface) shadow-xs",
2613
2957
  children: [
@@ -2622,24 +2966,10 @@ function EndpointIdentity(arg0) {
2622
2966
  interactive: serverInteractive,
2623
2967
  onToggle: onToggleServer
2624
2968
  }),
2625
- /* @__PURE__ */ jsx("div", {
2626
- className: "flex min-w-0 flex-1 items-center overflow-x-auto text-sm font-bold leading-6 whitespace-nowrap",
2627
- children: segments.length > 0 ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
2628
- className: "text-(--clarify-ui-text-faint)",
2629
- children: "/"
2630
- }), segments.map((segment, index) => /* @__PURE__ */ jsxs("span", {
2631
- className: "flex items-center",
2632
- children: [index > 0 ? /* @__PURE__ */ jsx("span", {
2633
- className: "text-(--clarify-ui-text-faint)",
2634
- children: "/"
2635
- }) : null, /* @__PURE__ */ jsx("span", {
2636
- className: "font-bold text-(--clarify-theme-tokens-colors-foreground)",
2637
- children: segment
2638
- })]
2639
- }, `${segment}-${index}`))] }) : /* @__PURE__ */ jsx("span", {
2640
- className: "font-bold text-(--clarify-theme-tokens-colors-foreground)",
2641
- children: "/"
2642
- })
2969
+ /* @__PURE__ */ jsx(EndpointPath, {
2970
+ path,
2971
+ copied: copiedUrl,
2972
+ onCopy: handleCopyUrl
2643
2973
  }),
2644
2974
  authOptions.length > 0 ? /* @__PURE__ */ jsx("button", {
2645
2975
  type: "button",
@@ -2681,32 +3011,11 @@ function OpenApiOperation(arg0) {
2681
3011
  const id = slug(`${method.toLowerCase()} ${path}`);
2682
3012
  const summary = operation.summary ?? `${method} ${path}`;
2683
3013
  const description = operation.description;
2684
- const parameters = getOperationParameters(spec, path, operation);
2685
- const requestBody = getRequestBody$1(spec, operation);
2686
- const requestContents = getMediaTypeEntries(requestBody?.content, spec);
2687
- const [selectedRequestMediaType, setSelectedRequestMediaType] = useState(requestContents[0]?.mediaType ?? "");
2688
- const selectedRequestContent = requestContents.find((content) => content.mediaType === selectedRequestMediaType) ?? requestContents[0];
2689
- const requestSchema = selectedRequestContent?.value.schema;
2690
- const servers = getServers(spec, operation, path);
2691
- const [selectedServerKey, setSelectedServerKey] = useState(getServerKey(servers[0], 0));
2692
- const selectedServer = servers.find((server, index) => getServerKey(server, index) === selectedServerKey) ?? servers[0];
2693
- const [serverVariables, setServerVariables] = useState(defaultServerVariables(selectedServer));
2694
- const [serverOpen, setServerOpen] = useState(false);
2695
- const authOptions = getAuthOptions(spec, operation);
2696
- const [selectedAuthName, setSelectedAuthName] = useState(authOptions[0]?.name ?? "");
2697
- const selectedAuth = authOptions.find((option) => option.name === selectedAuthName);
2698
- const [authValues, setAuthValues] = useState({});
2699
- const [authOpen, setAuthOpen] = useState(false);
2700
- const authInput = selectedAuth ? {
2701
- name: selectedAuth.name,
2702
- scheme: selectedAuth.scheme,
2703
- value: authValues[selectedAuth.name] ?? authPlaceholder(selectedAuth)
2704
- } : void 0;
2705
- const groupedParameters = {
2706
- path: parameters.filter((parameter) => parameter.in === "path"),
2707
- query: parameters.filter((parameter) => parameter.in === "query"),
2708
- header: parameters.filter((parameter) => parameter.in === "header")
2709
- };
3014
+ const requestState = useOperationRequestState(spec, path, operation);
3015
+ const serverState = useOperationServerState(spec, operation, path);
3016
+ const authState = useOperationAuthState(spec, operation);
3017
+ const [linkedExampleKey, setLinkedExampleKey] = useState("");
3018
+ const [selectedResponseStatus, setSelectedResponseStatus] = useState(() => getDefaultResponseStatus(operation, spec));
2710
3019
  return /* @__PURE__ */ jsxs("section", {
2711
3020
  className: "clarify-api-endpoint scroll-mt-24 pb-16 first:pt-0 last:pb-0",
2712
3021
  "aria-labelledby": id,
@@ -2718,58 +3027,54 @@ function OpenApiOperation(arg0) {
2718
3027
  /* @__PURE__ */ jsx(EndpointIdentity, {
2719
3028
  method,
2720
3029
  path,
2721
- servers,
2722
- selectedServerKey,
2723
- selectedServer,
2724
- serverVariables,
2725
- serverOpen,
2726
- authOptions,
2727
- selectedAuthName,
2728
- selectedAuth,
2729
- authValues,
2730
- authOpen,
2731
- onSelectServer: (value) => {
2732
- const nextServer = servers.find((server, index) => getServerKey(server, index) === value) ?? servers[0];
2733
- setSelectedServerKey(value);
2734
- setServerVariables(defaultServerVariables(nextServer));
2735
- },
2736
- onChangeServerVariable: (name, value) => setServerVariables((current) => ({
2737
- ...current,
2738
- [name]: value
2739
- })),
3030
+ servers: serverState.servers,
3031
+ selectedServerKey: serverState.selectedServerKey,
3032
+ selectedServer: serverState.selectedServer,
3033
+ serverVariables: serverState.serverVariables,
3034
+ serverOpen: serverState.serverOpen,
3035
+ authOptions: authState.authOptions,
3036
+ selectedAuthName: authState.selectedAuthName,
3037
+ selectedAuth: authState.selectedAuth,
3038
+ authValues: authState.authValues,
3039
+ authOpen: authState.authOpen,
3040
+ onSelectServer: serverState.onSelectServer,
3041
+ onChangeServerVariable: serverState.onChangeServerVariable,
2740
3042
  onToggleServer: () => {
2741
- setServerOpen((current) => !current);
2742
- setAuthOpen(false);
3043
+ serverState.onToggleServer();
3044
+ authState.closeAuth();
2743
3045
  },
2744
3046
  onToggleAuth: () => {
2745
- setAuthOpen((current) => !current);
2746
- setServerOpen(false);
3047
+ authState.onToggleAuth();
3048
+ serverState.closeServer();
2747
3049
  },
2748
- onSelectAuth: setSelectedAuthName,
2749
- onChangeAuthValue: (name, value) => setAuthValues((current) => ({
2750
- ...current,
2751
- [name]: value
2752
- }))
3050
+ onSelectAuth: authState.onSelectAuth,
3051
+ onChangeAuthValue: authState.onChangeAuthValue
2753
3052
  }),
2754
3053
  /* @__PURE__ */ jsx(EndpointRequest, {
2755
3054
  spec,
2756
3055
  path,
2757
3056
  method,
2758
3057
  description,
2759
- groupedParameters,
2760
- parameters,
2761
- requestBody,
2762
- requestContents,
2763
- requestSchema,
2764
- selectedRequestMediaType: selectedRequestContent?.mediaType ?? "",
2765
- onSelectRequestMediaType: setSelectedRequestMediaType,
2766
- selectedServer,
2767
- serverVariables,
2768
- auth: authInput
3058
+ groupedParameters: requestState.groupedParameters,
3059
+ parameters: requestState.parameters,
3060
+ requestBody: requestState.requestBody,
3061
+ requestContents: requestState.requestContents,
3062
+ requestSchema: requestState.requestSchema,
3063
+ selectedRequestMediaType: requestState.selectedRequestMediaType,
3064
+ onSelectRequestMediaType: requestState.setSelectedRequestMediaType,
3065
+ selectedServer: serverState.selectedServer,
3066
+ serverVariables: serverState.serverVariables,
3067
+ auth: authState.authInput,
3068
+ sharedExampleKey: linkedExampleKey,
3069
+ onSelectExampleKey: setLinkedExampleKey
2769
3070
  }),
2770
3071
  /* @__PURE__ */ jsx(EndpointResponse, {
2771
3072
  spec,
2772
- operation
3073
+ operation,
3074
+ sharedExampleKey: linkedExampleKey,
3075
+ onSelectExampleKey: setLinkedExampleKey,
3076
+ selectedStatus: selectedResponseStatus,
3077
+ onSelectStatus: setSelectedResponseStatus
2773
3078
  })
2774
3079
  ]
2775
3080
  });
@@ -2777,4 +3082,4 @@ function OpenApiOperation(arg0) {
2777
3082
  //#endregion
2778
3083
  export { Button as A, Code as C, Card as D, Mermaid as E, CardGroup as O, Collapse as S, Pre as T, HeroPattern as _, authPlaceholder as a, Tag as b, getServerKey as c, getRequestBody$1 as d, Markdown as f, GridPattern as g, Prose as h, ResponseExamplesPanel as i, Callout as k, getServers as l, WebFrame as m, OpenApiOperation as n, defaultServerVariables as o, primitives_exports as p, RequestExamplesPanel as r, getAuthOptions as s, EndpointIdentity as t, getMediaTypeEntries as u, Logo as v, CodeGroup as w, Feedback as x, Heading as y };
2779
3084
 
2780
- //# sourceMappingURL=OpenApiOperation-E8lSLsSK.js.map
3085
+ //# sourceMappingURL=OpenApiOperation-C9xyRo5a.js.map