@redocly/marketing-pages 0.1.26 → 0.1.28

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 (36) hide show
  1. package/dist/pages/editor/components/EditorPanel/EditorContent.js +1 -1
  2. package/dist/pages/editor/components/Layout/MainLayout.js +10 -10
  3. package/dist/pages/editor/components/Page.d.ts +1 -1
  4. package/dist/pages/editor/components/Page.js +1 -1
  5. package/dist/pages/editor/components/PreviewPanel/IframeContainer.d.ts +0 -1
  6. package/dist/pages/editor/components/PreviewPanel/IframeContainer.js +3 -3
  7. package/dist/pages/editor/components/PreviewPanel/PreviewContent.js +9 -5
  8. package/dist/pages/editor/components/PreviewPanel.js +1 -1
  9. package/dist/pages/editor/components/Toolbar.js +8 -8
  10. package/dist/pages/editor/editor.page.js +1 -1
  11. package/dist/pages/editor/hooks/useEditorCommunication.js +2 -2
  12. package/dist/pages/editor/hooks/useEditorState.js +1 -1
  13. package/dist/pages/editor/hooks/useMonacoEditor.d.ts +13 -10
  14. package/dist/pages/editor/hooks/useMonacoEditor.js +1 -2
  15. package/dist/pages/editor/{services/languageServerService.d.ts → service/languageServer.d.ts} +5 -2
  16. package/dist/pages/editor/service/languageServer.js +3 -0
  17. package/dist/pages/editor/templates/defaultOpenapiTemplate.d.ts +1 -1
  18. package/dist/pages/editor/templates/defaultOpenapiTemplate.js +228 -9
  19. package/dist/pages/editor-preview/components/Page.d.ts +2 -0
  20. package/dist/pages/editor-preview/components/Page.js +3 -0
  21. package/dist/pages/editor-preview/editor-preview.page.d.ts +2 -7
  22. package/dist/pages/editor-preview/editor-preview.page.js +1 -1
  23. package/dist/pages/editor-preview/hooks/useCommunicationManager.d.ts +2 -3
  24. package/dist/pages/editor-preview/hooks/useCommunicationManager.js +1 -1
  25. package/dist/pages/editor-preview/hooks/useDefinitionManager.js +1 -1
  26. package/dist/pages/pricing/components/PlansSection.js +6 -6
  27. package/dist/pages/pricing/pricingData/data.d.ts +3 -0
  28. package/dist/pages/pricing/pricingData/data.js +1 -1
  29. package/package.json +12 -2
  30. package/dist/pages/editor/services/languageServerService.js +0 -3
  31. package/dist/pages/editor/types/index.d.ts +0 -66
  32. package/dist/pages/editor/types/index.js +0 -0
  33. package/dist/pages/editor-preview/components/DocsRenderer.d.ts +0 -7
  34. package/dist/pages/editor-preview/components/DocsRenderer.js +0 -4
  35. package/dist/pages/editor-preview/components/PreviewContent.d.ts +0 -7
  36. package/dist/pages/editor-preview/components/PreviewContent.js +0 -1
@@ -1 +1 @@
1
- import*as n from"react";import p from"@monaco-editor/react";import{useMonacoEditor as O}from"../../hooks/useMonacoEditor";import{DEFAULT_EDITOR_OPTIONS as v,EDITOR_LANGUAGE as R,EDITOR_THEMES as T}from"../../constants/editorConfig";import{useEditorCommunication as b}from"../../hooks/useEditorCommunication";const M=({value:o,onChange:l,onValidationUpdate:m,hideWarnings:f,isFullPreview:s,gotoPosition:r})=>{const u=n.useRef(()=>{}),{activeColorMode:a,handleEditorDidMount:E,handleEditorBeforeMount:d,editorRef:e}=O({onValidationUpdate:m,hideWarnings:f,onClick:t=>{u.current(t.lineNumber)}}),{scrollPreviewToOperation:i}=b({value:o,isFullPreview:s||!1,editorRef:e});return n.useEffect(()=>{u.current=i},[i]),n.useEffect(()=>{r&&e.current&&(e.current.revealPositionInCenter({lineNumber:r.line,column:r.column}),e.current.setPosition({lineNumber:r.line,column:r.column}))},[r,e]),n.useEffect(()=>{if(!e.current)return;const t=new ResizeObserver(()=>{e.current&&e.current.layout()}),c=e.current.getDomNode();return c&&t.observe(c),()=>{t.disconnect()}},[e]),n.createElement(p,{language:R,theme:T[a],value:o,options:v,onChange:l,beforeMount:d,onMount:E})};var h=M;export{h as default};
1
+ import*as n from"react";import d from"@monaco-editor/react";import{useMonacoEditor as p}from"../../hooks/useMonacoEditor";import{DEFAULT_EDITOR_OPTIONS as O,EDITOR_LANGUAGE as v,EDITOR_THEMES as R}from"../../constants/editorConfig";import{useEditorCommunication as T}from"../../hooks/useEditorCommunication";const b=({value:o,onChange:l,onValidationUpdate:m,hideWarnings:s,isFullPreview:f,gotoPosition:r})=>{const c=n.useRef(()=>{}),{activeColorMode:a,handleEditorDidMount:E,editorRef:e}=p({onValidationUpdate:m,hideWarnings:s,onClick:t=>{c.current(t.lineNumber)}}),{scrollPreviewToOperation:i}=T({value:o,isFullPreview:f||!1,editorRef:e});return n.useEffect(()=>{c.current=i},[i]),n.useEffect(()=>{r&&e.current&&(e.current.revealPositionInCenter({lineNumber:r.line,column:r.column}),e.current.setPosition({lineNumber:r.line,column:r.column}))},[r,e]),n.useEffect(()=>{if(!e.current)return;const t=new ResizeObserver(()=>{e.current&&e.current.layout()}),u=e.current.getDomNode();return u&&t.observe(u),()=>{t.disconnect()}},[e]),n.createElement(d,{language:v,theme:R[a],value:o,options:O,onChange:l,onMount:E})};var M=b;export{M as default};
@@ -1,4 +1,4 @@
1
- import o from"react";import e from"styled-components";import{PanelGroup as P,PanelResizeHandle as k}from"react-resizable-panels";import x from"./EditorLayout";import z from"./PreviewLayout";const E=({value:a,onChange:n,onValidationUpdate:i,hideWarnings:l,onHideWarningsChange:t,isFullPreview:c,gotoPosition:s,parsedErrors:d,onProblemClick:m,onFileLoad:r,onDownloadYaml:u,onDownloadJson:h,onToggleFullPreview:g,definition:p,rawValue:v,hasRenderedOnce:y,hasStructErrors:b,onTemplateClick:f,isClient:w})=>o.createElement(C,null,o.createElement(L,{direction:"horizontal"},o.createElement(x,{value:a,onChange:n,onValidationUpdate:i,hideWarnings:l,onHideWarningsChange:t,isFullPreview:c,gotoPosition:s,parsedErrors:d,onProblemClick:m,onFileLoad:r,onDownloadYaml:u,onDownloadJson:h,onToggleFullPreview:g}),o.createElement(k,{className:"resize-handle"}),o.createElement(z,{definition:p,rawValue:v,hasRenderedOnce:y,hasStructErrors:b,onTemplateClick:f,onFileLoad:r,isClient:w})));var V=E;const C=e.div`
1
+ import e from"react";import r from"styled-components";import{PanelGroup as w,PanelResizeHandle as P}from"react-resizable-panels";import k from"./EditorLayout";import x from"./PreviewLayout";const E=({value:a,onChange:n,onValidationUpdate:l,hideWarnings:i,onHideWarningsChange:t,isFullPreview:c,gotoPosition:s,parsedErrors:d,onProblemClick:h,onFileLoad:o,onDownloadYaml:u,onDownloadJson:m,onToggleFullPreview:g,definition:p,rawValue:v,hasRenderedOnce:b,hasStructErrors:f,onTemplateClick:z,isClient:y})=>e.createElement(C,null,e.createElement(L,{direction:"horizontal"},e.createElement(k,{value:a,onChange:n,onValidationUpdate:l,hideWarnings:i,onHideWarningsChange:t,isFullPreview:c,gotoPosition:s,parsedErrors:d,onProblemClick:h,onFileLoad:o,onDownloadYaml:u,onDownloadJson:m,onToggleFullPreview:g}),e.createElement(P,{className:"resize-handle"}),e.createElement(x,{definition:p,rawValue:v,hasRenderedOnce:b,hasStructErrors:f,onTemplateClick:z,onFileLoad:o,isClient:y})));var V=E;const C=r.div`
2
2
  display: flex;
3
3
  flex-direction: column;
4
4
  height: calc(100vh - var(--navbar-height));
@@ -9,31 +9,31 @@ import o from"react";import e from"styled-components";import{PanelGroup as P,Pan
9
9
  [data-component-name='Layout/PageLayout']:has(&) + div + footer {
10
10
  display: none;
11
11
  }
12
- `,L=e(P)`
12
+ `,L=r(w)`
13
13
  display: flex;
14
14
  flex-grow: 1;
15
15
  height: 100%;
16
16
  overflow: visible;
17
17
 
18
18
  .resize-handle {
19
- width: 8px;
19
+ width: 4px;
20
20
  background-color: var(--border-color-primary);
21
21
  cursor: col-resize;
22
22
  transition: background-color 0.2s ease;
23
+ }
23
24
 
24
- &:hover {
25
- background-color: var(--color-primary-variant);
26
- }
25
+ .resize-handle[data-resize-handle-state="hover"] {
26
+ background-color: var(--color-blue-4);
27
27
  }
28
28
 
29
29
  .resize-handle-horizontal {
30
- height: 8px;
30
+ height: 4px;
31
31
  background-color: var(--border-color-primary);
32
32
  cursor: row-resize;
33
33
  transition: background-color 0.2s ease;
34
+ }
34
35
 
35
- &:hover {
36
- background-color: var(--color-primary-variant);
37
- }
36
+ .resize-handle-horizontal[data-resize-handle-state="hover"] {
37
+ background-color: var(--color-blue-4);
38
38
  }
39
39
  `;export{V as default};
@@ -1,2 +1,2 @@
1
- import React from "react";
1
+ import React from 'react';
2
2
  export default function Page(): React.JSX.Element;
@@ -1 +1 @@
1
- import o from"react";import{useEditorState as D}from"../hooks/useEditorState";import{useOpenApiValidation as L}from"../hooks/useOpenApiValidation";import{useFileOperations as R}from"../hooks/useFileOperations";import T from"./Layout/MainLayout";import W from"./Layout/FullPreviewLayout";function H(){const[i,h]=o.useState(!1),[r,s]=o.useState(!1);o.useEffect(()=>h(!0),[]);const{value:n,setValue:d,validatedValue:p,setValidatedValue:f,setValidationErrors:u,setFileName:w,parsedErrors:C,hasStructErrors:a,hideWarnings:F,setHideWarnings:P}=D(),{definition:c,hasRenderedOnce:m,setHasRenderedOnce:g}=L({validatedValue:p,hasStructErrors:a}),[E,V]=o.useState(null),e=R({setValue:d,setFileName:w,setHasRenderedOnce:g,setValidationErrors:u}),v=(t,l)=>{u(t),f(l)},O=(t,l)=>{V({line:t,column:l})},S=()=>e.handleDownloadYaml(n),k=()=>e.handleDownloadJson(n);return r?o.createElement(W,{definition:c,rawValue:n,hasRenderedOnce:m,hasStructErrors:a,onTemplateClick:e.handleTemplateClick,onFileLoad:e.handleFileLoad,onExitFullPreview:()=>s(!1),isClient:i}):o.createElement(T,{value:n,onChange:d,onValidationUpdate:v,hideWarnings:F,onHideWarningsChange:P,isFullPreview:r,gotoPosition:E,parsedErrors:C,onProblemClick:O,onFileLoad:e.handleFileLoad,onDownloadYaml:S,onDownloadJson:k,onToggleFullPreview:()=>s(!0),definition:c,rawValue:n,hasRenderedOnce:m,hasStructErrors:a,onTemplateClick:e.handleTemplateClick,isClient:i})}export{H as default};
1
+ import e from"react";import{useEditorState as L}from"../hooks/useEditorState";import{useOpenApiValidation as T}from"../hooks/useOpenApiValidation";import{useFileOperations as W}from"../hooks/useFileOperations";import H from"./Layout/MainLayout";import J from"./Layout/FullPreviewLayout";function Y(){const[r,p]=e.useState(!1),[s,d]=e.useState(!1);e.useEffect(()=>p(!0),[]);const{value:o,setValue:u,validatedValue:w,setValidatedValue:C,setValidationErrors:c,setFileName:E,parsedErrors:F,hasStructErrors:a,hideWarnings:P,setHideWarnings:g}=L(),{definition:t,hasRenderedOnce:f,setHasRenderedOnce:V}=T({validatedValue:w,hasStructErrors:a}),m=e.useRef(null);e.useEffect(()=>{t&&(m.current=t)},[t]);const h=t||m.current,[v,D]=e.useState(null),n=W({setValue:u,setFileName:E,setHasRenderedOnce:V,setValidationErrors:c}),R=(i,l)=>{c(i),C(l)},O=(i,l)=>{D({line:i,column:l})},S=()=>n.handleDownloadYaml(o),k=()=>n.handleDownloadJson(o);return s?e.createElement(J,{definition:h,rawValue:o,hasRenderedOnce:f,hasStructErrors:a,onTemplateClick:n.handleTemplateClick,onFileLoad:n.handleFileLoad,onExitFullPreview:()=>d(!1),isClient:r}):e.createElement(H,{value:o,onChange:u,onValidationUpdate:R,hideWarnings:P,onHideWarningsChange:g,isFullPreview:s,gotoPosition:v,parsedErrors:F,onProblemClick:O,onFileLoad:n.handleFileLoad,onDownloadYaml:S,onDownloadJson:k,onToggleFullPreview:()=>d(!0),definition:h,rawValue:o,hasRenderedOnce:f,hasStructErrors:a,onTemplateClick:n.handleTemplateClick,isClient:r})}export{Y as default};
@@ -2,7 +2,6 @@ import React from 'react';
2
2
  interface IframeContainerProps {
3
3
  definition: any | null;
4
4
  onIframeReady: (iframeWindow: Window) => void;
5
- onMessage: (event: MessageEvent) => void;
6
5
  }
7
6
  declare const IframeContainer: React.FC<IframeContainerProps>;
8
7
  export default IframeContainer;
@@ -1,8 +1,8 @@
1
- import n,{useRef as c,useEffect as a}from"react";import i from"styled-components";const d=({definition:r,onIframeReady:s,onMessage:g})=>{const l=c(null),t=c(null),[m,p]=n.useState(0);return a(()=>{const o=e=>{console.log("[IframeContainer] Iframe ready, setting up communication"),t.current=e,e.updateDefinition(r),s(e)};return window.onReady=o,console.log("[IframeContainer] onReady callback registered"),()=>{delete window.onReady}},[r,s]),a(()=>{const o=e=>{if(e.data?.type==="scroll-to-operation"){if(!t.current){console.warn("[IframeContainer] Received scroll message but iframe not ready");return}console.log("[IframeContainer] Forwarding scroll-to-operation to iframe:",e.data.operationPath),t.current.postMessage(e.data,"*")}};return window.addEventListener("message",o),()=>window.removeEventListener("message",o)},[]),a(()=>{t.current&&r&&t.current.updateDefinition(r)},[r]),n.createElement(u,null,n.createElement(f,{key:m,ref:l,title:"API Documentation Preview",src:"/preview",onLoad:()=>{}}))};var I=d;const u=i.div`
1
+ import o,{useRef as c,useEffect as a}from"react";import u from"styled-components";const d=({definition:t,onIframeReady:s})=>{const l=c(null),r=c(null),[i,w]=o.useState(0);return a(()=>{const n=e=>{r.current=e,e.updateDefinition(t),s(e)};return window.onReady=n,()=>{delete window.onReady}},[t,s]),a(()=>{const n=e=>{e.data?.type==="scroll-to-operation"&&r.current&&r.current.postMessage(e.data,"*")};return window.addEventListener("message",n),()=>window.removeEventListener("message",n)},[]),a(()=>{r.current&&t&&r.current.updateDefinition(t)},[t]),o.createElement(f,null,o.createElement(m,{key:i,ref:l,title:"API Documentation Preview",src:"/preview",onLoad:()=>{}}))};var y=d;const f=u.div`
2
2
  height: 100%;
3
3
  overflow: hidden;
4
- `,f=i.iframe`
4
+ `,m=u.iframe`
5
5
  width: 100%;
6
6
  height: 100%;
7
7
  border: none;
8
- `;export{I as default};
8
+ `;export{y as default};
@@ -1,16 +1,20 @@
1
- import e from"react";import n from"styled-components";import{Button as s}from"@redocly/theme/components/Button/Button";import{MinimizeIcon as f}from"@redocly/theme/icons/MinimizeIcon/MinimizeIcon";import l from"./ErrorOverlay";import E from"./IframeContainer";import d from"../EmptyState";const u=({definition:r,rawValue:t,hasStructErrors:o,onTemplateClick:m,onFileLoad:c,onExitFullPreview:i,onIframeReady:p})=>!t||typeof t!="string"||t.trim()===""?e.createElement(d,{onTemplateClick:m,onUploadClick:c}):r?e.createElement(a,null,e.createElement(l,{hasStructErrors:o}),i&&e.createElement(g,{variant:"secondary",onClick:i,"aria-label":"Exit full preview",icon:e.createElement(f,null)}),e.createElement(E,{definition:r,onIframeReady:p,onMessage:()=>{}})):e.createElement(a,null,e.createElement(l,{hasStructErrors:o}),e.createElement(y,null,"Loading..."));var M=u;const a=n.div`
1
+ import e from"react";import t from"styled-components";import{Button as f}from"@redocly/theme/components/Button/Button";import{Tooltip as s}from"@redocly/theme/components/Tooltip/Tooltip";import{ViewOffIcon as d}from"@redocly/theme/icons/ViewOffIcon/ViewOffIcon";import l from"./ErrorOverlay";import E from"./IframeContainer";import u from"../EmptyState";const x=({definition:n,rawValue:o,hasStructErrors:r,onTemplateClick:m,onFileLoad:p,onExitFullPreview:i,onIframeReady:c})=>!o||typeof o!="string"||o.trim()===""?e.createElement(u,{onTemplateClick:m,onUploadClick:p}):n?e.createElement(a,null,e.createElement(l,{hasStructErrors:r}),i&&e.createElement(y,null,e.createElement(g,{tip:"Exit full preview mode",width:"fit-content",placement:"right"},e.createElement(f,{variant:"secondary",onClick:i,"aria-label":"Exit full preview",icon:e.createElement(d,null)}))),e.createElement(E,{definition:n,onIframeReady:c})):e.createElement(a,null,e.createElement(l,{hasStructErrors:r}),e.createElement(v,null,"Loading..."));var w=x;const a=t.div`
2
2
  position: relative;
3
3
  height: 100%;
4
- `,g=n(s)`
4
+ `,y=t.div`
5
5
  position: absolute;
6
6
  top: 12px;
7
7
  left: 12px;
8
- z-index: 30;
9
- `,y=n.div`
8
+ z-index: 100;
9
+ `,g=t(s)`
10
+ [data-component-name='Tooltip/Tooltip'] {
11
+ z-index: 101 !important;
12
+ }
13
+ `,v=t.div`
10
14
  display: flex;
11
15
  align-items: center;
12
16
  justify-content: center;
13
17
  height: 100%;
14
18
  font-size: 14px;
15
19
  color: #666;
16
- `;export{M as default};
20
+ `;export{w as default};
@@ -1 +1 @@
1
- import*as r from"react";import{useRef as f}from"react";import m from"./PreviewPanel/PreviewContent";const s=({definition:e,rawValue:o,hasStructErrors:n,onTemplateClick:a,onFileLoad:l,onExitFullPreview:c})=>{const t=f(null),i=e||t.current;r.useEffect(()=>{e&&(t.current=e)},[e]);const u=r.useCallback(d=>{},[]);return r.createElement(m,{definition:i,rawValue:o,hasStructErrors:n,onTemplateClick:a,onFileLoad:l,onExitFullPreview:c,onIframeReady:u})};var R=s;export{R as default};
1
+ import*as e from"react";import m from"./PreviewPanel/PreviewContent";const c=({definition:r,rawValue:a,hasStructErrors:t,onTemplateClick:o,onFileLoad:n,onExitFullPreview:i})=>{const l=e.useCallback(d=>{},[]);return e.createElement(m,{definition:r??"",rawValue:a,hasStructErrors:t,onTemplateClick:o,onFileLoad:n,onExitFullPreview:i,onIframeReady:l})};var s=c;export{s as default};
@@ -1,4 +1,4 @@
1
- import e,{useRef as y,useState as k}from"react";import o from"styled-components";import{Button as n}from"@redocly/theme/components/Button/Button";import{DownloadIcon as s}from"@redocly/theme/icons/DownloadIcon/DownloadIcon";import{ChevronDownIcon as C}from"@redocly/theme/icons/ChevronDownIcon/ChevronDownIcon";import{MaximizeIcon as D}from"@redocly/theme/icons/MaximizeIcon/MaximizeIcon";function I({hideWarnings:f,onHideWarningsChange:u,onDownloadYamlClick:c,onDownloadJsonClick:x,onFileLoad:g,onToggleFullPreview:p}){const d=y(null),[b,r]=k(!1),v=()=>{d.current?.click()},E=()=>r(t=>!t),h=t=>{const l=t.target.files?.[0];if(!l)return;const a=new FileReader;a.onload=i=>{const w=i.target?.result;g(w,l.name)},a.onerror=i=>{console.error("Failed to read file!",i)},a.readAsText(l),t.target.value=""};return e.createElement(z,null,e.createElement(M,null,e.createElement("input",{type:"checkbox",checked:f,onChange:t=>u(t.target.checked),id:"hide-warnings"}),"Hide warnings"),e.createElement(R,null,p&&e.createElement(n,{variant:"text",onClick:p,"aria-label":"Enter full preview",icon:e.createElement(D,null)}),e.createElement(n,{variant:"text",icon:e.createElement(s,{style:{transform:"rotate(180deg)"}}),onClick:v,"aria-label":"Upload spec"}),e.createElement(F,{type:"file",ref:d,onChange:h,accept:".yaml,.yml,.json"}),e.createElement(A,null,e.createElement(n,{variant:"text",onClick:c,iconPosition:"left",icon:e.createElement(s,null)},"Download"),e.createElement(n,{icon:e.createElement(C,null),onClick:E,"aria-label":"Download options"}),b&&e.createElement(B,null,e.createElement(m,{onClick:()=>{c(),r(!1)}},"Download YAML"),e.createElement(m,{onClick:()=>{x(),r(!1)}},"Download JSON")))))}const z=o.div`
1
+ import e,{useRef as k,useState as C}from"react";import t from"styled-components";import{Button as n}from"@redocly/theme/components/Button/Button";import{Tooltip as c}from"@redocly/theme/components/Tooltip/Tooltip";import{DownloadIcon as m}from"@redocly/theme/icons/DownloadIcon/DownloadIcon";import{ChevronDownIcon as D}from"@redocly/theme/icons/ChevronDownIcon/ChevronDownIcon";import{ViewIcon as I}from"@redocly/theme/icons/ViewIcon/ViewIcon";function R({hideWarnings:u,onHideWarningsChange:x,onDownloadYamlClick:p,onDownloadJsonClick:g,onFileLoad:b,onToggleFullPreview:d}){const s=k(null),[w,r]=C(!1),E=()=>{s.current?.click()},h=()=>r(o=>!o),v=o=>{const l=o.target.files?.[0];if(!l)return;const a=new FileReader;a.onload=i=>{const y=i.target?.result;b(y,l.name)},a.onerror=i=>{console.error("Failed to read file!",i)},a.readAsText(l),o.target.value=""};return e.createElement(z,null,e.createElement(A,null,e.createElement("input",{type:"checkbox",checked:u,onChange:o=>x(o.target.checked),id:"hide-warnings"}),"Hide warnings"),e.createElement(B,null,d&&e.createElement(c,{tip:"Enter full preview mode",width:"fit-content"},e.createElement(n,{variant:"text",onClick:d,"aria-label":"Enter full preview",icon:e.createElement(I,null)})),e.createElement(c,{tip:"Upload spec",width:"fit-content"},e.createElement(n,{variant:"text",icon:e.createElement(m,{style:{transform:"rotate(180deg)"}}),onClick:E,"aria-label":"Upload spec"})),e.createElement(O,{type:"file",ref:s,onChange:v,accept:".yaml,.yml,.json"}),e.createElement(F,null,e.createElement(n,{variant:"text",onClick:p,iconPosition:"left",icon:e.createElement(m,null)},"Download"),e.createElement(c,{tip:"Download options",width:"fit-content"},e.createElement(n,{icon:e.createElement(D,null),onClick:h,"aria-label":"Download options"})),w&&e.createElement(M,null,e.createElement(f,{onClick:()=>{p(),r(!1)}},"Download YAML"),e.createElement(f,{onClick:()=>{g(),r(!1)}},"Download JSON")))))}const z=t.div`
2
2
  padding: 6px 12px;
3
3
  border-bottom: 1px solid var(--border-color-primary);
4
4
  display: flex;
@@ -6,25 +6,25 @@ import e,{useRef as y,useState as k}from"react";import o from"styled-components"
6
6
  background-color: var(--bg-color);
7
7
  color: var(--text-color-primary);
8
8
  gap: 16px;
9
- `,M=o.label`
9
+ `,A=t.label`
10
10
  display: flex;
11
11
  align-items: center;
12
12
  gap: 8px;
13
13
  font-size: 0.875rem;
14
14
  cursor: pointer;
15
- `,R=o.div`
15
+ `,B=t.div`
16
16
  display: flex;
17
17
  align-items: center;
18
18
  gap: 8px;
19
19
  margin-left: auto; /* Push to far right */
20
- `,A=o.div`
20
+ `,F=t.div`
21
21
  position: relative;
22
22
  display: inline-flex;
23
23
  align-items: center;
24
24
  display: flex;
25
25
  flex-direction: row;
26
26
  gap: calc(var(--spacing-xxs) / 2);
27
- `,B=o.ul`
27
+ `,M=t.ul`
28
28
  position: absolute;
29
29
  right: 0;
30
30
  top: 100%;
@@ -38,13 +38,13 @@ import e,{useRef as y,useState as k}from"react";import o from"styled-components"
38
38
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
39
39
  min-width: 140px;
40
40
  z-index: 20;
41
- `,m=o.li`
41
+ `,f=t.li`
42
42
  padding: 6px 12px;
43
43
  font-size: 0.875rem;
44
44
  cursor: pointer;
45
45
  &:hover {
46
46
  background-color: var(--bg-color-active, #f5f5f5);
47
47
  }
48
- `,F=o.input`
48
+ `,O=t.input`
49
49
  display: none;
50
- `;export{I as default};
50
+ `;export{R as default};
@@ -1 +1 @@
1
- import t from"./components/Page";const e={seo:{title:"Redocly Editor"},slug:"/editor"};var r=t;export{r as default,e as frontmatter};
1
+ import t from"./components/Page";const o={seo:{title:"Swagger Editor"},slug:"/editor"};var r=t;export{r as default,o as frontmatter};
@@ -1,2 +1,2 @@
1
- import{useEffect as P,useRef as f}from"react";import{findOperationAtLine as h,findOperationLineInEditor as w,sendScrollToPreview as E,isPositionInOperationBlock as L}from"../utils/operationScrolling";const T=({value:o,isFullPreview:c,editorRef:r})=>{const u=f(0),m=f(0);P(()=>{const e=t=>{if(t.data?.type!=="scroll-to-operation"||t.data?.source!=="preview"||!r.current||c)return;const a=Date.now();if(a-u.current<1e3)return;m.current=a;const l=t.data.operationPath;p(l)};return window.addEventListener("message",e),()=>window.removeEventListener("message",e)},[c,r]);const g=e=>{if(!o||c)return;const t=h(o,e);t?(console.log("[Editor] Sending scroll-to-operation:",t.pointer),u.current=Date.now(),E(t.pointer)):console.log("[Editor] No operation found at line",e)},p=e=>{if(!r.current||!o)return;const t=w(o,e);if(!t)return;const l=r.current.getPosition()?.lineNumber||1,i=o.split(`
2
- `);let s=-1,d=i.length;for(let n=0;n<i.length;n++)if(i[n].includes(e.replace("#/paths/","").replace(/~1/g,"/"))){s=n;break}if(s!==-1){for(let n=s+1;n<i.length;n++)if(/^\s*\/[^:]+:\s*$/.test(i[n])){d=n;break}if(L(l,s,d))return}r.current.revealPositionInCenter({lineNumber:t,column:1}),r.current.setPosition({lineNumber:t,column:1})};return{scrollPreviewToOperation:g,scrollToOperationInEditor:p}};export{T as useEditorCommunication};
1
+ import{useEffect as h,useRef as m}from"react";import{findOperationAtLine as w,findOperationLineInEditor as g,sendScrollToPreview as E,isPositionInOperationBlock as L}from"../utils/operationScrolling";const T=({value:o,isFullPreview:c,editorRef:r})=>{const u=m(0),d=m(0);h(()=>{const e=t=>{if(t.data?.type!=="scroll-to-operation"||t.data?.source!=="preview"||!r.current||c)return;const a=Date.now();if(a-u.current<1e3)return;d.current=a;const l=t.data.operationPath;p(l)};return window.addEventListener("message",e),()=>window.removeEventListener("message",e)},[c,r]);const P=e=>{if(!o||c)return;const t=w(o,e);t&&(u.current=Date.now(),E(t.pointer))},p=e=>{if(!r.current||!o)return;const t=g(o,e);if(!t)return;const l=r.current.getPosition()?.lineNumber||1,i=o.split(`
2
+ `);let s=-1,f=i.length;for(let n=0;n<i.length;n++)if(i[n].includes(e.replace("#/paths/","").replace(/~1/g,"/"))){s=n;break}if(s!==-1){for(let n=s+1;n<i.length;n++)if(/^\s*\/[^:]+:\s*$/.test(i[n])){f=n;break}if(L(l,s,f))return}r.current.revealPositionInCenter({lineNumber:t,column:1}),r.current.setPosition({lineNumber:t,column:1})};return{scrollPreviewToOperation:P,scrollToOperationInEditor:p}};export{T as useEditorCommunication};
@@ -1 +1 @@
1
- import{useEffect as l,useMemo as n,useState as t}from"react";function h(){const i=typeof localStorage<"u"&&localStorage.getItem("editorValue")||"",[e,u]=t(i),[c,o]=t(void 0),[r,d]=t([]),[m,f]=t(""),[V,g]=t(!1),E=/Rule: ([\w-_\/]+)/,s=n(()=>r.map(a=>({...a,rule:a.message.match(E)?.[1]})),[r]),S=n(()=>s.some(a=>a.rule==="struct"),[s]);return l(()=>{localStorage.setItem("editorValue",e)},[e]),l(()=>{o(e)},[e]),{value:e,setValue:u,validatedValue:c,setValidatedValue:o,validationErrors:r,setValidationErrors:d,fileName:m,setFileName:f,hideWarnings:V,setHideWarnings:g,parsedErrors:s,hasStructErrors:S}}export{h as useEditorState};
1
+ import{useEffect as S,useMemo as o,useState as e}from"react";function h(){const l=typeof localStorage<"u"&&localStorage.getItem("editorValue")||"",[a,n]=e(l),[i,u]=e(void 0),[r,c]=e([]),[d,m]=e(""),[f,V]=e(!1),g=/Rule: ([\w-_\/]+)/,s=o(()=>r.map(t=>({...t,rule:t.message.match(g)?.[1]})),[r]),E=o(()=>s.some(t=>t.rule==="struct"),[s]);return S(()=>{localStorage.setItem("editorValue",a)},[a]),{value:a,setValue:n,validatedValue:i,setValidatedValue:u,validationErrors:r,setValidationErrors:c,fileName:d,setFileName:m,hideWarnings:f,setHideWarnings:V,parsedErrors:s,hasStructErrors:E}}export{h as useEditorState};
@@ -1,13 +1,16 @@
1
- import type { editor, Position } from "monaco-editor";
1
+ import type * as Monaco from 'monaco-editor/esm/vs/editor/editor.api';
2
+ export interface MonacoEditorHook {
3
+ editorRef: React.MutableRefObject<Monaco.editor.IStandaloneCodeEditor | null>;
4
+ monacoRef: React.MutableRefObject<typeof Monaco | null>;
5
+ activeColorMode: string;
6
+ handleEditorDidMount: (editor: Monaco.editor.IStandaloneCodeEditor, monaco: typeof Monaco) => () => void;
7
+ }
2
8
  export interface MonacoEditorOptions {
3
- onValidationUpdate?: (errors: editor.IMarkerData[], value: string) => void;
4
- onClick?: (position: Position) => void;
9
+ onValidationUpdate?: (errors: Monaco.editor.IMarkerData[], value: string) => void;
10
+ onClick?: (position: Monaco.Position) => void;
5
11
  hideWarnings?: boolean;
6
12
  }
7
- export declare function useMonacoEditor({ onValidationUpdate, onClick, hideWarnings }: MonacoEditorOptions): {
8
- editorRef: import("react").MutableRefObject<editor.IStandaloneCodeEditor | null>;
9
- monacoRef: import("react").MutableRefObject<null>;
10
- activeColorMode: string;
11
- handleEditorDidMount: (editor: editor.IStandaloneCodeEditor, monaco: any) => (() => void);
12
- handleEditorBeforeMount: (monaco: any) => void;
13
- };
13
+ /**
14
+ * Custom hook to manage Monaco editor integration with language server and scroll sync
15
+ */
16
+ export declare const useMonacoEditor: (options?: MonacoEditorOptions) => MonacoEditorHook;
@@ -1,2 +1 @@
1
- import{useEffect as C,useRef as c}from"react";import{LanguageServerService as L}from"../services/languageServerService";import{useColorMode as b}from"./useColorMode";import{useThemeHooks as E}from"@redocly/theme/core/hooks";function x({onValidationUpdate:l,onClick:f,hideWarnings:r}){const i=c(null),o=c(null),t=c(null),{useGlobalData:m}=E(),T=m(),p=b(),M=(e,g)=>{i.current=e,o.current=g,t.current||(t.current=new L),t.current.initialize(e,g);const h=t.current.setupAutoValidation(l,r);e.onMouseDown(({target:u})=>{f?.(u.position)});const s=e.getModel();if(s){const u=s.onDidChangeContent(d=>{d.changes.some(n=>n.text.includes(`
2
- `))&&setTimeout(()=>{const n=e.getPosition();try{const a=e.getModel();if(a&&o.current){const D=a.getLanguageId();o.current.editor.setModelLanguage(a,"plaintext"),setTimeout(()=>{o.current.editor.setModelLanguage(a,D),n&&e.setPosition(n)},10)}}catch{e.render(),e.layout(),n&&e.setPosition(n)}},0)});e._contentChangeDisposable=u}return setTimeout(()=>{if(e.layout(),s){const u=s.getValue();s.setValue(u),e.render()}},100),setTimeout(()=>{e.layout(),e.render()},500),()=>{h(),e._contentChangeDisposable&&e._contentChangeDisposable.dispose()}};return C(()=>{t.current?.setupAutoValidation(l,r)},[r]),{editorRef:i,monacoRef:o,activeColorMode:p,handleEditorDidMount:M,handleEditorBeforeMount:e=>{}}}export{x as useMonacoEditor};
1
+ import{useEffect as m,useRef as t}from"react";import{useColorMode as M}from"./useColorMode";import{LanguageServerService as g}from"../service/languageServer";const C=(a={})=>{const{onValidationUpdate:r,onClick:l,hideWarnings:e}=a,i=t(null),u=t(null),o=t(null),s=M(),d=(n,c)=>{i.current=n,u.current=c,o.current||(o.current=new g),o.current.initialize(n,c);const f=o.current.setupAutoValidation(r,e);return n.onMouseDown(({target:p})=>{l?.(p.position)}),()=>{f()}};return m(()=>{o.current?.setupAutoValidation(r,e)},[e]),{editorRef:i,monacoRef:u,activeColorMode:s,handleEditorDidMount:d}};export{C as useMonacoEditor};
@@ -4,12 +4,14 @@ export interface LSPosition {
4
4
  character: number;
5
5
  }
6
6
  export interface DocumentProvider {
7
+ _lineOffsets: number[];
7
8
  getText: (options?: {
8
9
  start?: number;
9
10
  end?: number;
10
11
  }) => string;
11
12
  offsetAt: (position: LSPosition) => number;
12
- positionAt: (offset: number) => Monaco.IPosition;
13
+ positionAt: (offset: number) => LSPosition;
14
+ lineCount: number;
13
15
  }
14
16
  export interface ValidationCallback {
15
17
  (errors: Monaco.editor.IMarkerData[], value: string): void;
@@ -18,6 +20,7 @@ export interface ValidationCallback {
18
20
  * Service class to handle OpenAPI Language Server integration
19
21
  */
20
22
  export declare class LanguageServerService {
23
+ private languageServer;
21
24
  private monaco;
22
25
  private editor;
23
26
  constructor();
@@ -42,7 +45,7 @@ export declare class LanguageServerService {
42
45
  */
43
46
  private registerDefinitionProvider;
44
47
  /**
45
- * Validate OpenAPI content and provide diagnostics
48
+ * Get OpenAPI validation diagnostics
46
49
  */
47
50
  validateContent(onValidationUpdate?: ValidationCallback, hideWarnings?: boolean): Promise<void>;
48
51
  /**
@@ -0,0 +1,3 @@
1
+ import{OpenapiLanguageServer as d,languageServerConfig as g}from"@redocly/openapi-language-server";import{load as h}from"js-yaml";g.registerConfigFinder(async u=>(typeof globalThis.process>"u"?globalThis.process={cwd:()=>"/"}:typeof globalThis.process.cwd>"u"&&(globalThis.process.cwd=()=>"/"),"config"));class v{constructor(){this.monaco=null,this.editor=null,this.languageServer=new d}initialize(r,t){this.editor=r,this.monaco=t,globalThis.__dirname=".",this.registerDocumentsProvider(),this.languageServer.onDidConfigChange("config"),this.registerCompletionProvider(),this.registerDefinitionProvider()}registerDocumentsProvider(){g.registerDocumentsProvider({all(){return[]},get:r=>r==="config"||r==="file:///config"?{getText:()=>JSON.stringify({extends:["recommended"]},null,2)}:this.createDocumentProvider()})}createDocumentProvider(){const r=this.editor?.getModel();return{_lineOffsets:[],get lineCount(){return r?.getLineCount()||0},getText:({start:t=0,end:e=void 0}={})=>(this.editor?.getModel()?.getValue()||"").slice(t,e),offsetAt(t){const e=this.getText();this._lineOffsets=[0];for(let i=0;i<e.length;i++)e[i]===`
2
+ `&&this._lineOffsets.push(i+1);return r?r.getOffsetAt({lineNumber:t.line+1,column:t.character+1}):0},positionAt:t=>{if(!r)return{line:1,character:1};const e=r.getPositionAt(t);return{line:e.lineNumber,character:e.column}}}}registerCompletionProvider(){this.monaco&&this.monaco.languages.registerCompletionItemProvider("yaml",{triggerCharacters:[" ",`
3
+ `,"\\","/",'"',"'"],provideCompletionItems:async(r,t)=>{const e={uri:r.uri.toString()},i=m(t),l=await this.languageServer.onCompletion({textDocument:e,position:i});return l?{suggestions:l.map(n=>{let a=1;n.insertTextFormat===2&&(a=2);let s;return a===2&&(s=this.monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet),{label:n.label,kind:this.monaco.languages.CompletionItemKind[n.kind]||this.monaco.languages.CompletionItemKind.Text,insertText:n.insertText||n.label,insertTextFormat:a,sortText:n.sortText,insertTextRules:s,range:new this.monaco.Range(t.lineNumber,t.column,t.lineNumber,t.column)}})}:{suggestions:[]}}})}registerDefinitionProvider(){this.monaco&&this.monaco.languages.registerDefinitionProvider("yaml",{provideDefinition:async(r,t)=>{const e={uri:r.uri.toString()},i=m(t),l=await this.languageServer.onDefinition({textDocument:e,position:i});return l?(Array.isArray(l)?l:[l]).map(n=>({uri:this.monaco.Uri.parse(n.targetUri),originSelectionRange:new this.monaco.Range(n.originSelectionRange.start.line+1,n.originSelectionRange.start.character+1,n.originSelectionRange.end.line+1,n.originSelectionRange.end.character+1),range:new this.monaco.Range(n.targetSelectionRange.start.line+1,n.targetSelectionRange.start.character+1,n.targetSelectionRange.end.line+1,n.targetSelectionRange.end.character+1)})):[]}})}async validateContent(r,t){if(!this.editor||!this.monaco)return;const e=this.editor.getModel();if(!e)return;const i=e.getValue(),l={uri:e.uri.toString(),languageId:"yaml",version:e.getVersionId(),getText:()=>i,positionAt:a=>{const s=e.getPositionAt(a);return{line:s.lineNumber-1,character:s.column-1}},offsetAt:a=>e.getOffsetAt({lineNumber:a.line+1,column:a.character+1}),lineCount:e.getLineCount()},n={1:this.monaco.MarkerSeverity.Error,2:this.monaco.MarkerSeverity.Warning,3:this.monaco.MarkerSeverity.Info,4:this.monaco.MarkerSeverity.Hint};try{const s=(await this.languageServer.validateOpenAPI(l)).flatMap(o=>o.diagnostics.map(c=>({severity:n[c.severity]||this.monaco.MarkerSeverity.Error,startLineNumber:c.range.start.line+1,startColumn:c.range.start.character+1,endLineNumber:c.range.end.line+1,endColumn:c.range.end.character+1,message:c.message,source:""}))).filter(o=>t?o.severity!==this.monaco.MarkerSeverity.Warning:!0).sort((o,c)=>c.severity-o.severity);try{const o=h(i);i.trim()!==""&&(typeof o!="object"||o===null||(o.openapi===void 0||!o.openapi.match(/^3\.[0,1]\.\d+$/))&&(o.swagger===void 0||!o.swagger.match(/^2\.[0,1]\.\d+$/)))&&s.push({severity:8,message:"Not an OpenAPI or Swagger specification. Only OpenAPI 3.0.x and Swagger 2.0.x are supported. Rule: struct",startLineNumber:1,startColumn:1,endLineNumber:1,endColumn:1e3})}catch(o){s.push({severity:8,message:o.reason+" Rule: struct",startLineNumber:o.mark?.line||1,startColumn:0,endLineNumber:o.mark?.line||1,endColumn:1e3})}this.monaco.editor.setModelMarkers(e,"openapi-ls",s),r&&r(s,i)}catch(a){console.error("Error during validation:",a)}}setupAutoValidation(r,t){if(!this.editor)return()=>{};const e=()=>this.validateContent(r,t);e();const i=this.editor.onDidChangeModelContent(()=>{e()});return()=>i.dispose()}}function m(u){return{line:u.lineNumber-1,character:u.column-1}}export{v as LanguageServerService};
@@ -1 +1 @@
1
- export declare const defaultOpenapiTemplate = "openapi: 3.0.0\ninfo:\n title: My API\n version: 1.0.0\n description: A new API to be documented.\npaths:\n /example:\n get:\n summary: Example endpoint\n description: This is a sample endpoint.\n responses:\n '200':\n description: Successful response\n content:\n application/json:\n schema:\n type: object\n properties:\n message:\n type: string\n example: Hello World!\n";
1
+ export declare const defaultOpenapiTemplate = "openapi: 3.1.0\ninfo:\n title: Sample API\n version: 1.0.0\n contact:\n email: team@redocly.com\n description: |\n Welcome to the Resources API, a robust and efficient service for managing your data.\n ### Overview\n This API provides a standard set of RESTful endpoints to perform CRUD (Create, Read, Update, Delete) operations on resources. It is designed with standard conventions to be predictable and easy to use.\n ### Authentication\n Most endpoints are protected using the **OAuth2 Client Credentials** flow. The `/health` endpoint is public.\n `Authorization: Bearer <YOUR_ACCESS_TOKEN>`\n ### Errors\n The API uses standard HTTP status codes to indicate the success or failure of a request. In the event of an error, the response body will contain a `problem+json` object with details.\n For more information, see our [full developer documentation](https://docs.example.com).\nservers:\n - url: http://api.example.com/v1\ntags:\n - name: Health\n description: Operations to check the health of the service.\n - name: Resources\n description: Operations to manage resources.\nsecurity:\n - OAuth2AuthCode:\n - resources:read\n - resources:write\npaths:\n /health:\n get:\n tags:\n - Health\n summary: Check service health\n description: Provides a simple way to check if the API is up and running.\n operationId: getHealth\n security: [] # public\n responses:\n '200':\n description: Service is healthy.\n content:\n application/json:\n schema:\n type: object\n properties:\n status:\n type: string\n example: ok\n '503':\n description: Service unavailable.\n content:\n application/problem+json:\n schema:\n $ref: '#/components/schemas/ProblemJson'\n /resources:\n get:\n tags:\n - Resources\n summary: List all resources\n description: Retrieves a paginated list of all resources, sorted by creation date in descending order.\n operationId: listResources\n parameters:\n - $ref: '#/components/parameters/Limit'\n - $ref: '#/components/parameters/Cursor'\n responses:\n '200':\n description: A paginated list of resources.\n content:\n application/json:\n schema:\n type: object\n properties:\n pageInfo:\n $ref: '#/components/schemas/PageInfo'\n data:\n type: array\n items:\n $ref: '#/components/schemas/Resource'\n post:\n tags:\n - Resources\n summary: Create a new resource\n description: Creates a new resource. The server generates the ID and creation timestamp.\n operationId: createResource\n requestBody:\n required: true\n content:\n application/json:\n schema:\n $ref: '#/components/schemas/Resource'\n responses:\n '201':\n description: Resource created successfully.\n content:\n application/json:\n schema:\n $ref: '#/components/schemas/Resource'\n '400':\n description: Bad request.\n content:\n application/problem+json:\n schema:\n $ref: '#/components/schemas/ProblemJson'\n /resources/{resourceId}:\n parameters:\n - name: resourceId\n in: path\n required: true\n description: The ID of the resource.\n schema:\n type: string\n format: uuid\n get:\n tags:\n - Resources\n summary: Get a single resource\n operationId: getResourceById\n description: Retrieves the details of a specific resource by its unique ID.\n responses:\n '200':\n description: The requested resource.\n content:\n application/json:\n schema:\n $ref: '#/components/schemas/Resource'\n '404':\n description: Resource not found.\n content:\n application/problem+json:\n schema:\n $ref: '#/components/schemas/ProblemJson'\n delete:\n tags:\n - Resources\n summary: Delete a resource\n operationId: deleteResourceById\n description: Permanently deletes a resource. This action cannot be undone.\n responses:\n '204':\n description: Resource deleted successfully.\n '404':\n description: Resource not found.\n content:\n application/problem+json:\n schema:\n $ref: '#/components/schemas/ProblemJson'\n\ncomponents:\n securitySchemes:\n OAuth2AuthCode:\n type: oauth2\n description: OAuth2 Client Credentials Grant.\n flows:\n authorizationCode:\n x-usePkce: true\n tokenUrl: https://auth.example.com/oauth2/token\n authorizationUrl: https://auth.example.com/oauth2/authorize\n scopes:\n resources:read: Read access to resources\n resources:write: Write and delete access to resources\n parameters:\n Limit:\n name: limit\n in: query\n description: The number of items to return per page.\n schema:\n type: integer\n format: int32\n default: 20\n minimum: 1\n maximum: 100\n Cursor:\n name: cursor\n in: query\n description: An opaque cursor for fetching the next page of results.\n schema:\n type: string\n schemas:\n PageInfo:\n type: object\n properties:\n hasNextPage:\n type: boolean\n description: Indicates if there are more pages of results.\n endCursor:\n type: string\n description: The cursor to use to fetch the next page of results.\n required:\n - hasNextPage\n Resource:\n type: object\n properties:\n id:\n type: string\n format: uuid\n description: The unique identifier for the resource.\n example: 'a7b3c2d9-e4f5-4a6b-8c7d-1e2f3a4b5c6d'\n readOnly: true\n name:\n type: string\n description: The name of the resource.\n example: My New Widget\n createdAt:\n type: string\n format: date-time\n description: The timestamp when the resource was created.\n example: '2025-10-09T13:31:23Z'\n readOnly: true\n required:\n - name\n ProblemJson:\n type: object\n description: A problem details object as defined in RFC 9457.\n properties:\n type:\n type: string\n format: uri\n description: An absolute URI that identifies the problem type.\n default: 'about:blank'\n example: /errors/resource-not-found\n title:\n type: string\n description: A short, human-readable summary of the problem type.\n example: Resource not found\n status:\n type: integer\n format: int32\n description: The HTTP status code.\n example: 404\n detail:\n type: string\n description: A human-readable explanation specific to this occurrence.\n example: The resource with ID xyz was not found.\n instance:\n type: string\n format: uri-reference\n description: A URI reference that identifies the specific occurrence of the problem.\n example: /resources/xyz\n required:\n - title\n - status\n";
@@ -1,22 +1,241 @@
1
- const e=`openapi: 3.0.0
1
+ const e=`openapi: 3.1.0
2
2
  info:
3
- title: My API
3
+ title: Sample API
4
4
  version: 1.0.0
5
- description: A new API to be documented.
5
+ contact:
6
+ email: team@redocly.com
7
+ description: |
8
+ Welcome to the Resources API, a robust and efficient service for managing your data.
9
+ ### Overview
10
+ This API provides a standard set of RESTful endpoints to perform CRUD (Create, Read, Update, Delete) operations on resources. It is designed with standard conventions to be predictable and easy to use.
11
+ ### Authentication
12
+ Most endpoints are protected using the **OAuth2 Client Credentials** flow. The \`/health\` endpoint is public.
13
+ \`Authorization: Bearer <YOUR_ACCESS_TOKEN>\`
14
+ ### Errors
15
+ The API uses standard HTTP status codes to indicate the success or failure of a request. In the event of an error, the response body will contain a \`problem+json\` object with details.
16
+ For more information, see our [full developer documentation](https://docs.example.com).
17
+ servers:
18
+ - url: http://api.example.com/v1
19
+ tags:
20
+ - name: Health
21
+ description: Operations to check the health of the service.
22
+ - name: Resources
23
+ description: Operations to manage resources.
24
+ security:
25
+ - OAuth2AuthCode:
26
+ - resources:read
27
+ - resources:write
6
28
  paths:
7
- /example:
29
+ /health:
8
30
  get:
9
- summary: Example endpoint
10
- description: This is a sample endpoint.
31
+ tags:
32
+ - Health
33
+ summary: Check service health
34
+ description: Provides a simple way to check if the API is up and running.
35
+ operationId: getHealth
36
+ security: [] # public
11
37
  responses:
12
38
  '200':
13
- description: Successful response
39
+ description: Service is healthy.
14
40
  content:
15
41
  application/json:
16
42
  schema:
17
43
  type: object
18
44
  properties:
19
- message:
45
+ status:
20
46
  type: string
21
- example: Hello World!
47
+ example: ok
48
+ '503':
49
+ description: Service unavailable.
50
+ content:
51
+ application/problem+json:
52
+ schema:
53
+ $ref: '#/components/schemas/ProblemJson'
54
+ /resources:
55
+ get:
56
+ tags:
57
+ - Resources
58
+ summary: List all resources
59
+ description: Retrieves a paginated list of all resources, sorted by creation date in descending order.
60
+ operationId: listResources
61
+ parameters:
62
+ - $ref: '#/components/parameters/Limit'
63
+ - $ref: '#/components/parameters/Cursor'
64
+ responses:
65
+ '200':
66
+ description: A paginated list of resources.
67
+ content:
68
+ application/json:
69
+ schema:
70
+ type: object
71
+ properties:
72
+ pageInfo:
73
+ $ref: '#/components/schemas/PageInfo'
74
+ data:
75
+ type: array
76
+ items:
77
+ $ref: '#/components/schemas/Resource'
78
+ post:
79
+ tags:
80
+ - Resources
81
+ summary: Create a new resource
82
+ description: Creates a new resource. The server generates the ID and creation timestamp.
83
+ operationId: createResource
84
+ requestBody:
85
+ required: true
86
+ content:
87
+ application/json:
88
+ schema:
89
+ $ref: '#/components/schemas/Resource'
90
+ responses:
91
+ '201':
92
+ description: Resource created successfully.
93
+ content:
94
+ application/json:
95
+ schema:
96
+ $ref: '#/components/schemas/Resource'
97
+ '400':
98
+ description: Bad request.
99
+ content:
100
+ application/problem+json:
101
+ schema:
102
+ $ref: '#/components/schemas/ProblemJson'
103
+ /resources/{resourceId}:
104
+ parameters:
105
+ - name: resourceId
106
+ in: path
107
+ required: true
108
+ description: The ID of the resource.
109
+ schema:
110
+ type: string
111
+ format: uuid
112
+ get:
113
+ tags:
114
+ - Resources
115
+ summary: Get a single resource
116
+ operationId: getResourceById
117
+ description: Retrieves the details of a specific resource by its unique ID.
118
+ responses:
119
+ '200':
120
+ description: The requested resource.
121
+ content:
122
+ application/json:
123
+ schema:
124
+ $ref: '#/components/schemas/Resource'
125
+ '404':
126
+ description: Resource not found.
127
+ content:
128
+ application/problem+json:
129
+ schema:
130
+ $ref: '#/components/schemas/ProblemJson'
131
+ delete:
132
+ tags:
133
+ - Resources
134
+ summary: Delete a resource
135
+ operationId: deleteResourceById
136
+ description: Permanently deletes a resource. This action cannot be undone.
137
+ responses:
138
+ '204':
139
+ description: Resource deleted successfully.
140
+ '404':
141
+ description: Resource not found.
142
+ content:
143
+ application/problem+json:
144
+ schema:
145
+ $ref: '#/components/schemas/ProblemJson'
146
+
147
+ components:
148
+ securitySchemes:
149
+ OAuth2AuthCode:
150
+ type: oauth2
151
+ description: OAuth2 Client Credentials Grant.
152
+ flows:
153
+ authorizationCode:
154
+ x-usePkce: true
155
+ tokenUrl: https://auth.example.com/oauth2/token
156
+ authorizationUrl: https://auth.example.com/oauth2/authorize
157
+ scopes:
158
+ resources:read: Read access to resources
159
+ resources:write: Write and delete access to resources
160
+ parameters:
161
+ Limit:
162
+ name: limit
163
+ in: query
164
+ description: The number of items to return per page.
165
+ schema:
166
+ type: integer
167
+ format: int32
168
+ default: 20
169
+ minimum: 1
170
+ maximum: 100
171
+ Cursor:
172
+ name: cursor
173
+ in: query
174
+ description: An opaque cursor for fetching the next page of results.
175
+ schema:
176
+ type: string
177
+ schemas:
178
+ PageInfo:
179
+ type: object
180
+ properties:
181
+ hasNextPage:
182
+ type: boolean
183
+ description: Indicates if there are more pages of results.
184
+ endCursor:
185
+ type: string
186
+ description: The cursor to use to fetch the next page of results.
187
+ required:
188
+ - hasNextPage
189
+ Resource:
190
+ type: object
191
+ properties:
192
+ id:
193
+ type: string
194
+ format: uuid
195
+ description: The unique identifier for the resource.
196
+ example: 'a7b3c2d9-e4f5-4a6b-8c7d-1e2f3a4b5c6d'
197
+ readOnly: true
198
+ name:
199
+ type: string
200
+ description: The name of the resource.
201
+ example: My New Widget
202
+ createdAt:
203
+ type: string
204
+ format: date-time
205
+ description: The timestamp when the resource was created.
206
+ example: '2025-10-09T13:31:23Z'
207
+ readOnly: true
208
+ required:
209
+ - name
210
+ ProblemJson:
211
+ type: object
212
+ description: A problem details object as defined in RFC 9457.
213
+ properties:
214
+ type:
215
+ type: string
216
+ format: uri
217
+ description: An absolute URI that identifies the problem type.
218
+ default: 'about:blank'
219
+ example: /errors/resource-not-found
220
+ title:
221
+ type: string
222
+ description: A short, human-readable summary of the problem type.
223
+ example: Resource not found
224
+ status:
225
+ type: integer
226
+ format: int32
227
+ description: The HTTP status code.
228
+ example: 404
229
+ detail:
230
+ type: string
231
+ description: A human-readable explanation specific to this occurrence.
232
+ example: The resource with ID xyz was not found.
233
+ instance:
234
+ type: string
235
+ format: uri-reference
236
+ description: A URI reference that identifies the specific occurrence of the problem.
237
+ example: /resources/xyz
238
+ required:
239
+ - title
240
+ - status
22
241
  `;export{e as defaultOpenapiTemplate};
@@ -0,0 +1,2 @@
1
+ import * as React from 'react';
2
+ export default function Page(): React.JSX.Element;
@@ -0,0 +1,3 @@
1
+ import{useCommunicationManager as o}from"../hooks/useCommunicationManager";import r from"styled-components";import*as e from"react";import{RedoclyOpenAPIDocs as a,safeSlugify as s}from"@redocly/openapi-docs";function f(){const[t,i]=e.useState(null);return o({definition:t,safeSlugify:s}),e.useEffect(()=>{window.updateDefinition=n=>{i(n)},window.parent.onReady(window)},[t]),t?e.createElement(l,null,e.createElement(a,{store:{options:{routingBasePath:"/preview",disableRouter:!0,hideSidebar:!0,scrollYOffset:0,hideInfoMetadata:!0},definition:t}})):e.createElement("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh",fontFamily:"system-ui, -apple-system, sans-serif",color:"#666"}},"No API definition available")}const l=r.div`
2
+ --sidebar-width: 0px;
3
+ `;export{f as default};
@@ -1,7 +1,2 @@
1
- import React from 'react';
2
- interface PageProps {
3
- RedoclyOpenAPIDocs: any;
4
- safeSlugify: (value: string) => string;
5
- }
6
- export default function Page({ RedoclyOpenAPIDocs, safeSlugify }: PageProps): React.JSX.Element;
7
- export {};
1
+ import Page from './components/Page';
2
+ export default Page;
@@ -1 +1 @@
1
- import o from"react";import r from"./components/PreviewContent";function n({RedoclyOpenAPIDocs:e,safeSlugify:t}){return o.createElement(r,{RedoclyOpenAPIDocs:e,safeSlugify:t})}export{n as default};
1
+ import e from"./components/Page";var r=e;export{r as default};
@@ -1,10 +1,9 @@
1
1
  interface UseCommunicationManagerProps {
2
2
  definition: any;
3
- lastGoodDefinition: any;
4
3
  safeSlugify: (value: string) => string;
5
4
  }
6
- export declare const useCommunicationManager: ({ definition, lastGoodDefinition, safeSlugify }: UseCommunicationManagerProps) => {
5
+ export declare const useCommunicationManager: ({ definition, safeSlugify }: UseCommunicationManagerProps) => {
7
6
  scrollToPointer: (pointer: string) => void;
8
- scrollToOperationInEditor: (operationPath: string) => void;
7
+ scrollToOperationInEditor: (path: string, method?: string) => void;
9
8
  };
10
9
  export {};
@@ -1 +1 @@
1
- import{useEffect as l}from"react";import{extractOperationFromButton as y}from"../utils/html";const k=({definition:f,lastGoodDefinition:h,safeSlugify:d})=>{const s=e=>{const o=f||h;if(!o?.paths){console.warn("[EditorPreview] No definition or paths available");return}let r="",t="";if(e.startsWith("#/")){const i=e.slice(2).split("/");t=i[2]||"",r=(i[1]||"").replaceAll("~1","/")}else{const i=e.split("/"),w=i[1]||"";t=i[2]||"",r=w.replace(/^paths/,"").replaceAll("~1","/")}if(!r||!t){console.warn("[EditorPreview] Invalid pointer format:",e);return}const n=o.paths[r]?.[t];if(!n){console.warn("[EditorPreview] No operation found for",{path:r,verb:t,pointer:e});return}const g=n.tags?.[0],v=g?d(g)+"/":"";let a="";if(n?.operationId?a="/preview/"+v+d(n.operationId):a="/preview/"+v+"paths/"+d(r)+"/"+t.toLowerCase(),a&&a!==window.location.pathname){window.history.replaceState({},"",a);const i=t.toLowerCase(),w=r,E=()=>{const P=document.querySelectorAll('button[data-component-name="Button/Button"]');for(const c of P){const u=y(c);if(u&&u.path===w&&u.method.toLowerCase()===i)return c.click(),!0}return!1};let p=E();p||[0,100,300,800].forEach(c=>{setTimeout(()=>{p||(p=E())},c)})}else a||console.warn("[EditorPreview] could not compute url for pointer:",e)},m=e=>{window.parent.postMessage({type:"scroll-to-operation",operationPath:e,source:"preview"},"*")};return l(()=>{try{window.parent&&typeof window.parent.onReady=="function"?(window.parent.onReady(window),console.log("[EditorPreview] Successfully registered with parent window")):(console.warn("[EditorPreview] Parent onReady not available, retrying..."),setTimeout(()=>{window.parent&&typeof window.parent.onReady=="function"?(window.parent.onReady(window),console.log("[EditorPreview] Successfully registered with parent window (retry)")):console.error("[EditorPreview] Failed to register with parent window")},100))}catch(e){console.error("[EditorPreview] Error registering with parent:",e)}},[]),l(()=>(window.scrollToPointer=s,()=>{delete window.scrollToPointer}),[f,h]),l(()=>{const e=o=>{o.data?.type==="scroll-to-operation"&&o.data?.source==="editor"&&(console.log("[EditorPreview] Received scroll-to-operation message:",o.data.operationPath),s(o.data.operationPath))};return window.addEventListener("message",e),()=>{window.removeEventListener("message",e)}},[s]),l(()=>{const e=o=>{const t=o.target.closest("button");if(t){const n=y(t);n&&m(n.path)}};return document.addEventListener("click",e),()=>{document.removeEventListener("click",e)}},[]),{scrollToPointer:s,scrollToOperationInEditor:m}};export{k as useCommunicationManager};
1
+ import{useEffect as l}from"react";import{extractOperationFromButton as E}from"../utils/html";const L=({definition:f,safeSlugify:d})=>{const s=t=>{const e=f;if(!e?.paths){console.warn("[EditorPreview] No definition or paths available");return}let o="",n="";if(t.startsWith("#/")){const a=t.slice(2).split("/");n=a[2]||"",o=(a[1]||"").replaceAll("~1","/")}else{const a=t.split("/"),w=a[1]||"";n=a[2]||"",o=w.replace(/^paths/,"").replaceAll("~1","/")}if(!o||!n){console.warn("[EditorPreview] Invalid pointer format:",t);return}const r=e.paths[o]?.[n];if(!r){console.warn("[EditorPreview] No operation found for",{path:o,verb:n,pointer:t});return}const m=r.tags?.[0],v=m?d(m)+"/":"";let i="";if(r?.operationId?i="/preview/"+v+d(r.operationId):i="/preview/"+v+"paths/"+d(o)+"/"+n.toLowerCase(),i&&i!==window.location.pathname){window.history.replaceState({},"",i);const a=n.toLowerCase(),w=o,P=()=>{const g=document.querySelectorAll('button[data-component-name="Button/Button"]');for(const c of g){const u=E(c);if(u&&u.path===w&&u.method.toLowerCase()===a)return c.click(),!0}return!1};let p=P();p||[0,100,300,800].forEach(c=>{setTimeout(()=>{p||(p=P())},c)})}else i||console.warn("[EditorPreview] could not compute url for pointer:",t)},h=(t,e)=>{let o=t;e&&(o=`#/paths/${t.replace(/\//g,"~1")}/${e.toLowerCase()}`),window.parent.postMessage({type:"scroll-to-operation",operationPath:o,source:"preview"},"*")};return l(()=>{try{window.parent&&typeof window.parent.onReady=="function"?window.parent.onReady(window):(console.warn("[EditorPreview] Parent onReady not available, retrying..."),setTimeout(()=>{window.parent&&typeof window.parent.onReady=="function"?window.parent.onReady(window):console.error("[EditorPreview] Failed to register with parent window")},100))}catch(t){console.error("[EditorPreview] Error registering with parent:",t)}},[]),l(()=>(window.scrollToPointer=s,()=>{delete window.scrollToPointer}),[f]),l(()=>{const t=e=>{e.data?.type==="scroll-to-operation"&&e.data?.source==="editor"&&s(e.data.operationPath)};return window.addEventListener("message",t),()=>{window.removeEventListener("message",t)}},[s]),l(()=>{const t=e=>{const n=e.target.closest("button");if(n){const r=E(n);r&&h(r.path,r.method)}};return document.addEventListener("click",t),()=>{document.removeEventListener("click",t)}},[]),{scrollToPointer:s,scrollToOperationInEditor:h}};export{L as useCommunicationManager};
@@ -1 +1 @@
1
- import{useState as c,useRef as s,useEffect as a}from"react";const d=()=>{const[u,o]=c(null),r=s(null),i=s(null),f=e=>{try{const n={...e};return Array.isArray(n.servers)&&(n.servers=n.servers.filter(t=>t&&typeof t=="object").filter(t=>typeof t.url=="string"&&t.url.trim().length>0)),n}catch{return e}},l=e=>{if(e&&typeof e=="object"&&typeof e.openapi=="string"){const t=f(e);r.current=t,o(t)}else r.current?i.current!==r.current&&o(r.current):o(null);i.current=e};return a(()=>(window.updateDefinition=l,()=>{delete window.updateDefinition}),[]),{definition:u,lastGoodDefinition:r.current}};export{d as useDefinitionManager};
1
+ import{useState as i,useRef as l,useEffect as p}from"react";const y=()=>{const[f,o]=i(null),s=l(null),n=l(null),c=e=>{try{const r={...e};return Array.isArray(r.servers)&&(r.servers=r.servers.filter(t=>t&&typeof t=="object").filter(t=>typeof t.url=="string"&&t.url.trim().length>0)),r}catch{return e}},a=e=>{const r=e&&typeof e=="object"&&typeof e.openapi=="string",t=e&&typeof e=="object"&&typeof e.swagger=="string";if(r||t){const u=c(e);s.current=u,o(u)}else s.current?n.current!==s.current&&o(s.current):o(null);n.current=e};return p(()=>(window.updateDefinition=a,()=>{delete window.updateDefinition}),[]),{definition:f,lastGoodDefinition:s.current}};export{y as useDefinitionManager};
@@ -1,4 +1,4 @@
1
- import*as t from"react";import n from"styled-components";import{breakpoints as l}from"@redocly/theme/core/utils";import{Tooltip as P}from"@redocly/theme/components/Tooltip/Tooltip";import{Link as M}from"@redocly/theme/components/Link/Link";import{periodsList as S,seatIntervals as f,seatProPlanIntervals as k}from"../pricingData/data";import{Period as y,Plan as v,Product as g}from"../types/types";import{choosePeriod as T}from"../calculations/choosePeriod";import{plansList as L}from"../pricingData/data";import{PlanCard as z}from"./PlanCard";import{Switcher as O}from"../../calculator/components/Switcher";import{chooseProduct as N}from"../calculations/chooseProduct";import{ActiveCheckmark as A}from"../images/ActiveCheckmark";const D=(e,o,a,m)=>{let s=0;const p=!m||isNaN(m)||m<1?1:m;return o===v.PRO?a===y.YEAR?s=k[e][a]/12:s=k[e][a]:(o===v.ENTERPRISE&&(a===y.YEAR?s=f[e][a][f[e][a].findIndex(c=>p<=c.tierEnd&&p>=c.tierStart)].price/12:s=f[e][a][f[e][a].findIndex(c=>p<=c.tierEnd&&p>=c.tierStart)].price),s)},fe=({setCalculatorProperties:e,period:o,plan:a,amountSelectedProjects:m,onChange:s,onFocus:p,onBlur:c,seats:h,inputValue:b,calculatorProperties:r})=>{const E=[{name:g.REALM,subName:": All combined",gradient:["#1677FF","#08C7E0"]},{name:g.REDOC,color:"#1677FF",activeColor:"#E5F1FF",descriptionProperties:[{title:"OpenAPI",tooltip:"Render OpenAPI docs with the beauty and function of Redoc. Try it panel with Replay. Code samples generated automatically in a dozen languages."},{title:"GraphQL",tooltip:"Redoc renders GraphQL SDL files with a consistent design to OpenAPI."},{title:"AsyncAPI",tooltip:"AsyncAPI docs rendered natively\u2014just drop in your spec file."},{title:"SOAP",tooltip:"Redoc renders SOAP WSDL files with an extension. Functional but not beautiful. SOAP is outdated folks, do you really want us spending more time there?"},{title:"Mock servers",tooltip:"Mock servers are generated automatically for every OpenAPI and hosted at the same custom domain as your website."},{title:"Lint",tooltip:"Make sure API definitions are correct and enforce from a variety of rules or your own configurable rules."}]},{name:g.REVEL,color:"#735CFF",activeColor:"#EDEBFF",descriptionProperties:[{title:"Markdown docs",tooltip:"Render Markdown and Markdoc docs. You can also use our built-in Markdoc tags and create your own."},{title:"React pages",tooltip:"Render tsx and jsx files perfect for landing pages or other fancy pages. This actual web page is one of them."},{title:"Component ejections",tooltip:"Eject components (React code) to the file system in a folder where front end developers can wrap or tweak the components to meet your vision."},{title:"Localization",tooltip:"Translate your content and built-in website tokens."},{title:"Multi-product support",tooltip:"Segment your website by product, if you desire, and have separate configurations and content per product."}]},{name:g.REEF,color:"#A45CFF",activeColor:"#F1E5FF",descriptionProperties:[{title:"Catalog",linkTo:"/reef",underlined:!0,tooltip:"Catalog all the things, including your APIs. Filter by metadata."},{title:"API registry",tooltip:"This registry is automated. It recognizes APIs as they flow into the project and add to the registry automatically."},{title:"Scorecard for governance",tooltip:"Lint your APIs? This allows you to run multiple rulesets against each API. It collates the results into an interactive report some managers cannot live without."},{title:"API functions",tooltip:"Build custom backend logic (auth, data fetching, forms, and more) right inside your docs with API functions."},{title:"Markdown docs",tooltip:"Render Markdown and Markdoc docs. You can also use our built-in Markdoc tags and create your own."},{title:"Dynamic client registration",tooltip:"Want to allow customers to register a client/app, get API credentials, and request access to various API products or scopes?"}]}];return t.createElement(ie,null,t.createElement(j,{id:"selected-products"},E.map((i,x)=>t.createElement(Y,{key:x,isLastElement:E.length-1===x,isRealm:i.name===g.REALM},t.createElement(G,null,t.createElement("div",null,t.createElement(O,{height:"22px",transform:"translateX(18px)",width:"40px",right:"0",top:"0",activeColor:i.gradient?`linear-gradient(90deg, ${i.gradient[0]} 0%, ${i.gradient[1]} 100%)`:i.color,isActive:r.coreProducts.includes(i.name)||r.coreProducts.length===3,onClick:()=>N(e,i.name,r.coreProducts)})),t.createElement("p",null,i.name,i.subName&&t.createElement("span",null,i.subName))),i.descriptionProperties&&i.descriptionProperties.map((d,u)=>t.createElement(Q,{key:u},d.linkTo?t.createElement(B,{to:d.linkTo,underlined:d.underlined.toString()},t.createElement(I,null,t.createElement($,{isFirst:u===0,isActive:r.coreProducts.includes(i.name)||r.coreProducts.length===3,activeColor:i.color}),t.createElement(C,{isActive:r.coreProducts.includes(i.name)||r.coreProducts.length===3,activeColor:i.activeColor},r.coreProducts.includes(i.name)||r.coreProducts.length===3?t.createElement(A,{fill:i.color}):t.createElement(R,null))),d.title,t.createElement(w,{src:require("../images/external.svg")})):t.createElement(q,{underlined:d.underlined},t.createElement(I,null,t.createElement($,{isFirst:u===0,isActive:r.coreProducts.includes(i.name)||r.coreProducts.length===3,activeColor:i.color}),t.createElement(C,{isActive:r.coreProducts.includes(i.name)||r.coreProducts.length===3,activeColor:i.activeColor},r.coreProducts.includes(i.name)||r.coreProducts.length===3?t.createElement(A,{fill:i.color}):t.createElement(R,null))),t.createElement("p",null,d.title)),d.tooltip&&t.createElement(H,{tip:d.tooltip,width:"fit-content",children:t.createElement("img",{src:require("../images/tooltip.svg"),style:{maxWidth:"14px",maxHeight:"14px"}})})))))),t.createElement(te,null,t.createElement(ee,null,t.createElement(Z,null,t.createElement("p",null,"Seats"),t.createElement(K,null,t.createElement(J,{placeholder:"40",pattern:"\\d+(\\.\\d+)?",value:b!==void 0?b:h,onChange:s,onFocus:p,onBlur:c}),t.createElement(P,{tip:"Seats count for users who have the OWNER, MEMBER, or COMMITTER roles. Additional roles such as BILLING and VIEWER are users that do not count towards your seat limits.",children:t.createElement("img",{src:require("../images/tooltip.svg"),style:{maxWidth:"14px"}})}))),t.createElement(U,null,t.createElement(_,null,S.map(i=>t.createElement(X,{key:i,onClick:()=>T(e,i,a),selected:o===i},t.createElement(F,null,i,"ly")))),o===y.MONTH&&t.createElement(W,{src:require("../images/save-one-month-badge.svg")}))),t.createElement(V,null,L.map((i,x)=>t.createElement(z,{key:x,plan:i,period:o,price:D(m,i.name,o,h),isCustom:i.name===v.ENTERPRISE_PLUS||h>500})))))},W=n.img`
1
+ import*as t from"react";import n from"styled-components";import{breakpoints as l}from"@redocly/theme/core/utils";import{Tooltip as P}from"@redocly/theme/components/Tooltip/Tooltip";import{Link as M}from"@redocly/theme/components/Link/Link";import{periodsList as S,seatIntervals as f,seatProPlanIntervals as k}from"../pricingData/data";import{Period as y,Plan as v,Product as x}from"../types/types";import{choosePeriod as L}from"../calculations/choosePeriod";import{plansList as T}from"../pricingData/data";import{PlanCard as z}from"./PlanCard";import{Switcher as O}from"../../calculator/components/Switcher";import{chooseProduct as N}from"../calculations/chooseProduct";import{ActiveCheckmark as A}from"../images/ActiveCheckmark";const D=(e,o,a,m)=>{let s=0;const p=!m||isNaN(m)||m<1?1:m;return o===v.PRO?a===y.YEAR?s=k[e][a]/12:s=k[e][a]:(o===v.ENTERPRISE&&(a===y.YEAR?s=f[e][a][f[e][a].findIndex(c=>p<=c.tierEnd&&p>=c.tierStart)].price/12:s=f[e][a][f[e][a].findIndex(c=>p<=c.tierEnd&&p>=c.tierStart)].price),s)},fe=({setCalculatorProperties:e,period:o,plan:a,amountSelectedProjects:m,onChange:s,onFocus:p,onBlur:c,seats:h,inputValue:b,calculatorProperties:r})=>{const E=[{name:x.REALM,subName:": All combined",gradient:["#1677FF","#08C7E0"]},{name:x.REDOC,color:"#1677FF",activeColor:"#E5F1FF",descriptionProperties:[{title:"OpenAPI",tooltip:"Render OpenAPI docs with the beauty and function of Redoc. Try it panel with Replay. Code samples generated automatically in a dozen languages."},{title:"GraphQL",tooltip:"Redoc renders GraphQL SDL files with a consistent design to OpenAPI."},{title:"AsyncAPI",tooltip:"AsyncAPI docs rendered natively\u2014just drop in your spec file."},{title:"SOAP",tooltip:"Redoc renders SOAP WSDL files with an extension. Functional but not beautiful. SOAP is outdated folks, do you really want us spending more time there?"},{title:"Mock servers",tooltip:"Mock servers are generated automatically for every OpenAPI and hosted at the same custom domain as your website."},{title:"Lint",tooltip:"Make sure API definitions are correct and enforce from a variety of rules or your own configurable rules."}]},{name:x.REVEL,color:"#735CFF",activeColor:"#EDEBFF",descriptionProperties:[{title:"Markdown docs",tooltip:"Render Markdown and Markdoc docs. You can also use our built-in Markdoc tags and create your own."},{title:"React pages",tooltip:"Render tsx and jsx files perfect for landing pages or other fancy pages. This actual web page is one of them."},{title:"Component ejections",tooltip:"Eject components (React code) to the file system in a folder where front end developers can wrap or tweak the components to meet your vision."},{title:"Localization",tooltip:"Translate your content and built-in website tokens."},{title:"Multi-product support",tooltip:"Segment your website by product, if you desire, and have separate configurations and content per product."}]},{name:x.REEF,color:"#A45CFF",activeColor:"#F1E5FF",descriptionProperties:[{title:"Catalog",linkTo:"/reef",underlined:!0,tooltip:"Catalog all the things, including your APIs. Filter by metadata."},{title:"Scorecard for governance",tooltip:"Lint your APIs? This allows you to run multiple rulesets against each API. It collates the results into an interactive report some managers cannot live without."},{title:"API functions",tooltip:"Build custom backend logic (auth, data fetching, forms, and more) right inside your docs with API functions."},{title:"Markdown docs",tooltip:"Render Markdown and Markdoc docs. You can also use our built-in Markdoc tags and create your own."},{title:"Dynamic client registration",tooltip:"Want to allow customers to register a client/app, get API credentials, and request access to various API products or scopes?"}]}];return t.createElement(ie,null,t.createElement(q,{id:"selected-products"},E.map((i,g)=>t.createElement(Y,{key:g,isLastElement:E.length-1===g,isRealm:i.name===x.REALM},t.createElement(G,null,t.createElement("div",null,t.createElement(O,{height:"22px",transform:"translateX(18px)",width:"40px",right:"0",top:"0",activeColor:i.gradient?`linear-gradient(90deg, ${i.gradient[0]} 0%, ${i.gradient[1]} 100%)`:i.color,isActive:r.coreProducts.includes(i.name)||r.coreProducts.length===3,onClick:()=>N(e,i.name,r.coreProducts)})),t.createElement("p",null,i.name,i.subName&&t.createElement("span",null,i.subName))),i.descriptionProperties&&i.descriptionProperties.map((d,u)=>t.createElement(Q,{key:u},d.linkTo?t.createElement(B,{to:d.linkTo,underlined:d.underlined.toString()},t.createElement($,null,t.createElement(C,{isFirst:u===0,isActive:r.coreProducts.includes(i.name)||r.coreProducts.length===3,activeColor:i.color}),t.createElement(I,{isActive:r.coreProducts.includes(i.name)||r.coreProducts.length===3,activeColor:i.activeColor},r.coreProducts.includes(i.name)||r.coreProducts.length===3?t.createElement(A,{fill:i.color}):t.createElement(R,null))),d.title,t.createElement(w,{src:require("../images/external.svg")})):t.createElement(j,{underlined:d.underlined},t.createElement($,null,t.createElement(C,{isFirst:u===0,isActive:r.coreProducts.includes(i.name)||r.coreProducts.length===3,activeColor:i.color}),t.createElement(I,{isActive:r.coreProducts.includes(i.name)||r.coreProducts.length===3,activeColor:i.activeColor},r.coreProducts.includes(i.name)||r.coreProducts.length===3?t.createElement(A,{fill:i.color}):t.createElement(R,null))),t.createElement("p",null,d.title)),d.tooltip&&t.createElement(H,{tip:d.tooltip,width:"fit-content",children:t.createElement("img",{src:require("../images/tooltip.svg"),style:{maxWidth:"14px",maxHeight:"14px"}})})))))),t.createElement(te,null,t.createElement(ee,null,t.createElement(Z,null,t.createElement("p",null,"Seats"),t.createElement(K,null,t.createElement(J,{placeholder:"40",pattern:"\\d+(\\.\\d+)?",value:b!==void 0?b:h,onChange:s,onFocus:p,onBlur:c}),t.createElement(P,{tip:"Seats count for users who have the OWNER, MEMBER, or COMMITTER roles. Additional roles such as BILLING and VIEWER are users that do not count towards your seat limits.",children:t.createElement("img",{src:require("../images/tooltip.svg"),style:{maxWidth:"14px"}})}))),t.createElement(U,null,t.createElement(_,null,S.map(i=>t.createElement(X,{key:i,onClick:()=>L(e,i,a),selected:o===i},t.createElement(F,null,i,"ly")))),o===y.MONTH&&t.createElement(W,{src:require("../images/save-one-month-badge.svg")}))),t.createElement(V,null,T.map((i,g)=>t.createElement(z,{key:g,plan:i,period:o,price:D(m,i.name,o,h),isCustom:i.name===v.ENTERPRISE_PLUS||h>500})))))},W=n.img`
2
2
  position: absolute;
3
3
  right: 9px;
4
4
  margin-bottom: 5px;
@@ -14,14 +14,14 @@ import*as t from"react";import n from"styled-components";import{breakpoints as l
14
14
  margin-left: 8px;
15
15
  margin-top: 6px;
16
16
  align-self: center;
17
- `,I=n.div`
17
+ `,$=n.div`
18
18
  display: flex;
19
19
  flex-direction: column;
20
20
  align-items: center;
21
21
  justify-content: center;
22
22
  margin-right: 12px;
23
23
  height: 100%;
24
- `,$=n.div`
24
+ `,C=n.div`
25
25
  background: ${({isActive:e,activeColor:o})=>e?o:"var(--border-color-secondary)"};
26
26
  opacity: ${({isActive:e})=>e?"0.44":"1"};
27
27
  width: 1px;
@@ -29,7 +29,7 @@ import*as t from"react";import n from"styled-components";import{breakpoints as l
29
29
  margin-top: ${({isFirst:e})=>e&&"-4px"};
30
30
  min-height: 8px;
31
31
  max-height: 40px;
32
- `,C=n.div`
32
+ `,I=n.div`
33
33
  width: 40px;
34
34
  height: 20px;
35
35
  min-height: 20px;
@@ -64,7 +64,7 @@ import*as t from"react";import n from"styled-components";import{breakpoints as l
64
64
  display: block;
65
65
  }
66
66
  }
67
- `,j=n.div`
67
+ `,q=n.div`
68
68
  display: flex;
69
69
  flex-direction: column;
70
70
  width: 100%;
@@ -85,7 +85,7 @@ import*as t from"react";import n from"styled-components";import{breakpoints as l
85
85
  padding: 16px 24px 0 0;
86
86
  border-bottom: none;
87
87
  }
88
- `,q=n.div`
88
+ `,j=n.div`
89
89
  display: flex;
90
90
  align-items: flex-end;
91
91
  color: var(--text-color-secondary);
@@ -28,6 +28,7 @@ export declare const plansList: ({
28
28
  aiSearch?: undefined;
29
29
  typesense?: undefined;
30
30
  analytics?: undefined;
31
+ mcpServers?: undefined;
31
32
  residencyOptions?: undefined;
32
33
  salesAssistance?: undefined;
33
34
  forms?: undefined;
@@ -48,6 +49,7 @@ export declare const plansList: ({
48
49
  aiSearch: boolean;
49
50
  typesense: boolean;
50
51
  analytics: boolean;
52
+ mcpServers: boolean;
51
53
  reunite?: undefined;
52
54
  hasHosting?: undefined;
53
55
  projects?: undefined;
@@ -82,6 +84,7 @@ export declare const plansList: ({
82
84
  aiSearch?: undefined;
83
85
  typesense?: undefined;
84
86
  analytics?: undefined;
87
+ mcpServers?: undefined;
85
88
  };
86
89
  })[];
87
90
  export declare const periodsList: Period[];
@@ -1 +1 @@
1
- import{Period as r,Plan as o,Product as a,ProductBundle as i}from"../types/types";const l=[{title:a.REALM,description:"All combined (Redoc + Revel + Reef)",bgColor:"linear-gradient(90deg, rgba(22, 119, 255, 0.08) 0%, rgba(8, 199, 224, 0.08) 100%)",titleColor:"linear-gradient(90deg, #1677FF 0%, #08C7E0 100%)"},{title:a.REDOC,description:"Streamline API development with support for OpenAPI, GraphQL, and AsyncAPI, with mock servers and advanced linting.",bgColor:"#E5F1FF",titleColor:"#1677FF",features:["OpenAPI","GraphQL","AsyncAPI","Mock servers","Lint"]},{title:a.REVEL,description:"Showcase your APIs. Add guides. Localize. Add contextual docs. Landing pages. Multi-product support.",bgColor:"#EDEBFF",titleColor:"#735CFF",features:["Markdown docs","React pages","Component ejections","Localization","Multi-product support"]},{title:a.REEF,description:"API catalog is great for internal use cases. Scorecard for governance. API functions for custom integration capabilities.",bgColor:"#F1E5FF",titleColor:"#A45CFF",features:["API catalog","Scorecard for governance","API functions","Markdown docs","Dynamic client registration"]}],d=[{property:"reunite",name:"Reunite",tooltip:"Reunite is a full collaboration suite with Git integration, editor, visual reviews, and more."},{property:"hasHosting",name:"Custom domain hosting",tooltip:"Host your project on your custom domain"},{property:"projects",name:"Project",tooltip:"The number of projects included under this plan. Extra available for USD $49/month."},{property:"pages",name:"Pages",tooltip:"Total number of pages included across all your projects. Extra available for USD $0.12/month."},{property:"SSO",name:"SSO",tooltip:"Single Sign-On integration for streamlined and secure login"},{property:"guestSSO",name:"Guest SSO",tooltip:"Single Sign-On integration for external guest login"},{property:"RBAC",name:"RBAC",tooltip:"Role-Based Access Control to manage user permissions"},{property:"residencyOptions",name:"Data residency options",tooltip:"Choose where your data is stored to comply with regional regulations"},{property:"IPNetworkRestrictions",name:"IP network restrictions and more",tooltip:"Set IP restrictions to enhance security and control access"},{property:"salesAssistance",name:"Sales-assistance",tooltip:"Get support from our sales team for finding the best solutions for your organization"},{property:"forms",name:"Procurement forms",tooltip:"Access and submit necessary procurement documentation"},{property:"securityQuestionnaires",name:"Security questionnaires",tooltip:"Receive and complete security questionnaires to ensure compliance"},{property:"payByInvoice",name:"Pay-by-invoice / PO process",tooltip:"Flexible payment options including invoices and purchase orders"},{property:"reviews",name:"Legal reviews",tooltip:"Get assistance with legal reviews and compliance checks"},{property:"singleTenant",name:"Single-tenant hosting options",tooltip:"Opt for dedicated hosting for enhanced security and performance"},{property:"premiumSupport",name:"Premium support and professional services options",tooltip:"Access priority support and professional services for your projects"},{property:"remoteContent",name:"Remote content",tooltip:"Remote content allows you to automate sourcing content from a remote source. This is different from sourcing the entire project repository. Remote content can be sourced from Git repos, CICD push command, or a remote URL."},{property:"aiSearch",name:"AI search",tooltip:"Use AI to search your content"},{property:"typesense",name:"Typesense search",tooltip:"Use Typesense to search your content. Create additional search facets. Better relevance for search results."},{property:"apiFunctions",name:"API functions",tooltip:"Custom API endpoints for dynamic and server-side logic"},{property:"analytics",name:"Analytics",tooltip:"Get a clear picture of what users see and search for\u2014page views, search trends, and AI-powered query details"}],u=[{name:o.PRO,features:{reunite:!0,hasHosting:!0,projects:1,pages:100}},{name:o.ENTERPRISE,features:{pages:500,SSO:!0,guestSSO:!0,RBAC:!0,remoteContent:!0,aiSearch:!0,typesense:!0,analytics:!0}},{name:o.ENTERPRISE_PLUS,features:{residencyOptions:!0,salesAssistance:!0,forms:!0,securityQuestionnaires:!0,payByInvoice:!0,reviews:!0,singleTenant:!0,premiumSupport:!0}}],m=[r.MONTH,r.YEAR],n=[{tierStart:1,tierEnd:20},{tierStart:21,tierEnd:50},{tierStart:51,tierEnd:100},{tierStart:101,tierEnd:250},{tierStart:251,tierEnd:500},{tierStart:501,tierEnd:1e3},{tierStart:1001,tierEnd:1/0}],E={[i.ONE]:{[r.MONTH]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[24,21.6,19.2,16.8,15.6,14.4,13.2][t]})),[r.YEAR]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[264,237.6,211.2,184.8,171.6,158.4,145.2][t]}))},[i.TWO]:{[r.MONTH]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[48,43.2,38.4,33.6,31.2,28.8,26.4][t]})),[r.YEAR]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[528,475.2,422.4,369.6,343.2,316.8,290.4][t]}))},[i.REALM]:{[r.MONTH]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[66,59.4,52.8,46.2,42.9,39.6,36.3][t]})),[r.YEAR]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[708,653.4,580.8,508.2,471.9,435.6,399.3][t]}))}},S={[i.ONE]:{[r.MONTH]:10,[r.YEAR]:108},[i.TWO]:{[r.MONTH]:20,[r.YEAR]:216},[i.REALM]:{[r.MONTH]:28,[r.YEAR]:300}},s=[{tierStart:1,tierEnd:500},{tierStart:501,tierEnd:1/0}],p=[{tierStart:1,tierEnd:100},{tierStart:101,tierEnd:1/0}],y={[o.PRO]:{[r.MONTH]:p.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,.12][t]})),[r.YEAR]:p.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,1.44][t]}))},[o.ENTERPRISE]:{[r.MONTH]:s.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,.12][t]})),[r.YEAR]:s.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,1.44][t]}))},[o.ENTERPRISE_PLUS]:{[r.MONTH]:s.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,.12][t]})),[r.YEAR]:s.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,1.44][t]}))}},g=49,f={[o.PRO]:1,[o.ENTERPRISE]:1,[o.ENTERPRISE_PLUS]:1};export{d as featuresList,y as pageIntervals,m as periodsList,u as plansList,g as pricePerProject,l as productItems,E as seatIntervals,S as seatProPlanIntervals,f as startNumOfProjectPerPlan};
1
+ import{Period as r,Plan as o,Product as a,ProductBundle as i}from"../types/types";const l=[{title:a.REALM,description:"All combined (Redoc + Revel + Reef)",bgColor:"linear-gradient(90deg, rgba(22, 119, 255, 0.08) 0%, rgba(8, 199, 224, 0.08) 100%)",titleColor:"linear-gradient(90deg, #1677FF 0%, #08C7E0 100%)"},{title:a.REDOC,description:"Streamline API development with support for OpenAPI, GraphQL, and AsyncAPI, with mock servers and advanced linting.",bgColor:"#E5F1FF",titleColor:"#1677FF",features:["OpenAPI","GraphQL","AsyncAPI","Mock servers","Lint"]},{title:a.REVEL,description:"Showcase your APIs. Add guides. Localize. Add contextual docs. Landing pages. Multi-product support.",bgColor:"#EDEBFF",titleColor:"#735CFF",features:["Markdown docs","React pages","Component ejections","Localization","Multi-product support"]},{title:a.REEF,description:"API catalog is great for internal use cases. Scorecard for governance. API functions for custom integration capabilities.",bgColor:"#F1E5FF",titleColor:"#A45CFF",features:["API catalog","Scorecard for governance","API functions","Markdown docs","Dynamic client registration"]}],d=[{property:"reunite",name:"Reunite",tooltip:"Reunite is a full collaboration suite with Git integration, editor, visual reviews, and more."},{property:"hasHosting",name:"Custom domain hosting",tooltip:"Host your project on your custom domain"},{property:"projects",name:"Project",tooltip:"The number of projects included under this plan. Extra available for USD $49/month."},{property:"pages",name:"Pages",tooltip:"Total number of pages included across all your projects. Extra available for USD $0.12/month."},{property:"SSO",name:"SSO",tooltip:"Single Sign-On integration for streamlined and secure login"},{property:"guestSSO",name:"Guest SSO",tooltip:"Single Sign-On integration for external guest login"},{property:"RBAC",name:"RBAC",tooltip:"Role-Based Access Control to manage user permissions"},{property:"residencyOptions",name:"Data residency options",tooltip:"Choose where your data is stored to comply with regional regulations"},{property:"IPNetworkRestrictions",name:"IP network restrictions and more",tooltip:"Set IP restrictions to enhance security and control access"},{property:"salesAssistance",name:"Sales-assistance",tooltip:"Get support from our sales team for finding the best solutions for your organization"},{property:"forms",name:"Procurement forms",tooltip:"Access and submit necessary procurement documentation"},{property:"securityQuestionnaires",name:"Security questionnaires",tooltip:"Receive and complete security questionnaires to ensure compliance"},{property:"payByInvoice",name:"Pay-by-invoice / PO process",tooltip:"Flexible payment options including invoices and purchase orders"},{property:"reviews",name:"Legal reviews",tooltip:"Get assistance with legal reviews and compliance checks"},{property:"singleTenant",name:"Single-tenant hosting options",tooltip:"Opt for dedicated hosting for enhanced security and performance"},{property:"premiumSupport",name:"Premium support and professional services options",tooltip:"Access priority support and professional services for your projects"},{property:"remoteContent",name:"Remote content",tooltip:"Remote content allows you to automate sourcing content from a remote source. This is different from sourcing the entire project repository. Remote content can be sourced from Git repos, CICD push command, or a remote URL."},{property:"aiSearch",name:"AI search",tooltip:"Use AI to search your content"},{property:"typesense",name:"Typesense search",tooltip:"Use Typesense to search your content. Create additional search facets. Better relevance for search results."},{property:"apiFunctions",name:"API functions",tooltip:"Custom API endpoints for dynamic and server-side logic"},{property:"analytics",name:"Analytics",tooltip:"Get a clear picture of what users see and search for\u2014page views, search trends, and AI-powered query details"},{property:"mcpServers",name:"MCP Servers",tooltip:"Built-in MCP server lets AI agents query your API docs at runtime \u2014 contextual, authenticated, dynamic"}],u=[{name:o.PRO,features:{reunite:!0,hasHosting:!0,projects:1,pages:100}},{name:o.ENTERPRISE,features:{pages:500,SSO:!0,guestSSO:!0,RBAC:!0,remoteContent:!0,aiSearch:!0,typesense:!0,analytics:!0,mcpServers:!0}},{name:o.ENTERPRISE_PLUS,features:{residencyOptions:!0,salesAssistance:!0,forms:!0,securityQuestionnaires:!0,payByInvoice:!0,reviews:!0,singleTenant:!0,premiumSupport:!0}}],m=[r.MONTH,r.YEAR],n=[{tierStart:1,tierEnd:20},{tierStart:21,tierEnd:50},{tierStart:51,tierEnd:100},{tierStart:101,tierEnd:250},{tierStart:251,tierEnd:500},{tierStart:501,tierEnd:1e3},{tierStart:1001,tierEnd:1/0}],E={[i.ONE]:{[r.MONTH]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[24,21.6,19.2,16.8,15.6,14.4,13.2][t]})),[r.YEAR]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[264,237.6,211.2,184.8,171.6,158.4,145.2][t]}))},[i.TWO]:{[r.MONTH]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[48,43.2,38.4,33.6,31.2,28.8,26.4][t]})),[r.YEAR]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[528,475.2,422.4,369.6,343.2,316.8,290.4][t]}))},[i.REALM]:{[r.MONTH]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[66,59.4,52.8,46.2,42.9,39.6,36.3][t]})),[r.YEAR]:n.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[708,653.4,580.8,508.2,471.9,435.6,399.3][t]}))}},S={[i.ONE]:{[r.MONTH]:10,[r.YEAR]:108},[i.TWO]:{[r.MONTH]:20,[r.YEAR]:216},[i.REALM]:{[r.MONTH]:28,[r.YEAR]:300}},s=[{tierStart:1,tierEnd:500},{tierStart:501,tierEnd:1/0}],p=[{tierStart:1,tierEnd:100},{tierStart:101,tierEnd:1/0}],y={[o.PRO]:{[r.MONTH]:p.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,.12][t]})),[r.YEAR]:p.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,1.44][t]}))},[o.ENTERPRISE]:{[r.MONTH]:s.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,.12][t]})),[r.YEAR]:s.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,1.44][t]}))},[o.ENTERPRISE_PLUS]:{[r.MONTH]:s.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,.12][t]})),[r.YEAR]:s.map((e,t)=>({tierStart:e.tierStart,tierEnd:e.tierEnd,price:[0,1.44][t]}))}},g=49,f={[o.PRO]:1,[o.ENTERPRISE]:1,[o.ENTERPRISE_PLUS]:1};export{d as featuresList,y as pageIntervals,m as periodsList,u as plansList,g as pricePerProject,l as productItems,E as seatIntervals,S as seatProPlanIntervals,f as startNumOfProjectPerPlan};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/marketing-pages",
3
- "version": "0.1.26",
3
+ "version": "0.1.28",
4
4
  "keywords": [],
5
5
  "author": "",
6
6
  "license": "UNLICENSED",
@@ -26,6 +26,8 @@
26
26
  "@monaco-editor/react": "^4.7.0",
27
27
  "@rebilly/lead-source-tracker": "^2.18.13",
28
28
  "@redocly/json-to-json-schema": "^0.0.1",
29
+ "@redocly/openapi-docs": "^3.14.1",
30
+ "@redocly/openapi-language-server": "^0.6.9",
29
31
  "@uiw/react-codemirror": "^4.23.12",
30
32
  "dayjs": "^1.11.13",
31
33
  "framer-motion": "^12.10.5",
@@ -58,9 +60,9 @@
58
60
  },
59
61
  "devDependencies": {
60
62
  "@changesets/cli": "^2.29.5",
63
+ "@markdoc/markdoc": "0.5.1",
61
64
  "@redocly/config": "^0.24.0",
62
65
  "@redocly/theme": "^0.53.0",
63
- "@markdoc/markdoc": "0.5.1",
64
66
  "@shikijs/types": "3.4.0",
65
67
  "@types/js-yaml": "^4.0.9",
66
68
  "@types/node": "^22.15.17",
@@ -72,5 +74,13 @@
72
74
  "react-dom": "^18.3.1",
73
75
  "styled-components": ">=5.3.11",
74
76
  "typescript": "^5.8.3"
77
+ },
78
+ "overrides": {
79
+ "@redocly/openapi-docs": {
80
+ "@redocly/theme": "$@redocly/theme",
81
+ "@markdoc/markdoc": "$@markdoc/markdoc",
82
+ "react": "$react",
83
+ "react-dom": "$react-dom"
84
+ }
75
85
  }
76
86
  }
@@ -1,3 +0,0 @@
1
- import{load as v}from"js-yaml";class M{constructor(){this.monaco=null,this.editor=null}initialize(n,r){this.editor=n,this.monaco=r}registerDocumentsProvider(){}createDocumentProvider(){return{getText:({start:n=0,end:r=void 0}={})=>(this.editor?.getModel()?.getValue()||"").slice(n,r),offsetAt:n=>{const r=this.editor?.getModel();return r?r.getOffsetAt({lineNumber:n.line+1,column:n.character+1}):0},positionAt:n=>{const r=this.editor?.getModel();if(!r)return{lineNumber:1,column:1};const s=r.getPositionAt(n);return{lineNumber:s.lineNumber,column:s.column}}}}registerCompletionProvider(){this.monaco&&this.monaco.languages.registerCompletionItemProvider("yaml",{triggerCharacters:[" ",`
2
- `,"\\","/",'"',"'"],provideCompletionItems:async(n,r)=>({suggestions:[]})})}registerDefinitionProvider(){this.monaco&&this.monaco.languages.registerDefinitionProvider("yaml",{provideDefinition:async(n,r)=>[]})}async validateContent(n,r){if(!this.editor||!this.monaco)return;const s=this.editor.getModel();if(!s)return;const o=s.getValue(),C={uri:s.uri.toString(),languageId:"yaml",version:s.getVersionId(),getText:()=>o,positionAt:e=>{const c=s.getPositionAt(e);return{line:c.lineNumber-1,character:c.column-1}},offsetAt:e=>s.getOffsetAt({lineNumber:e.line+1,column:e.character+1}),lineCount:s.getLineCount()};try{let e=[];r&&(e=e.filter(t=>t.severity!==4));let c=null;try{v(o)}catch(t){c={severity:8,message:t.reason+" Rule: struct",startLineNumber:t.mark?.line||1,startColumn:0,endLineNumber:t.mark?.line||1,endColumn:1e3},e.push(c)}const u=o.split(`
3
- `);u.forEach((t,i)=>{const p=t.match(/^\s*type:\s*([^\s#]+)\s*(?:#.*)?$/);if(p){const l=L(u,i),m=l?new Set(["apiKey","http","oauth2","openIdConnect"]):new Set(["string","number","integer","boolean","array","object"]),a=p[1].trim();if(!m.has(a)){const g=t.indexOf("type:")+5+2;e.push({severity:8,message:l?`Invalid security scheme type '${a}'. Allowed: apiKey, http, oauth2, openIdConnect. Rule: struct`:`Invalid schema type '${a}'. Allowed: string, number, integer, boolean, array, object. Rule: struct`,startLineNumber:i+1,startColumn:Math.max(1,g),endLineNumber:i+1,endColumn:t.length+1,source:"Custom YAML Validator"})}}const f=t.match(/^(\s*)-(\s*)$/);if(f){const l={severity:8,message:"Empty list item detected. List items should have content. Rule: struct",startLineNumber:i+1,startColumn:f[1].length+1,endLineNumber:i+1,endColumn:t.length+1,source:"Custom YAML Validator"};e.push(l)}const d=t.match(/^(\s*)([^#\s][^:]*):\s*$/);if(d&&!t.trim().endsWith(":")){const l=d[2].trim().toLowerCase();if(["version","title","description","type","format","required","default","example"].some(a=>l.includes(a))){const a={severity:8,message:"Key without value detected. This key typically requires a value. Rule: struct",startLineNumber:i+1,startColumn:d[1].length+1,endLineNumber:i+1,endColumn:t.length+1,source:"Custom YAML Validator"};e.push(a)}}const y=t.match(/^(\s*)-(\s*)(.*)$/);if(y){const[l,m,a,g]=y;if(g.trim().length>0&&a.length!==1){const b={severity:8,message:a.length===0?"Missing space after dash in list item. There should be exactly one space between the dash and content. Rule: struct":"Too many spaces after dash in list item. There should be exactly one space between the dash and content. Rule: struct",startLineNumber:i+1,startColumn:m.length+2,endLineNumber:i+1,endColumn:t.length+1,source:"Custom YAML Validator"};e.push(b)}}}),this.monaco.editor.setModelMarkers(s,"openapi-ls",e),n&&n(e,o)}catch(e){console.error("Error during validation:",e)}}setupAutoValidation(n,r){if(!this.editor)return()=>{};const s=()=>this.validateContent(n,r);s();const o=this.editor.onDidChangeModelContent(()=>{s()});return()=>o.dispose()}}function L(h,n){const s=(h[n]||"").match(/^\s*/)?.[0].length||0;for(let o=n;o>=0;o--){const e=(h[o]??"").replace(/#.*$/,"");if(!e.trim())continue;const c=e.match(/^\s*/)?.[0].length||0,u=e.match(/^\s*([A-Za-z0-9_\-]+):\s*$/);if(u&&c<s&&u[1]==="components")return!1;if(u&&c<=s){const t=u[1];if(t==="securitySchemes")return!0;if(new Set(["schemas","responses","parameters","examples","requestBodies","headers","links","callbacks","pathItems"]).has(t))return!1}}return!1}export{M as LanguageServerService};
@@ -1,66 +0,0 @@
1
- import type * as Monaco from 'monaco-editor/esm/vs/editor/editor.api';
2
- export interface EditorPosition {
3
- line: number;
4
- column: number;
5
- }
6
- export interface EditorValidationUpdate {
7
- errors: Monaco.editor.IMarkerData[];
8
- value: string | undefined;
9
- }
10
- export interface PreviewDefinition {
11
- [key: string]: any;
12
- }
13
- export interface PreviewPanelProps {
14
- definition: PreviewDefinition | null;
15
- rawValue: string;
16
- hasRenderedOnce: boolean;
17
- hasStructErrors: boolean;
18
- onTemplateClick: () => void;
19
- onFileLoad: (content: string, fileName: string) => void;
20
- onExitFullPreview?: () => void;
21
- }
22
- export interface FileOperations {
23
- handleTemplateClick: () => void;
24
- handleFileLoad: (content: string, fileName: string) => void;
25
- handleDownloadYaml: (value: string) => void;
26
- handleDownloadJson: (value: string) => void;
27
- }
28
- export interface LayoutProps {
29
- isClient: boolean;
30
- }
31
- export interface EditorLayoutProps extends LayoutProps {
32
- value: string;
33
- onChange: (value: string | undefined) => void;
34
- onValidationUpdate: (errors: Monaco.editor.IMarkerData[], value: string | undefined) => void;
35
- hideWarnings: boolean;
36
- onHideWarningsChange: (hide: boolean) => void;
37
- isFullPreview: boolean;
38
- gotoPosition: EditorPosition | null;
39
- parsedErrors: Monaco.editor.IMarkerData[];
40
- onProblemClick: (line: number, column: number) => void;
41
- onFileLoad: (content: string, fileName: string) => void;
42
- onDownloadYaml: () => void;
43
- onDownloadJson: () => void;
44
- onToggleFullPreview: () => void;
45
- }
46
- export interface PreviewLayoutProps extends LayoutProps {
47
- definition: PreviewDefinition | null;
48
- rawValue: string;
49
- hasRenderedOnce: boolean;
50
- hasStructErrors: boolean;
51
- onTemplateClick: () => void;
52
- onFileLoad: (content: string, fileName: string) => void;
53
- }
54
- export interface FullPreviewLayoutProps extends PreviewLayoutProps {
55
- onExitFullPreview: () => void;
56
- }
57
- export interface ScrollToOperationMessage {
58
- type: 'scroll-to-operation';
59
- operationPath: string;
60
- source: 'editor' | 'preview';
61
- }
62
- export interface OperationPath {
63
- path: string;
64
- verb: string;
65
- pointer: string;
66
- }
File without changes
@@ -1,7 +0,0 @@
1
- import React from 'react';
2
- interface DocsRendererProps {
3
- RedoclyOpenAPIDocs: any;
4
- definition: any;
5
- }
6
- declare const DocsRenderer: React.FC<DocsRendererProps>;
7
- export default DocsRenderer;
@@ -1,4 +0,0 @@
1
- import e from"react";import i from"styled-components";const m=({RedoclyOpenAPIDocs:o,definition:t})=>{const r=e.useMemo(()=>({options:{routingBasePath:"/preview",disableRouter:!0,hideSidebar:!0},definition:t}),[t]);return e.createElement(n,null,e.createElement(o,{router:"memory",withCommonStyles:!0,store:r}))};var a=m;const n=i.div`
2
- height: 100vh;
3
- overflow: auto;
4
- `;export{a as default};
@@ -1,7 +0,0 @@
1
- import React from 'react';
2
- interface PreviewContentProps {
3
- RedoclyOpenAPIDocs: any;
4
- safeSlugify: (value: string) => string;
5
- }
6
- declare const PreviewContent: React.FC<PreviewContentProps>;
7
- export default PreviewContent;
@@ -1 +0,0 @@
1
- import t from"react";import{useThemeManager as i}from"../hooks/useThemeManager";import{useDefinitionManager as m}from"../hooks/useDefinitionManager";import{useCommunicationManager as a}from"../hooks/useCommunicationManager";import f from"./DocsRenderer";import c from"./EmptyState";const p=({RedoclyOpenAPIDocs:o,safeSlugify:r})=>{i();const{definition:e,lastGoodDefinition:n}=m();return a({definition:e,lastGoodDefinition:n,safeSlugify:r}),e?t.createElement(f,{RedoclyOpenAPIDocs:o,definition:e}):t.createElement(c,null)};var E=p;export{E as default};