@redocly/marketing-pages 0.1.20 → 0.1.21

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 (52) hide show
  1. package/dist/pages/editor/components/EditorPanel/EditorContent.d.ts +15 -0
  2. package/dist/pages/editor/components/EditorPanel/EditorContent.js +1 -0
  3. package/dist/pages/editor/components/EditorPanel.d.ts +1 -0
  4. package/dist/pages/editor/components/EditorPanel.js +1 -1
  5. package/dist/pages/editor/components/Layout/EditorLayout.d.ts +22 -0
  6. package/dist/pages/editor/components/Layout/EditorLayout.js +15 -0
  7. package/dist/pages/editor/components/Layout/FullPreviewLayout.d.ts +13 -0
  8. package/dist/pages/editor/components/Layout/FullPreviewLayout.js +5 -0
  9. package/dist/pages/editor/components/Layout/MainLayout.d.ts +28 -0
  10. package/dist/pages/editor/components/Layout/MainLayout.js +39 -0
  11. package/dist/pages/editor/components/Layout/PreviewLayout.d.ts +12 -0
  12. package/dist/pages/editor/components/Layout/PreviewLayout.js +7 -0
  13. package/dist/pages/editor/components/Page.js +1 -59
  14. package/dist/pages/editor/components/PreviewPanel/ErrorOverlay.d.ts +6 -0
  15. package/dist/pages/editor/components/PreviewPanel/ErrorOverlay.js +13 -0
  16. package/dist/pages/editor/components/PreviewPanel/IframeContainer.d.ts +8 -0
  17. package/dist/pages/editor/components/PreviewPanel/IframeContainer.js +8 -0
  18. package/dist/pages/editor/components/PreviewPanel/PreviewContent.d.ts +12 -0
  19. package/dist/pages/editor/components/PreviewPanel/PreviewContent.js +16 -0
  20. package/dist/pages/editor/components/PreviewPanel.d.ts +1 -0
  21. package/dist/pages/editor/components/PreviewPanel.js +1 -20
  22. package/dist/pages/editor/components/Toolbar.d.ts +2 -1
  23. package/dist/pages/editor/components/Toolbar.js +8 -8
  24. package/dist/pages/editor/constants/editorConfig.js +1 -1
  25. package/dist/pages/editor/hooks/useEditorCommunication.d.ts +11 -0
  26. package/dist/pages/editor/hooks/useEditorCommunication.js +2 -0
  27. package/dist/pages/editor/hooks/useFileOperations.js +1 -1
  28. package/dist/pages/editor/hooks/useIframeCommunication.d.ts +10 -0
  29. package/dist/pages/editor/hooks/useIframeCommunication.js +1 -0
  30. package/dist/pages/editor/hooks/useMonacoEditor.d.ts +2 -1
  31. package/dist/pages/editor/hooks/useMonacoEditor.js +2 -1
  32. package/dist/pages/editor/types/index.d.ts +66 -0
  33. package/dist/pages/editor/types/index.js +0 -0
  34. package/dist/pages/editor/utils/operationScrolling.d.ts +28 -0
  35. package/dist/pages/editor/utils/operationScrolling.js +3 -0
  36. package/dist/pages/editor-preview/components/DocsRenderer.d.ts +7 -0
  37. package/dist/pages/editor-preview/components/DocsRenderer.js +4 -0
  38. package/dist/pages/editor-preview/components/EmptyState.d.ts +3 -0
  39. package/dist/pages/editor-preview/components/EmptyState.js +1 -0
  40. package/dist/pages/editor-preview/components/PreviewContent.d.ts +7 -0
  41. package/dist/pages/editor-preview/components/PreviewContent.js +1 -0
  42. package/dist/pages/editor-preview/editor-preview.page.d.ts +3 -2
  43. package/dist/pages/editor-preview/editor-preview.page.js +1 -1
  44. package/dist/pages/editor-preview/hooks/useCommunicationManager.d.ts +10 -0
  45. package/dist/pages/editor-preview/hooks/useCommunicationManager.js +1 -0
  46. package/dist/pages/editor-preview/hooks/useDefinitionManager.d.ts +4 -0
  47. package/dist/pages/editor-preview/hooks/useDefinitionManager.js +1 -0
  48. package/dist/pages/editor-preview/hooks/useThemeManager.d.ts +3 -0
  49. package/dist/pages/editor-preview/hooks/useThemeManager.js +1 -0
  50. package/dist/pages/editor-preview/utils/html.d.ts +4 -0
  51. package/dist/pages/editor-preview/utils/html.js +1 -0
  52. package/package.json +1 -1
@@ -0,0 +1,15 @@
1
+ import * as React from 'react';
2
+ import type * as Monaco from 'monaco-editor/esm/vs/editor/editor.api';
3
+ interface EditorContentProps {
4
+ value: string;
5
+ onChange: (value: string | undefined) => void;
6
+ onValidationUpdate?: (errors: Monaco.editor.IMarkerData[], value: string | undefined) => void;
7
+ hideWarnings: boolean;
8
+ isFullPreview?: boolean;
9
+ gotoPosition?: {
10
+ line: number;
11
+ column: number;
12
+ } | null;
13
+ }
14
+ declare const EditorContent: React.FC<EditorContentProps>;
15
+ export default EditorContent;
@@ -0,0 +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};
@@ -5,6 +5,7 @@ interface EditorPanelProps {
5
5
  onChange: (value: string | undefined) => void;
6
6
  onValidationUpdate?: (errors: Monaco.editor.IMarkerData[], value: string | undefined) => void;
7
7
  hideWarnings: boolean;
8
+ isFullPreview?: boolean;
8
9
  gotoPosition?: {
9
10
  line: number;
10
11
  column: number;
@@ -1 +1 @@
1
- import*as t from"react";import f from"@monaco-editor/react";import{useMonacoEditor as s}from"../hooks/useMonacoEditor";import{DEFAULT_EDITOR_OPTIONS as d,EDITOR_LANGUAGE as p,EDITOR_THEMES as C}from"../constants/editorConfig";const I=({value:r,onChange:l,onValidationUpdate:o,hideWarnings:u,gotoPosition:e})=>{const[c,i]=t.useState(!1);t.useEffect(()=>i(!0),[]);const{activeColorMode:a,handleEditorDidMount:m,editorRef:n}=s({onValidationUpdate:o,hideWarnings:u,onClick:E=>{console.log("Editor clicked at position:",E)}});return t.useEffect(()=>{e&&n.current&&(n.current.revealPositionInCenter({lineNumber:e.line,column:e.column}),n.current.setPosition({lineNumber:e.line,column:e.column}),n.current.focus())},[e,n]),c?t.createElement(f,{language:p,theme:C[a],value:r,options:d,onChange:l,onMount:m}):null};var O=I;export{O as default};
1
+ import*as e from"react";import f from"./EditorPanel/EditorContent";const u=({value:t,onChange:o,onValidationUpdate:n,hideWarnings:r,isFullPreview:i,gotoPosition:a})=>{const[l,s]=e.useState(!1);return e.useEffect(()=>s(!0),[]),l?e.createElement(f,{value:t,onChange:o,onValidationUpdate:n,hideWarnings:r,isFullPreview:i,gotoPosition:a}):e.createElement("div",{style:{height:"100%",minHeight:"400px",backgroundColor:"var(--background-color, #fff)"}})};var d=u;export{d as default};
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import type * as Monaco from 'monaco-editor/esm/vs/editor/editor.api';
3
+ interface EditorLayoutProps {
4
+ value: string;
5
+ onChange: (value: string | undefined) => void;
6
+ onValidationUpdate: (errors: Monaco.editor.IMarkerData[], value: string | undefined) => void;
7
+ hideWarnings: boolean;
8
+ onHideWarningsChange: (hide: boolean) => void;
9
+ isFullPreview: boolean;
10
+ gotoPosition: {
11
+ line: number;
12
+ column: number;
13
+ } | null;
14
+ parsedErrors: Monaco.editor.IMarkerData[];
15
+ onProblemClick: (line: number, column: number) => void;
16
+ onFileLoad: (content: string, fileName: string) => void;
17
+ onDownloadYaml: () => void;
18
+ onDownloadJson: () => void;
19
+ onToggleFullPreview: () => void;
20
+ }
21
+ declare const EditorLayout: React.FC<EditorLayoutProps>;
22
+ export default EditorLayout;
@@ -0,0 +1,15 @@
1
+ import e from"react";import a from"styled-components";import{Panel as n,PanelGroup as z,PanelResizeHandle as h}from"react-resizable-panels";import y from"../EditorPanel";import{ProblemsPanel as k}from"../ProblemsPanel";import S from"../Toolbar";const w=({value:i,onChange:s,onValidationUpdate:d,hideWarnings:r,onHideWarningsChange:c,isFullPreview:m,gotoPosition:p,parsedErrors:u,onProblemClick:f,onFileLoad:P,onDownloadYaml:b,onDownloadJson:E,onToggleFullPreview:g})=>{const[l,t]=e.useState(!0),o=e.useRef(null),C=(v,x)=>{f(v,x),l&&o.current?.expand()};return e.createElement(R,{defaultSize:50,minSize:20},e.createElement(S,{onFileLoad:P,onDownloadYamlClick:b,onDownloadJsonClick:E,hideWarnings:r,onHideWarningsChange:c,onToggleFullPreview:g}),e.createElement(F,null,e.createElement(z,{direction:"vertical"},e.createElement(n,{defaultSize:95},e.createElement(y,{value:i,onChange:s,onValidationUpdate:d,hideWarnings:r,isFullPreview:m,gotoPosition:p})),e.createElement(h,{className:"resize-handle-horizontal",style:{display:l?"none":"block"}}),e.createElement(n,{ref:o,collapsible:!0,collapsedSize:5,defaultSize:5,minSize:20,onCollapse:t.bind(null,!0),onExpand:t.bind(null,!1)},e.createElement(k,{problems:u,onProblemClick:C,isCollapsed:l,onToggle:()=>{l?o.current?.expand():o.current?.collapse()}})))))};var J=w;const R=a(n)`
2
+ flex: 2;
3
+ display: flex;
4
+ flex-direction: column;
5
+ overflow: visible;
6
+
7
+ .monaco-editor {
8
+ --vscode-editor-background: var(--layer-color);
9
+ --vscode-editorGutter-background: var(--layer-color);
10
+ }
11
+ `,F=a.div`
12
+ flex: 1;
13
+ min-height: 0;
14
+ display: flex;
15
+ `;export{J as default};
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ interface FullPreviewLayoutProps {
3
+ definition: any | null;
4
+ rawValue: string;
5
+ hasRenderedOnce: boolean;
6
+ hasStructErrors: boolean;
7
+ onTemplateClick: () => void;
8
+ onFileLoad: (content: string, fileName: string) => void;
9
+ onExitFullPreview: () => void;
10
+ isClient: boolean;
11
+ }
12
+ declare const FullPreviewLayout: React.FC<FullPreviewLayoutProps>;
13
+ export default FullPreviewLayout;
@@ -0,0 +1,5 @@
1
+ import e from"react";import m from"styled-components";import u from"../PreviewPanel";const d=({definition:r,rawValue:t,hasRenderedOnce:l,hasStructErrors:i,onTemplateClick:a,onFileLoad:n,onExitFullPreview:o,isClient:c})=>e.createElement(v,null,c&&e.createElement(u,{definition:r,rawValue:t,hasRenderedOnce:l,hasStructErrors:i,onTemplateClick:a,onFileLoad:n,onExitFullPreview:o}));var p=d;const v=m.div`
2
+ display: flex;
3
+ flex-direction: column;
4
+ height: calc(100vh - var(--navbar-height));
5
+ `;export{p as default};
@@ -0,0 +1,28 @@
1
+ import React from 'react';
2
+ import type * as Monaco from 'monaco-editor/esm/vs/editor/editor.api';
3
+ interface MainLayoutProps {
4
+ value: string;
5
+ onChange: (value: string | undefined) => void;
6
+ onValidationUpdate: (errors: Monaco.editor.IMarkerData[], value: string | undefined) => void;
7
+ hideWarnings: boolean;
8
+ onHideWarningsChange: (hide: boolean) => void;
9
+ isFullPreview: boolean;
10
+ gotoPosition: {
11
+ line: number;
12
+ column: number;
13
+ } | null;
14
+ parsedErrors: Monaco.editor.IMarkerData[];
15
+ onProblemClick: (line: number, column: number) => void;
16
+ onFileLoad: (content: string, fileName: string) => void;
17
+ onDownloadYaml: () => void;
18
+ onDownloadJson: () => void;
19
+ onToggleFullPreview: () => void;
20
+ definition: any | null;
21
+ rawValue: string;
22
+ hasRenderedOnce: boolean;
23
+ hasStructErrors: boolean;
24
+ onTemplateClick: () => void;
25
+ isClient: boolean;
26
+ }
27
+ declare const MainLayout: React.FC<MainLayoutProps>;
28
+ export default MainLayout;
@@ -0,0 +1,39 @@
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`
2
+ display: flex;
3
+ flex-direction: column;
4
+ height: calc(100vh - var(--navbar-height));
5
+
6
+ background-color: var(--bg-color);
7
+ color: var(--text-color-primary);
8
+
9
+ [data-component-name='Layout/PageLayout']:has(&) + div + footer {
10
+ display: none;
11
+ }
12
+ `,L=e(P)`
13
+ display: flex;
14
+ flex-grow: 1;
15
+ height: 100%;
16
+ overflow: visible;
17
+
18
+ .resize-handle {
19
+ width: 8px;
20
+ background-color: var(--border-color-primary);
21
+ cursor: col-resize;
22
+ transition: background-color 0.2s ease;
23
+
24
+ &:hover {
25
+ background-color: var(--color-primary-variant);
26
+ }
27
+ }
28
+
29
+ .resize-handle-horizontal {
30
+ height: 8px;
31
+ background-color: var(--border-color-primary);
32
+ cursor: row-resize;
33
+ transition: background-color 0.2s ease;
34
+
35
+ &:hover {
36
+ background-color: var(--color-primary-variant);
37
+ }
38
+ }
39
+ `;export{V as default};
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ interface PreviewLayoutProps {
3
+ definition: any | null;
4
+ rawValue: string;
5
+ hasRenderedOnce: boolean;
6
+ hasStructErrors: boolean;
7
+ onTemplateClick: () => void;
8
+ onFileLoad: (content: string, fileName: string) => void;
9
+ isClient: boolean;
10
+ }
11
+ declare const PreviewLayout: React.FC<PreviewLayoutProps>;
12
+ export default PreviewLayout;
@@ -0,0 +1,7 @@
1
+ import e from"react";import p from"styled-components";import{Panel as d}from"react-resizable-panels";import m from"../PreviewPanel";const c=({definition:r,rawValue:o,hasRenderedOnce:t,hasStructErrors:i,onTemplateClick:a,onFileLoad:l,isClient:n})=>e.createElement(s,{defaultSize:50,minSize:20,collapsible:!0,collapsedSize:0},n&&e.createElement(m,{definition:r,rawValue:o,hasRenderedOnce:t,hasStructErrors:i,onTemplateClick:a,onFileLoad:l}));var P=c;const s=p(d)`
2
+ flex: 3;
3
+ position: relative;
4
+ border-left: 1px solid var(--border-color-primary);
5
+ --sidebar-width: 0px;
6
+ --panel-gap-horizontal: var(--spacing-md);
7
+ `;export{P as default};
@@ -1,59 +1 @@
1
- import r from"styled-components";import e from"react";import{Panel as t,PanelGroup as f,PanelResizeHandle as h}from"react-resizable-panels";import{useEditorState as L}from"../hooks/useEditorState";import{useOpenApiValidation as O}from"../hooks/useOpenApiValidation";import{useFileOperations as W}from"../hooks/useFileOperations";import H from"./EditorPanel";import{ProblemsPanel as N}from"./ProblemsPanel";import T from"./Toolbar";import G from"./PreviewPanel";function J(){const[v,g]=e.useState(!1);e.useEffect(()=>g(!0),[]);const{value:a,setValue:d,validatedValue:b,setValidatedValue:E,validationErrors:q,setValidationErrors:c,fileName:B,setFileName:P,parsedErrors:z,hasStructErrors:m,hideWarnings:p,setHideWarnings:x}=L(),{definition:y,hasRenderedOnce:C,setHasRenderedOnce:k}=O({validatedValue:b,hasStructErrors:m}),[w,S]=e.useState(null),[l,u]=e.useState(!0),n=e.useRef(null),o=W({setValue:d,setFileName:P,setHasRenderedOnce:k,setValidationErrors:c}),V=(i,s)=>{c(i),E(s)},R=(i,s)=>{S({line:i,column:s}),l&&n.current?.expand()},D=()=>o.handleDownloadYaml(a),F=()=>o.handleDownloadJson(a);return e.createElement(Y,null,e.createElement(U,{direction:"horizontal"},e.createElement(A,{defaultSize:50,minSize:20},e.createElement(T,{onFileLoad:o.handleFileLoad,onDownloadYamlClick:D,onDownloadJsonClick:F,hideWarnings:p,onHideWarningsChange:x}),e.createElement(I,null,e.createElement(f,{direction:"vertical"},e.createElement(t,{defaultSize:95},e.createElement(H,{value:a,onChange:d,onValidationUpdate:V,hideWarnings:p,gotoPosition:w})),e.createElement(h,{className:"resize-handle-horizontal",style:{display:l?"none":"block"}}),e.createElement(t,{ref:n,collapsible:!0,collapsedSize:5,defaultSize:5,minSize:20,onCollapse:u.bind(null,!0),onExpand:u.bind(null,!1)},e.createElement(N,{problems:z,onProblemClick:R,isCollapsed:l,onToggle:()=>{l?n.current?.expand():n.current?.collapse()}}))))),e.createElement(h,{className:"resize-handle"}),e.createElement(j,{defaultSize:50,minSize:20,collapsible:!0,collapsedSize:0},v&&e.createElement(G,{definition:y,rawValue:a,hasRenderedOnce:C,hasStructErrors:m,onTemplateClick:o.handleTemplateClick,onFileLoad:o.handleFileLoad}))))}const Y=r.div`
2
- display: flex;
3
- flex-direction: column;
4
- height: calc(100vh - var(--navbar-height));
5
-
6
- background-color: var(--bg-color);
7
- color: var(--text-color-primary);
8
-
9
- [data-component-name='Layout/PageLayout']:has(&) + div + footer {
10
- display: none;
11
- }
12
- `,U=r(f)`
13
- display: flex;
14
- flex-grow: 1;
15
- height: 100%;
16
- overflow: visible;
17
-
18
- .resize-handle {
19
- width: 8px;
20
- background-color: var(--border-color-primary);
21
- cursor: col-resize;
22
- transition: background-color 0.2s ease;
23
-
24
- &:hover {
25
- background-color: var(--color-primary-variant);
26
- }
27
- }
28
-
29
- .resize-handle-horizontal {
30
- height: 8px;
31
- background-color: var(--border-color-primary);
32
- cursor: row-resize;
33
- transition: background-color 0.2s ease;
34
-
35
- &:hover {
36
- background-color: var(--color-primary-variant);
37
- }
38
- }
39
- `,A=r(t)`
40
- flex: 2;
41
- display: flex;
42
- flex-direction: column;
43
- overflow: visible;
44
-
45
- .monaco-editor {
46
- --vscode-editor-background: var(--layer-color);
47
- --vscode-editorGutter-background: var(--layer-color);
48
- }
49
- `,I=r.div`
50
- flex: 1;
51
- min-height: 0;
52
- display: flex;
53
- `,j=r(t)`
54
- flex: 3;
55
- position: relative;
56
- border-left: 1px solid var(--border-color-primary);
57
- --sidebar-width: 0px;
58
- --panel-gap-horizontal: var(--spacing-md);
59
- `;export{J as default};
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};
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ interface ErrorOverlayProps {
3
+ hasStructErrors: boolean;
4
+ }
5
+ declare const ErrorOverlay: React.FC<ErrorOverlayProps>;
6
+ export default ErrorOverlay;
@@ -0,0 +1,13 @@
1
+ import r from"react";import t from"styled-components";const o=({hasStructErrors:e})=>e?r.createElement(l,null,"Preview is showing the last valid version. The current content has structural errors. Please check editor messages."):null;var s=o;const l=t.div`
2
+ position: absolute;
3
+ top: 0;
4
+ left: 0;
5
+ right: 0;
6
+ background-color: rgba(255, 235, 238, 0.95);
7
+ color: #5c2121;
8
+ padding: 8px 16px;
9
+ border-bottom: 1px solid #f5c6cb;
10
+ text-align: center;
11
+ font-size: 0.9em;
12
+ z-index: 10;
13
+ `;export{s as default};
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ interface IframeContainerProps {
3
+ definition: any | null;
4
+ onIframeReady: (iframeWindow: Window) => void;
5
+ onMessage: (event: MessageEvent) => void;
6
+ }
7
+ declare const IframeContainer: React.FC<IframeContainerProps>;
8
+ export default IframeContainer;
@@ -0,0 +1,8 @@
1
+ import o,{useRef as c,useEffect as s}from"react";import u from"styled-components";const f=({definition:t,onIframeReady:a,onMessage:p})=>{const l=c(null),r=c(null),[i,w]=o.useState(0);return s(()=>{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)},[]),s(()=>{const n=e=>{r.current=e,e.updateDefinition(t),a(e)};window.onReady=n},[t,a]),s(()=>{r.current&&t&&r.current.updateDefinition(t)},[t]),o.createElement(m,null,o.createElement(d,{key:i,ref:l,title:"API Documentation Preview",src:"/preview",onLoad:()=>{}}))};var v=f;const m=u.div`
2
+ height: 100%;
3
+ overflow: hidden;
4
+ `,d=u.iframe`
5
+ width: 100%;
6
+ height: 100%;
7
+ border: none;
8
+ `;export{v as default};
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ interface PreviewContentProps {
3
+ definition: any | null;
4
+ rawValue: string;
5
+ hasStructErrors: boolean;
6
+ onTemplateClick: () => void;
7
+ onFileLoad: (content: string, fileName: string) => void;
8
+ onExitFullPreview?: () => void;
9
+ onIframeReady: (iframeWindow: Window) => void;
10
+ }
11
+ declare const PreviewContent: React.FC<PreviewContentProps>;
12
+ export default PreviewContent;
@@ -0,0 +1,16 @@
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`
2
+ position: relative;
3
+ height: 100%;
4
+ `,g=n(s)`
5
+ position: absolute;
6
+ top: 12px;
7
+ left: 12px;
8
+ z-index: 30;
9
+ `,y=n.div`
10
+ display: flex;
11
+ align-items: center;
12
+ justify-content: center;
13
+ height: 100%;
14
+ font-size: 14px;
15
+ color: #666;
16
+ `;export{M as default};
@@ -6,6 +6,7 @@ interface PreviewPanelProps {
6
6
  hasStructErrors: boolean;
7
7
  onTemplateClick: () => void;
8
8
  onFileLoad: (content: string, fileName: string) => void;
9
+ onExitFullPreview?: () => void;
9
10
  }
10
11
  declare const PreviewPanel: React.FC<PreviewPanelProps>;
11
12
  export default PreviewPanel;
@@ -1,20 +1 @@
1
- import*as e from"react";import u from"styled-components";import{useEffect as a,useRef as i}from"react";import E from"./EmptyState";const R=u.div`
2
- position: absolute;
3
- top: 0;
4
- left: 0;
5
- right: 0;
6
- background-color: rgba(255, 235, 238, 0.95);
7
- color: #5c2121;
8
- padding: 8px 16px;
9
- border-bottom: 1px solid #f5c6cb;
10
- text-align: center;
11
- font-size: 0.9em;
12
- z-index: 10;
13
- `,b=u.iframe`
14
- width: 100%;
15
- height: 100%;
16
- border: none;
17
- `,I=({definition:o,rawValue:c,hasStructErrors:p,onTemplateClick:g,onFileLoad:y})=>{const d=i(null),r=o||d.current,h=i(null),n=i(null),[f,v]=e.useState(!1),[w,P]=e.useState(0),l=i(!1);a(()=>{const s=t=>{t.data?.type!=="scroll-sync"||t.data?.source==="preview"||!n.current||l.current||(l.current=!0,n.current.postMessage(t.data,"*"),setTimeout(()=>{l.current=!1},50))};return window.addEventListener("message",s),()=>window.removeEventListener("message",s)},[]),a(()=>{const s=t=>{n.current=t,t.updateDefinition(r),v(!0)};window.onReady=s},[r]),a(()=>{o&&(d.current=o)},[o]),a(()=>{n.current&&f&&n.current.updateDefinition(r)},[r,f]);const m=p&&e.createElement(R,null,"Preview is showing the last valid version. The current content has structural errors. Please check editor messages.")||null;return!c||typeof c!="string"||c.trim()===""?e.createElement(E,{onTemplateClick:g,onUploadClick:y}):r?e.createElement(e.Fragment,null,m,e.createElement(x,null,e.createElement(b,{key:w,ref:h,title:"API Documentation Preview",src:"/preview",onLoad:()=>{}}))):m||"Loading..."};var L=I;const x=u.div`
18
- height: 100%;
19
- overflow: hidden;
20
- `;export{L as default};
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};
@@ -5,6 +5,7 @@ interface ToolbarProps {
5
5
  onDownloadJsonClick: () => void;
6
6
  hideWarnings: boolean;
7
7
  onHideWarningsChange: (hide: boolean) => void;
8
+ onToggleFullPreview?: () => void;
8
9
  }
9
- export default function Toolbar({ hideWarnings, onHideWarningsChange, onDownloadYamlClick, onDownloadJsonClick, onFileLoad }: ToolbarProps): React.JSX.Element;
10
+ export default function Toolbar({ hideWarnings, onHideWarningsChange, onDownloadYamlClick, onDownloadJsonClick, onFileLoad, onToggleFullPreview }: ToolbarProps): React.JSX.Element;
10
11
  export {};
@@ -1,4 +1,4 @@
1
- import e,{useRef as v,useState as E}from"react";import o from"styled-components";import{Button as i}from"@redocly/theme/components/Button/Button";import{DownloadIcon as p}from"@redocly/theme/icons/DownloadIcon/DownloadIcon";import{ChevronDownIcon as k}from"@redocly/theme/icons/ChevronDownIcon/ChevronDownIcon";function C({hideWarnings:m,onHideWarningsChange:f,onDownloadYamlClick:c,onDownloadJsonClick:u,onFileLoad:g}){const d=v(null),[x,t]=E(!1),b=()=>{d.current?.click()},h=()=>t(n=>!n),w=n=>{const r=n.target.files?.[0];if(!r)return;const l=new FileReader;l.onload=a=>{const y=a.target?.result;g(y,r.name)},l.onerror=a=>{console.error("Failed to read file!",a)},l.readAsText(r),n.target.value=""};return e.createElement(D,null,e.createElement(I,null,e.createElement("input",{type:"checkbox",checked:m,onChange:n=>f(n.target.checked),id:"hide-warnings"}),"Hide warnings"),e.createElement(F,null,e.createElement(i,{variant:"text",icon:e.createElement(p,{style:{transform:"rotate(180deg)"}}),onClick:b,"aria-label":"Upload spec"}),e.createElement(A,{type:"file",ref:d,onChange:w,accept:".yaml,.yml,.json"}),e.createElement(R,null,e.createElement(i,{onClick:c,iconPosition:"left",icon:e.createElement(p,null)},"Download"),e.createElement(i,{icon:e.createElement(k,null),onClick:h,"aria-label":"Download options"}),x&&e.createElement(z,null,e.createElement(s,{onClick:()=>{c(),t(!1)}},"Download YAML"),e.createElement(s,{onClick:()=>{u(),t(!1)}},"Download JSON")))))}const D=o.div`
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`
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 v,useState as E}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
- `,I=o.label`
9
+ `,M=o.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
- `,F=o.div`
15
+ `,R=o.div`
16
16
  display: flex;
17
17
  align-items: center;
18
18
  gap: 8px;
19
19
  margin-left: auto; /* Push to far right */
20
- `,R=o.div`
20
+ `,A=o.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
- `,z=o.ul`
27
+ `,B=o.ul`
28
28
  position: absolute;
29
29
  right: 0;
30
30
  top: 100%;
@@ -38,13 +38,13 @@ import e,{useRef as v,useState as E}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
- `,s=o.li`
41
+ `,m=o.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
- `,A=o.input`
48
+ `,F=o.input`
49
49
  display: none;
50
- `;export{C as default};
50
+ `;export{I as default};
@@ -1 +1 @@
1
- const t={padding:{top:12,bottom:12},fontSize:14,tabSize:2,detectIndentation:!0,minimap:{enabled:!1},renderLineHighlight:"all",placeholder:"Drag your file here or start typing...",stickyScroll:{enabled:!0}},e="yaml",r={light:"light",dark:"vs-dark"};export{t as DEFAULT_EDITOR_OPTIONS,e as EDITOR_LANGUAGE,r as EDITOR_THEMES};
1
+ const e={padding:{top:12,bottom:12},fontSize:14,tabSize:2,detectIndentation:!0,minimap:{enabled:!1},renderLineHighlight:"all",placeholder:"Drag your file here or start typing...",stickyScroll:{enabled:!0},fixedOverflowWidgets:!0},t="yaml",r={light:"light",dark:"vs-dark"};export{e as DEFAULT_EDITOR_OPTIONS,t as EDITOR_LANGUAGE,r as EDITOR_THEMES};
@@ -0,0 +1,11 @@
1
+ import type * as Monaco from 'monaco-editor/esm/vs/editor/editor.api';
2
+ interface UseEditorCommunicationProps {
3
+ value: string;
4
+ isFullPreview: boolean;
5
+ editorRef: React.RefObject<Monaco.editor.IStandaloneCodeEditor | null>;
6
+ }
7
+ export declare const useEditorCommunication: ({ value, isFullPreview, editorRef }: UseEditorCommunicationProps) => {
8
+ scrollPreviewToOperation: (lineNumber: number) => void;
9
+ scrollToOperationInEditor: (incoming: string) => void;
10
+ };
11
+ export {};
@@ -0,0 +1,2 @@
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{dump as p,load as e}from"js-yaml";import{downloadFile as d}from"../utils/download";import{defaultOpenapiTemplate as m}from"../templates/defaultOpenapiTemplate";function L(s){const{setValue:a,setFileName:i,setHasRenderedOnce:r,setValidationErrors:l}=s;return{handleFileLoad:(n,o)=>{a(n),console.log(`Loaded file: ${o}`),i(o),r(!1),l([])},handleTemplateClick:()=>{a(m),console.log("Loaded default template."),r(!1),l([])},handleDownloadYaml:n=>{let o=n;try{if(n.trim().startsWith("{")){const t=JSON.parse(n);o=p(t)}else e(n),o=n}catch(t){try{e(n),o=n}catch(c){alert("Content is not valid JSON or YAML. Cannot convert to YAML for download."),console.error("Error preparing YAML for download:",t,c);return}}d(o,"openapi.yaml","application/x-yaml")},handleDownloadJson:n=>{try{const o=e(n);if(typeof o!="object"||o===null)throw new Error("Parsed content is not an object.");const t=JSON.stringify(o,null,2);d(t,"openapi.json","application/json")}catch(o){alert("Content is not valid YAML/JSON. Cannot convert to JSON for download."),console.error("Error preparing JSON for download:",o)}}}}export{L as useFileOperations};
1
+ import{dump as c,load as e}from"js-yaml";import{downloadFile as s}from"../utils/download";import{defaultOpenapiTemplate as p}from"../templates/defaultOpenapiTemplate";function C(i){const{setValue:a,setFileName:d,setHasRenderedOnce:l,setValidationErrors:r}=i;return{handleFileLoad:(o,n)=>{a(o),d(n),l(!1),r([])},handleTemplateClick:()=>{a(p),l(!1),r([])},handleDownloadYaml:o=>{let n=o;try{if(o.trim().startsWith("{")){const t=JSON.parse(o);n=c(t)}else e(o),n=o}catch{try{e(o),n=o}catch{alert("Content is not valid JSON or YAML. Cannot convert to YAML for download.");return}}s(n,"openapi.yaml","application/x-yaml")},handleDownloadJson:o=>{try{const n=e(o);if(typeof n!="object"||n===null)throw new Error("Parsed content is not an object.");const t=JSON.stringify(n,null,2);s(t,"openapi.json","application/json")}catch{alert("Content is not valid YAML/JSON. Cannot convert to JSON for download.")}}}}export{C as useFileOperations};
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ interface UseIframeCommunicationProps {
3
+ definition: any | null;
4
+ onIframeReady?: (iframeWindow: Window) => void;
5
+ }
6
+ export declare const useIframeCommunication: ({ definition, onIframeReady }: UseIframeCommunicationProps) => {
7
+ iframeWindowRef: React.MutableRefObject<Window | null>;
8
+ isIframeReady: boolean;
9
+ };
10
+ export {};
@@ -0,0 +1 @@
1
+ import{useRef as n,useEffect as a,useState as o}from"react";const p=({definition:e,onIframeReady:s})=>{const t=n(null),[r,c]=o(!1);return a(()=>{const f=u=>{t.current=u,u.updateDefinition(e),c(!0),s?.(u)};window.onReady=f},[e,s]),a(()=>{t.current&&r&&e&&t.current.updateDefinition(e)},[e,r]),{iframeWindowRef:t,isIframeReady:r}};export{p as useIframeCommunication};
@@ -8,5 +8,6 @@ export declare function useMonacoEditor({ onValidationUpdate, onClick, hideWarni
8
8
  editorRef: import("react").MutableRefObject<editor.IStandaloneCodeEditor | null>;
9
9
  monacoRef: import("react").MutableRefObject<null>;
10
10
  activeColorMode: string;
11
- handleEditorDidMount: (editor: editor.IStandaloneCodeEditor, monaco: any) => () => void;
11
+ handleEditorDidMount: (editor: editor.IStandaloneCodeEditor, monaco: any) => (() => void);
12
+ handleEditorBeforeMount: (monaco: any) => void;
12
13
  };
@@ -1 +1,2 @@
1
- import{useEffect as M,useRef as r}from"react";import{LanguageServerService as d}from"../services/languageServerService";import{useColorMode as v}from"./useColorMode";import{useThemeHooks as D}from"@redocly/theme/core/hooks";function w({onValidationUpdate:n,onClick:i,hideWarnings:e}){const u=r(null),c=r(null),o=r(null),{useGlobalData:s}=D(),R=s(),a=v(),f=(t,l)=>{u.current=t,c.current=l,o.current||(o.current=new d),o.current.initialize(t,l);const m=o.current.setupAutoValidation(n,e);return t.onMouseDown(({target:p})=>{i?.(p.position)}),()=>{m()}};return M(()=>{o.current?.setupAutoValidation(n,e)},[e]),{editorRef:u,monacoRef:c,activeColorMode:a,handleEditorDidMount:f}}export{w as useMonacoEditor};
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};
@@ -0,0 +1,66 @@
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
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Utility functions for handling operation scrolling between editor and preview
3
+ */
4
+ export interface OperationPosition {
5
+ lineNumber: number;
6
+ column: number;
7
+ }
8
+ export interface OperationPath {
9
+ path: string;
10
+ verb: string;
11
+ pointer: string;
12
+ }
13
+ /**
14
+ * Finds the operation path and verb at a given line number in the OpenAPI spec
15
+ */
16
+ export declare const findOperationAtLine: (value: string, lineNumber: number) => OperationPath | null;
17
+ /**
18
+ * Finds the line number for a given operation path in the editor
19
+ */
20
+ export declare const findOperationLineInEditor: (value: string, operationPath: string) => number | null;
21
+ /**
22
+ * Sends a scroll-to-operation message to the preview
23
+ */
24
+ export declare const sendScrollToPreview: (operationPointer: string) => void;
25
+ /**
26
+ * Checks if the current editor position is within an operation block
27
+ */
28
+ export declare const isPositionInOperationBlock: (currentLine: number, pathLineIndex: number, nextPathIndex: number) => boolean;
@@ -0,0 +1,3 @@
1
+ const b=(i,o)=>{const t=i.split(`
2
+ `),s=o-1,l=t[s];let r=-1,a="";for(let n=s;n>=0;n--){const p=t[n];if(/^\s*\/[^:]+:\s*$/.test(p)){r=n,a=p.trim().replace(/:\s*$/,"");break}if(/^\s*components:\s*$/.test(p)||/^\s*schemas:\s*$/.test(p))break}if(r===-1)return null;let c=t.length;for(let n=r+1;n<t.length;n++){if(/^\s*\/[^:]+:\s*$/.test(t[n])){c=n;break}if(/^\s*components:\s*$/.test(t[n])||/^\s*schemas:\s*$/.test(t[n])){c=n;break}}if(!(s>r&&s<c))return null;let d=-1,e="";for(let n=s;n>r;n--){const u=t[n].match(/^\s*(get|post|put|delete|patch):\s*$/i);if(u){e=(u[1]||"").toLowerCase(),d=n;break}}if(d===-1)return null;const f=`#/paths/${a.replace(/\//g,"~1")}/${e}`;return{path:a,verb:e,pointer:f}},g=(i,o)=>{const t=i.split(`
3
+ `);let s="",l="";if(o.startsWith("#/")){const e=o.slice(2).split("/");l=(e[2]||"").toLowerCase(),s=(e[1]||"").replaceAll("~1","/")}else o.startsWith("/")?s=o:s=`/${o}`;let r=-1;for(let e=0;e<t.length;e++)if(t[e].trim()===`${s}:`){r=e;break}if(r===-1){for(let e=0;e<t.length;e++)if(t[e].includes(s)){r=e;break}}if(r===-1)return null;let a=t.length;for(let e=r+1;e<t.length;e++)if(/^\s*\/[^:]+:\s*$/.test(t[e])){a=e;break}let c=-1;for(let e=r+1;e<a;e++){const h=t[e].match(/^\s*(get|post|put|delete|patch):\s*$/i);if(h){const f=(h[1]||"").toLowerCase();if(!l||l===f){c=e,l=f;break}}}return(c!==-1?c:r)+1},$=i=>{window.postMessage({type:"scroll-to-operation",operationPath:i,source:"editor"},"*")},x=(i,o,t)=>{const s=o+1,l=t;return i>s&&i<=l};export{b as findOperationAtLine,g as findOperationLineInEditor,x as isPositionInOperationBlock,$ as sendScrollToPreview};
@@ -0,0 +1,7 @@
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;
@@ -0,0 +1,4 @@
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};
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const EmptyState: React.FC;
3
+ export default EmptyState;
@@ -0,0 +1 @@
1
+ import e from"react";const 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");var a=t;export{a as default};
@@ -0,0 +1,7 @@
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;
@@ -0,0 +1 @@
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};
@@ -1,6 +1,7 @@
1
- import * as React from 'react';
1
+ import React from 'react';
2
2
  interface PageProps {
3
3
  RedoclyOpenAPIDocs: any;
4
+ safeSlugify: (value: string) => string;
4
5
  }
5
- export default function Page({ RedoclyOpenAPIDocs }: PageProps): React.JSX.Element;
6
+ export default function Page({ RedoclyOpenAPIDocs, safeSlugify }: PageProps): React.JSX.Element;
6
7
  export {};
@@ -1 +1 @@
1
- import*as n from"react";function h({RedoclyOpenAPIDocs:i}){const[o,e]=n.useState(null),l=n.useRef(null),c=n.useRef(!1),w=n.useRef(null);return n.useEffect(()=>{window.updateDefinition=r=>{if(r&&typeof r=="object"&&typeof r.openapi=="string"){const t=v(r);l.current=t,e(t)}else l.current?w.current!==l.current&&e(l.current):e(null);w.current=r},window.parent.onReady(window)},[]),n.useEffect(()=>{const r=()=>{if(c.current)return;const t=document.querySelector("article");if(!t)return;const a=window.innerHeight,f=t.scrollHeight,d=window.scrollY,s=f-a;if(s<=0)return;const p=Math.round(d/s*100);window.parent.postMessage({type:"scroll-sync",position:{absolute:d,relative:p},source:"preview"},"*")},u=t=>{if(t.data?.type!=="scroll-sync"||t.data?.source==="preview"||c.current)return;const a=document.querySelector("article");if(!a)return;const f=window.innerHeight,s=a.scrollHeight-f;if(s<=0)return;c.current=!0;const p=Math.round(t.data.position.relative/100*s);window.scrollTo({top:p,behavior:"smooth"}),setTimeout(()=>{c.current=!1},50)};return window.addEventListener("scroll",r),window.addEventListener("message",u),()=>{window.removeEventListener("scroll",r),window.removeEventListener("message",u)}},[]),o?n.createElement(i,{store:{options:{routingBasePath:"/preview",disableRouter:!0,hideSidebar:!0,scrollYOffset:0},definition:o}}):n.createElement("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh",fontFamily:"system-ui, -apple-system, sans-serif",color:"#666"}},"No API definition available")}function v(i){try{const o={...i};return Array.isArray(o.servers)&&(o.servers=o.servers.filter(e=>e&&typeof e=="object").filter(e=>typeof e.url=="string"&&e.url.trim().length>0)),o}catch{return i}}export{h as default};
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};
@@ -0,0 +1,10 @@
1
+ interface UseCommunicationManagerProps {
2
+ definition: any;
3
+ lastGoodDefinition: any;
4
+ safeSlugify: (value: string) => string;
5
+ }
6
+ export declare const useCommunicationManager: ({ definition, lastGoodDefinition, safeSlugify }: UseCommunicationManagerProps) => {
7
+ scrollToPointer: (pointer: string) => void;
8
+ scrollToOperationInEditor: (operationPath: string) => void;
9
+ };
10
+ export {};
@@ -0,0 +1 @@
1
+ import{useEffect as P}from"react";import{extractOperationFromButton as b}from"../utils/html";const k=({definition:w,lastGoodDefinition:f,safeSlugify:c})=>{const l=t=>{const o=w||f;if(!o?.paths){console.warn("[EditorPreview] No definition or paths available");return}let n="",e="";if(t.startsWith("#/")){const a=t.slice(2).split("/");e=a[2]||"",n=(a[1]||"").replaceAll("~1","/")}else{const a=t.split("/"),p=a[1]||"";e=a[2]||"",n=p.replace(/^paths/,"").replaceAll("~1","/")}if(!n||!e){console.warn("[EditorPreview] Invalid pointer format:",t);return}const r=o.paths[n]?.[e];if(!r){console.warn("[EditorPreview] No operation found for",{path:n,verb:e,pointer:t});return}const h=r.tags?.[0],v=h?c(h)+"/":"";let s="";if(r?.operationId?s="/preview/"+v+c(r.operationId):s="/preview/"+v+"paths/"+c(n)+"/"+e.toLowerCase(),s&&s!==window.location.pathname){window.history.replaceState({},"",s);const a=e.toLowerCase(),p=n,E=()=>{const g=document.querySelectorAll('button[data-component-name="Button/Button"]');for(const i of g){const u=b(i);if(u&&u.path===p&&u.method.toLowerCase()===a)return i.click(),!0}return!1};let d=E();d||[0,100,300,800].forEach(i=>{setTimeout(()=>{d||(d=E())},i)})}else s||console.warn("[EditorPreview] could not compute url for pointer:",t)},m=t=>{window.parent.postMessage({type:"scroll-to-operation",operationPath:t,source:"preview"},"*")};return P(()=>{window.scrollToPointer=l;const t=o=>{o.data?.type==="scroll-to-operation"&&o.data?.source==="editor"&&l(o.data.operationPath)};return window.addEventListener("message",t),window.parent.onReady(window),()=>{window.removeEventListener("message",t),delete window.scrollToPointer}},[w,f]),P(()=>{const t=o=>{const e=o.target.closest("button");if(e){const r=b(e);r&&m(r.path)}};return document.addEventListener("click",t),()=>{document.removeEventListener("click",t)}},[]),{scrollToPointer:l,scrollToOperationInEditor:m}};export{k as useCommunicationManager};
@@ -0,0 +1,4 @@
1
+ export declare const useDefinitionManager: () => {
2
+ definition: any;
3
+ lastGoodDefinition: any;
4
+ };
@@ -0,0 +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};
@@ -0,0 +1,3 @@
1
+ export declare const useThemeManager: () => {
2
+ preservedTheme: string | null;
3
+ };
@@ -0,0 +1 @@
1
+ import{useEffect as a,useRef as i,useCallback as l}from"react";const d="manual",w=()=>{const e=i(null),n=l(r=>r.split(" ").filter(Boolean).find(t=>t==="light"||t==="dark")||"light",[]),u=l(()=>{try{return n(window.parent.document.documentElement.className)}catch{return"light"}},[n]);return a(()=>{const r=window.useColorSwitcher,c=(()=>{const t=n(document.documentElement.className);return t!=="light"?t:u()})();e.current=c,document.documentElement.className=c,window.useColorSwitcher=()=>({isSwitcherHidden:!0,initActiveColorMode:()=>{e.current&&(document.documentElement.className=e.current)},activeColorMode:e.current||"light"});const o=new MutationObserver(()=>{const t=document.documentElement.className,m=t.includes(d),s=n(t);if(m){e.current=s,document.documentElement.className=s;return}e.current&&s!==e.current&&(document.documentElement.className=e.current)});return o.observe(document.documentElement,{attributes:!0,attributeFilter:["class"]}),()=>{o.disconnect(),r&&(window.useColorSwitcher=r)}},[u,n]),{preservedTheme:e.current}};export{w as useThemeManager};
@@ -0,0 +1,4 @@
1
+ export declare const extractOperationFromButton: (buttonElement: HTMLButtonElement) => {
2
+ path: string;
3
+ method: string;
4
+ } | null;
@@ -0,0 +1 @@
1
+ const d=e=>{try{const n=e.textContent||"",a=n.match(/\b(get|post|put|delete|patch|head|options)\b/i),t=a?a[1].toLowerCase():"",r=n.match(/\/([a-zA-Z0-9\-_\/\{\}]+)/),o=r?r[0]:"",c=e.getAttribute("data-component-name"),h=e.getAttribute("data-operation"),u=e.querySelector('[data-component-name*="Tag"]')!==null,p=/\/[a-zA-Z0-9\-_\/\{\}]+/.test(n),s=/\b(get|post|put|delete|patch|head|options)\b/i.test(n);return t&&o?{path:o,method:t}:u&&p&&(t||s)?{path:o||"unknown",method:t||"unknown"}:h?{path:h,method:t||"unknown"}:c&&c.includes("Button")&&(t||o)?{path:o||"unknown",method:t||"unknown"}:s&&p?{path:o||"unknown",method:t||"unknown"}:null}catch(n){return console.error("Error extracting operation from button:",n),null}};export{d as extractOperationFromButton};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/marketing-pages",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "keywords": [],
5
5
  "author": "",
6
6
  "license": "UNLICENSED",