@burdenoff/microfe-vibecontrols 2026.601.21 → 2026.601.23
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.
- package/dist/components/actions/ActionCard.js +77 -66
- package/dist/components/actions/ActionCard.js.map +1 -1
- package/dist/components/ai/AIContextsTab.js +186 -173
- package/dist/components/ai/AIContextsTab.js.map +1 -1
- package/dist/components/ai/AITemplatesTab.js +135 -125
- package/dist/components/ai/AITemplatesTab.js.map +1 -1
- package/dist/components/ai/InstructionFilesManager.js +151 -137
- package/dist/components/ai/InstructionFilesManager.js.map +1 -1
- package/dist/components/docs/DocsEditPanel.js +17 -16
- package/dist/components/docs/DocsEditPanel.js.map +1 -1
- package/dist/components/docs/DocsPreviewPanel.js +25 -24
- package/dist/components/docs/DocsPreviewPanel.js.map +1 -1
- package/dist/components/docs/DocsTabPanel.js +110 -94
- package/dist/components/docs/DocsTabPanel.js.map +1 -1
- package/dist/components/notes/NotesTabPanel.js +8 -8
- package/dist/components/scorecard/ScorecardPanel.js +271 -257
- package/dist/components/scorecard/ScorecardPanel.js.map +1 -1
- package/dist/components/sharing/EntityShareButton.js +58 -0
- package/dist/components/sharing/EntityShareButton.js.map +1 -0
- package/dist/components/sharing/entityShareOps.js +603 -0
- package/dist/components/sharing/entityShareOps.js.map +1 -0
- package/dist/components/sharing/index.js +3 -0
- package/dist/components/sharing/shareRegistry.js +37 -12
- package/dist/components/sharing/shareRegistry.js.map +1 -1
- package/dist/components/sharing/useEntityShareController.js +88 -0
- package/dist/components/sharing/useEntityShareController.js.map +1 -0
- package/dist/constants/permissions.js +11 -0
- package/dist/constants/permissions.js.map +1 -1
- package/dist/pages/ActionsPage.js +162 -162
- package/dist/pages/ActionsPage.js.map +1 -1
- package/dist/pages/CatalogDetailPage.js +264 -250
- package/dist/pages/CatalogDetailPage.js.map +1 -1
- package/dist/pages/ComponentDetailPage.js +124 -113
- package/dist/pages/ComponentDetailPage.js.map +1 -1
- package/dist/pages/TargetDetailsPage.js +139 -126
- package/dist/pages/TargetDetailsPage.js.map +1 -1
- package/dist/pages/TemplateDetailPage.js +78 -67
- package/dist/pages/TemplateDetailPage.js.map +1 -1
- package/dist/pages/VibeDeckPage.js +1 -1
- package/dist/pages/VibeDetailsPage.js +484 -484
- package/dist/pages/VibeDetailsPage.js.map +1 -1
- package/dist/pages/tunnels/TunnelDetailsPage.js +91 -77
- package/dist/pages/tunnels/TunnelDetailsPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -8,15 +8,15 @@ import { useEffect as o, useState as s } from "react";
|
|
|
8
8
|
import { ArrowLeft as c, History as l, RefreshCw as u, Settings as d, Trash2 as f } from "lucide-react";
|
|
9
9
|
import { jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
10
10
|
//#region src/components/docs/DocsEditPanel.tsx
|
|
11
|
-
function h({ site: h, pages: g, onBack: _, onSavePage: v, onAddPage: y, pageAdding: b, onDeletePage: x, onCompile: S, onSaveSettings: C, onRollback: w, onDeleteSite: T, rollingBack: E, compileRevision: D, onPollRevision: O, compiling: k }) {
|
|
12
|
-
let
|
|
11
|
+
function h({ site: h, pages: g, onBack: _, onSavePage: v, onAddPage: y, pageAdding: b, onDeletePage: x, onCompile: S, onSaveSettings: C, onRollback: w, onDeleteSite: T, rollingBack: E, compileRevision: D, onPollRevision: O, compiling: k, shareSlot: A }) {
|
|
12
|
+
let j = e(), [M, N] = s(g[0]?.id || null), [P, F] = s(!1), [I, L] = s(!1), R = g.find((e) => e.id === M) || null;
|
|
13
13
|
return o(() => {
|
|
14
14
|
if (g.length === 0) {
|
|
15
|
-
|
|
15
|
+
M && N(null);
|
|
16
16
|
return;
|
|
17
17
|
}
|
|
18
|
-
(!
|
|
19
|
-
}, [g,
|
|
18
|
+
(!M || !g.some((e) => e.id === M)) && N(g[0].id);
|
|
19
|
+
}, [g, M]), /* @__PURE__ */ m("div", {
|
|
20
20
|
className: "flex flex-col h-full",
|
|
21
21
|
style: { minHeight: "calc(100vh - 380px)" },
|
|
22
22
|
children: [
|
|
@@ -29,7 +29,7 @@ function h({ site: h, pages: g, onBack: _, onSavePage: v, onAddPage: y, pageAddi
|
|
|
29
29
|
type: "button",
|
|
30
30
|
onClick: _,
|
|
31
31
|
className: "flex items-center gap-1.5 text-sm text-text-secondary hover:text-text-primary transition-colors",
|
|
32
|
-
children: [/* @__PURE__ */ p(c, { className: "size-4" }),
|
|
32
|
+
children: [/* @__PURE__ */ p(c, { className: "size-4" }), j("vibecontrols.docs.edit.preview", "Preview")]
|
|
33
33
|
}),
|
|
34
34
|
/* @__PURE__ */ p("span", {
|
|
35
35
|
className: "text-text-muted",
|
|
@@ -43,6 +43,7 @@ function h({ site: h, pages: g, onBack: _, onSavePage: v, onAddPage: y, pageAddi
|
|
|
43
43
|
}), /* @__PURE__ */ m("div", {
|
|
44
44
|
className: "flex items-center gap-2",
|
|
45
45
|
children: [
|
|
46
|
+
A,
|
|
46
47
|
/* @__PURE__ */ p("div", {
|
|
47
48
|
className: "relative",
|
|
48
49
|
children: /* @__PURE__ */ p(t, {
|
|
@@ -55,21 +56,21 @@ function h({ site: h, pages: g, onBack: _, onSavePage: v, onAddPage: y, pageAddi
|
|
|
55
56
|
onClick: S,
|
|
56
57
|
disabled: k,
|
|
57
58
|
className: "flex items-center gap-1.5 px-3 py-1.5 text-sm bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50",
|
|
58
|
-
children: [/* @__PURE__ */ p(u, { className: `size-3.5 ${k ? "animate-spin" : ""}` }),
|
|
59
|
+
children: [/* @__PURE__ */ p(u, { className: `size-3.5 ${k ? "animate-spin" : ""}` }), j("vibecontrols.docs.edit.compile", "Compile")]
|
|
59
60
|
}),
|
|
60
61
|
/* @__PURE__ */ p("button", {
|
|
61
62
|
type: "button",
|
|
62
63
|
onClick: () => {
|
|
63
|
-
|
|
64
|
+
L((e) => !e), F(!1);
|
|
64
65
|
},
|
|
65
|
-
className: `p-1.5 transition-colors ${
|
|
66
|
+
className: `p-1.5 transition-colors ${I ? "text-action-primary-text-alt" : "text-text-secondary hover:text-text-primary"}`,
|
|
66
67
|
title: "Build history",
|
|
67
68
|
children: /* @__PURE__ */ p(l, { className: "size-4" })
|
|
68
69
|
}),
|
|
69
70
|
/* @__PURE__ */ p("button", {
|
|
70
71
|
type: "button",
|
|
71
72
|
onClick: () => {
|
|
72
|
-
|
|
73
|
+
F(!0), L(!1);
|
|
73
74
|
},
|
|
74
75
|
className: "p-1.5 text-text-secondary hover:text-text-primary transition-colors",
|
|
75
76
|
title: "Settings",
|
|
@@ -85,7 +86,7 @@ function h({ site: h, pages: g, onBack: _, onSavePage: v, onAddPage: y, pageAddi
|
|
|
85
86
|
]
|
|
86
87
|
})]
|
|
87
88
|
}),
|
|
88
|
-
|
|
89
|
+
I && /* @__PURE__ */ p("div", {
|
|
89
90
|
className: "border-b border-border-default bg-bg-base max-h-64 overflow-y-auto",
|
|
90
91
|
children: /* @__PURE__ */ p(a, {
|
|
91
92
|
revisions: h.revisions ?? [],
|
|
@@ -100,8 +101,8 @@ function h({ site: h, pages: g, onBack: _, onSavePage: v, onAddPage: y, pageAddi
|
|
|
100
101
|
className: "border-r border-border-default overflow-hidden",
|
|
101
102
|
children: /* @__PURE__ */ p(n, {
|
|
102
103
|
pages: g,
|
|
103
|
-
selectedPageId:
|
|
104
|
-
onSelectPage:
|
|
104
|
+
selectedPageId: M,
|
|
105
|
+
onSelectPage: N,
|
|
105
106
|
onAddPage: y,
|
|
106
107
|
pageAdding: b,
|
|
107
108
|
onDeletePage: x
|
|
@@ -109,15 +110,15 @@ function h({ site: h, pages: g, onBack: _, onSavePage: v, onAddPage: y, pageAddi
|
|
|
109
110
|
}), /* @__PURE__ */ p("div", {
|
|
110
111
|
className: "overflow-hidden",
|
|
111
112
|
children: /* @__PURE__ */ p(r, {
|
|
112
|
-
page:
|
|
113
|
+
page: R,
|
|
113
114
|
onSave: v
|
|
114
115
|
})
|
|
115
116
|
})]
|
|
116
117
|
}),
|
|
117
118
|
/* @__PURE__ */ p(i, {
|
|
118
119
|
site: h,
|
|
119
|
-
open:
|
|
120
|
-
onClose: () =>
|
|
120
|
+
open: P,
|
|
121
|
+
onClose: () => F(!1),
|
|
121
122
|
onSave: C
|
|
122
123
|
})
|
|
123
124
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocsEditPanel.js","names":[],"sources":["../../../src/components/docs/DocsEditPanel.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { ArrowLeft, Settings, RefreshCw, History, Trash2 } from 'lucide-react';\nimport { DocsPageTree } from './DocsPageTree';\nimport { DocsPageEditor } from './DocsPageEditor';\nimport { DocsSettingsPanel } from './DocsSettingsPanel';\nimport { DocsCompileStatus } from './DocsCompileStatus';\nimport { DocsRevisionHistory } from './DocsRevisionHistory';\nimport type { DocsSite, DocsPage, DocsRevision } from './types';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface DocsEditPanelProps {\n site: DocsSite;\n pages: DocsPage[];\n onBack: () => void;\n onSavePage: (\n id: string,\n data: { title?: string; content?: string; slug?: string }\n ) => Promise<void>;\n onAddPage: (parentId?: string, category?: string) => void;\n pageAdding?: boolean;\n onDeletePage: (pageId: string) => void;\n onCompile: () => void;\n onSaveSettings: (data: {\n name?: string;\n visibility?: 'PRIVATE' | 'PUBLIC';\n provider?: 'DOCUSAURUS' | 'MKDOCS' | 'VITEPRESS';\n providerConfig?: Record<string, unknown>;\n }) => Promise<void>;\n onRollback: (revisionId: string) => Promise<void>;\n onDeleteSite: () => Promise<void>;\n rollingBack: string | null;\n compileRevision: DocsRevision | null;\n onPollRevision?: (id: string) => Promise<DocsRevision | null>;\n compiling: boolean;\n}\n\nexport function DocsEditPanel({\n site,\n pages,\n onBack,\n onSavePage,\n onAddPage,\n pageAdding,\n onDeletePage,\n onCompile,\n onSaveSettings,\n onRollback,\n onDeleteSite,\n rollingBack,\n compileRevision,\n onPollRevision,\n compiling,\n}: DocsEditPanelProps) {\n const tr = useTr();\n const [selectedPageId, setSelectedPageId] = useState<string | null>(pages[0]?.id || null);\n const [showSettings, setShowSettings] = useState(false);\n const [showHistory, setShowHistory] = useState(false);\n\n const selectedPage = pages.find((p) => p.id === selectedPageId) || null;\n\n useEffect(() => {\n if (pages.length === 0) {\n if (selectedPageId) setSelectedPageId(null);\n return;\n }\n if (!selectedPageId || !pages.some((page) => page.id === selectedPageId)) {\n setSelectedPageId(pages[0].id);\n }\n }, [pages, selectedPageId]);\n\n return (\n <div className=\"flex flex-col h-full\" style={{ minHeight: 'calc(100vh - 380px)' }}>\n {/* Top bar */}\n <div className=\"flex items-center justify-between px-4 py-2 border-b border-border-default bg-bg-surface\">\n <div className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={onBack}\n className=\"flex items-center gap-1.5 text-sm text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n {tr('vibecontrols.docs.edit.preview', 'Preview')}\n </button>\n <span className=\"text-text-muted\">|</span>\n <span className=\"text-sm font-medium text-text-primary\">{site.name}</span>\n </div>\n <div className=\"flex items-center gap-2\">\n <div className=\"relative\">\n <DocsCompileStatus revision={compileRevision} onPoll={onPollRevision} />\n </div>\n <button\n type=\"button\"\n onClick={onCompile}\n disabled={compiling}\n className=\"flex items-center gap-1.5 px-3 py-1.5 text-sm bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n <RefreshCw className={`size-3.5 ${compiling ? 'animate-spin' : ''}`} />\n {tr('vibecontrols.docs.edit.compile', 'Compile')}\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setShowHistory((v) => !v);\n setShowSettings(false);\n }}\n className={`p-1.5 transition-colors ${showHistory ? 'text-action-primary-text-alt' : 'text-text-secondary hover:text-text-primary'}`}\n title=\"Build history\"\n >\n <History className=\"size-4\" />\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setShowSettings(true);\n setShowHistory(false);\n }}\n className=\"p-1.5 text-text-secondary hover:text-text-primary transition-colors\"\n title=\"Settings\"\n >\n <Settings className=\"size-4\" />\n </button>\n <button\n type=\"button\"\n onClick={onDeleteSite}\n className=\"p-1.5 text-text-muted hover:text-status-error-text transition-colors\"\n title=\"Delete site\"\n >\n <Trash2 className=\"size-4\" />\n </button>\n </div>\n </div>\n\n {/* Revision history drawer */}\n {showHistory && (\n <div className=\"border-b border-border-default bg-bg-base max-h-64 overflow-y-auto\">\n <DocsRevisionHistory\n revisions={site.revisions ?? []}\n currentRevisionId={site.currentRevisionId}\n onRollback={onRollback}\n rollingBack={rollingBack}\n />\n </div>\n )}\n\n {/* Main content: sidebar + editor */}\n <div className=\"flex-1 grid grid-cols-[260px_1fr] min-h-0\">\n {/* Page tree sidebar */}\n <div className=\"border-r border-border-default overflow-hidden\">\n <DocsPageTree\n pages={pages}\n selectedPageId={selectedPageId}\n onSelectPage={setSelectedPageId}\n onAddPage={onAddPage}\n pageAdding={pageAdding}\n onDeletePage={onDeletePage}\n />\n </div>\n\n {/* Editor */}\n <div className=\"overflow-hidden\">\n <DocsPageEditor page={selectedPage} onSave={onSavePage} />\n </div>\n </div>\n\n {/* Settings panel */}\n <DocsSettingsPanel\n site={site}\n open={showSettings}\n onClose={() => setShowSettings(false)}\n onSave={onSaveSettings}\n />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"DocsEditPanel.js","names":[],"sources":["../../../src/components/docs/DocsEditPanel.tsx"],"sourcesContent":["import { useEffect, useState, type ReactNode } from 'react';\nimport { ArrowLeft, Settings, RefreshCw, History, Trash2 } from 'lucide-react';\nimport { DocsPageTree } from './DocsPageTree';\nimport { DocsPageEditor } from './DocsPageEditor';\nimport { DocsSettingsPanel } from './DocsSettingsPanel';\nimport { DocsCompileStatus } from './DocsCompileStatus';\nimport { DocsRevisionHistory } from './DocsRevisionHistory';\nimport type { DocsSite, DocsPage, DocsRevision } from './types';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface DocsEditPanelProps {\n site: DocsSite;\n pages: DocsPage[];\n onBack: () => void;\n onSavePage: (\n id: string,\n data: { title?: string; content?: string; slug?: string }\n ) => Promise<void>;\n onAddPage: (parentId?: string, category?: string) => void;\n pageAdding?: boolean;\n onDeletePage: (pageId: string) => void;\n onCompile: () => void;\n onSaveSettings: (data: {\n name?: string;\n visibility?: 'PRIVATE' | 'PUBLIC';\n provider?: 'DOCUSAURUS' | 'MKDOCS' | 'VITEPRESS';\n providerConfig?: Record<string, unknown>;\n }) => Promise<void>;\n onRollback: (revisionId: string) => Promise<void>;\n onDeleteSite: () => Promise<void>;\n rollingBack: string | null;\n compileRevision: DocsRevision | null;\n onPollRevision?: (id: string) => Promise<DocsRevision | null>;\n compiling: boolean;\n /** Generic grant-based Share affordance (owner-keyed; supplied by the host). */\n shareSlot?: ReactNode;\n}\n\nexport function DocsEditPanel({\n site,\n pages,\n onBack,\n onSavePage,\n onAddPage,\n pageAdding,\n onDeletePage,\n onCompile,\n onSaveSettings,\n onRollback,\n onDeleteSite,\n rollingBack,\n compileRevision,\n onPollRevision,\n compiling,\n shareSlot,\n}: DocsEditPanelProps) {\n const tr = useTr();\n const [selectedPageId, setSelectedPageId] = useState<string | null>(pages[0]?.id || null);\n const [showSettings, setShowSettings] = useState(false);\n const [showHistory, setShowHistory] = useState(false);\n\n const selectedPage = pages.find((p) => p.id === selectedPageId) || null;\n\n useEffect(() => {\n if (pages.length === 0) {\n if (selectedPageId) setSelectedPageId(null);\n return;\n }\n if (!selectedPageId || !pages.some((page) => page.id === selectedPageId)) {\n setSelectedPageId(pages[0].id);\n }\n }, [pages, selectedPageId]);\n\n return (\n <div className=\"flex flex-col h-full\" style={{ minHeight: 'calc(100vh - 380px)' }}>\n {/* Top bar */}\n <div className=\"flex items-center justify-between px-4 py-2 border-b border-border-default bg-bg-surface\">\n <div className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={onBack}\n className=\"flex items-center gap-1.5 text-sm text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n {tr('vibecontrols.docs.edit.preview', 'Preview')}\n </button>\n <span className=\"text-text-muted\">|</span>\n <span className=\"text-sm font-medium text-text-primary\">{site.name}</span>\n </div>\n <div className=\"flex items-center gap-2\">\n {shareSlot}\n <div className=\"relative\">\n <DocsCompileStatus revision={compileRevision} onPoll={onPollRevision} />\n </div>\n <button\n type=\"button\"\n onClick={onCompile}\n disabled={compiling}\n className=\"flex items-center gap-1.5 px-3 py-1.5 text-sm bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n <RefreshCw className={`size-3.5 ${compiling ? 'animate-spin' : ''}`} />\n {tr('vibecontrols.docs.edit.compile', 'Compile')}\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setShowHistory((v) => !v);\n setShowSettings(false);\n }}\n className={`p-1.5 transition-colors ${showHistory ? 'text-action-primary-text-alt' : 'text-text-secondary hover:text-text-primary'}`}\n title=\"Build history\"\n >\n <History className=\"size-4\" />\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setShowSettings(true);\n setShowHistory(false);\n }}\n className=\"p-1.5 text-text-secondary hover:text-text-primary transition-colors\"\n title=\"Settings\"\n >\n <Settings className=\"size-4\" />\n </button>\n <button\n type=\"button\"\n onClick={onDeleteSite}\n className=\"p-1.5 text-text-muted hover:text-status-error-text transition-colors\"\n title=\"Delete site\"\n >\n <Trash2 className=\"size-4\" />\n </button>\n </div>\n </div>\n\n {/* Revision history drawer */}\n {showHistory && (\n <div className=\"border-b border-border-default bg-bg-base max-h-64 overflow-y-auto\">\n <DocsRevisionHistory\n revisions={site.revisions ?? []}\n currentRevisionId={site.currentRevisionId}\n onRollback={onRollback}\n rollingBack={rollingBack}\n />\n </div>\n )}\n\n {/* Main content: sidebar + editor */}\n <div className=\"flex-1 grid grid-cols-[260px_1fr] min-h-0\">\n {/* Page tree sidebar */}\n <div className=\"border-r border-border-default overflow-hidden\">\n <DocsPageTree\n pages={pages}\n selectedPageId={selectedPageId}\n onSelectPage={setSelectedPageId}\n onAddPage={onAddPage}\n pageAdding={pageAdding}\n onDeletePage={onDeletePage}\n />\n </div>\n\n {/* Editor */}\n <div className=\"overflow-hidden\">\n <DocsPageEditor page={selectedPage} onSave={onSavePage} />\n </div>\n </div>\n\n {/* Settings panel */}\n <DocsSettingsPanel\n site={site}\n open={showSettings}\n onClose={() => setShowSettings(false)}\n onSave={onSaveSettings}\n />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;AAsCA,SAAgB,EAAc,EAC5B,SACA,UACA,WACA,eACA,cACA,eACA,iBACA,cACA,mBACA,eACA,iBACA,gBACA,oBACA,mBACA,cACA,gBACqB;CACrB,IAAM,IAAK,GAAO,EACZ,CAAC,GAAgB,KAAqB,EAAwB,EAAM,IAAI,MAAM,KAAK,EACnF,CAAC,GAAc,KAAmB,EAAS,GAAM,EACjD,CAAC,GAAa,KAAkB,EAAS,GAAM,EAE/C,IAAe,EAAM,MAAM,MAAM,EAAE,OAAO,EAAe,IAAI;AAYnE,QAVA,QAAgB;AACd,MAAI,EAAM,WAAW,GAAG;AACtB,GAAI,KAAgB,EAAkB,KAAK;AAC3C;;AAEF,GAAI,CAAC,KAAkB,CAAC,EAAM,MAAM,MAAS,EAAK,OAAO,EAAe,KACtE,EAAkB,EAAM,GAAG,GAAG;IAE/B,CAAC,GAAO,EAAe,CAAC,EAGzB,kBAAC,OAAD;EAAK,WAAU;EAAuB,OAAO,EAAE,WAAW,uBAAuB;YAAjF;GAEE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,UAAD;OACE,MAAK;OACL,SAAS;OACT,WAAU;iBAHZ,CAKE,kBAAC,GAAD,EAAW,WAAU,UAAW,CAAA,EAC/B,EAAG,kCAAkC,UAAU,CACzC;;MACT,kBAAC,QAAD;OAAM,WAAU;iBAAkB;OAAQ,CAAA;MAC1C,kBAAC,QAAD;OAAM,WAAU;iBAAyC,EAAK;OAAY,CAAA;MACtE;QACN,kBAAC,OAAD;KAAK,WAAU;eAAf;MACG;MACD,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,GAAD;QAAmB,UAAU;QAAiB,QAAQ;QAAkB,CAAA;OACpE,CAAA;MACN,kBAAC,UAAD;OACE,MAAK;OACL,SAAS;OACT,UAAU;OACV,WAAU;iBAJZ,CAME,kBAAC,GAAD,EAAW,WAAW,YAAY,IAAY,iBAAiB,MAAQ,CAAA,EACtE,EAAG,kCAAkC,UAAU,CACzC;;MACT,kBAAC,UAAD;OACE,MAAK;OACL,eAAe;AAEb,QADA,GAAgB,MAAM,CAAC,EAAE,EACzB,EAAgB,GAAM;;OAExB,WAAW,2BAA2B,IAAc,iCAAiC;OACrF,OAAM;iBAEN,kBAAC,GAAD,EAAS,WAAU,UAAW,CAAA;OACvB,CAAA;MACT,kBAAC,UAAD;OACE,MAAK;OACL,eAAe;AAEb,QADA,EAAgB,GAAK,EACrB,EAAe,GAAM;;OAEvB,WAAU;OACV,OAAM;iBAEN,kBAAC,GAAD,EAAU,WAAU,UAAW,CAAA;OACxB,CAAA;MACT,kBAAC,UAAD;OACE,MAAK;OACL,SAAS;OACT,WAAU;OACV,OAAM;iBAEN,kBAAC,GAAD,EAAQ,WAAU,UAAW,CAAA;OACtB,CAAA;MACL;OACF;;GAGL,KACC,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD;KACE,WAAW,EAAK,aAAa,EAAE;KAC/B,mBAAmB,EAAK;KACZ;KACC;KACb,CAAA;IACE,CAAA;GAIR,kBAAC,OAAD;IAAK,WAAU;cAAf,CAEE,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,GAAD;MACS;MACS;MAChB,cAAc;MACH;MACC;MACE;MACd,CAAA;KACE,CAAA,EAGN,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,GAAD;MAAgB,MAAM;MAAc,QAAQ;MAAc,CAAA;KACtD,CAAA,CACF;;GAGN,kBAAC,GAAD;IACQ;IACN,MAAM;IACN,eAAe,EAAgB,GAAM;IACrC,QAAQ;IACR,CAAA;GACE"}
|
|
@@ -7,18 +7,18 @@ import { useState as i } from "react";
|
|
|
7
7
|
import { AlertTriangle as a, Check as o, Edit3 as s, ExternalLink as c, Link2 as l, Loader2 as u, RefreshCw as d, Settings as f, XCircle as p } from "lucide-react";
|
|
8
8
|
import { jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
9
9
|
//#region src/components/docs/DocsPreviewPanel.tsx
|
|
10
|
-
function g({ site: g, pages: _ = [], selectedPageSlug: v = "", onSelectPage: y, docsBaseUrl: b, docsHtml: x, docsContentLoading: S, onEdit: C, onCompile: w, onSettings: T, onGetShareUrl: E, onOpenFullScreen: D, compileRevision: O, onPollRevision: k, compiling: A }) {
|
|
11
|
-
let
|
|
10
|
+
function g({ site: g, pages: _ = [], selectedPageSlug: v = "", onSelectPage: y, docsBaseUrl: b, docsHtml: x, docsContentLoading: S, onEdit: C, onCompile: w, onSettings: T, onGetShareUrl: E, onOpenFullScreen: D, compileRevision: O, onPollRevision: k, compiling: A, shareSlot: j }) {
|
|
11
|
+
let M = e(), N = g.currentRevision, [P, F] = i(!1), [I, L] = i(!1), R = async () => {
|
|
12
12
|
if (E) {
|
|
13
|
-
|
|
13
|
+
F(!0);
|
|
14
14
|
try {
|
|
15
15
|
let e = await E();
|
|
16
|
-
e && (await navigator.clipboard.writeText(e),
|
|
16
|
+
e && (await navigator.clipboard.writeText(e), L(!0), setTimeout(() => L(!1), 2e3));
|
|
17
17
|
} finally {
|
|
18
|
-
|
|
18
|
+
F(!1);
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
-
},
|
|
21
|
+
}, z = x ? r(x) : null;
|
|
22
22
|
return /* @__PURE__ */ h("div", {
|
|
23
23
|
className: "space-y-4",
|
|
24
24
|
children: [
|
|
@@ -31,9 +31,9 @@ function g({ site: g, pages: _ = [], selectedPageSlug: v = "", onSelectPage: y,
|
|
|
31
31
|
className: "font-semibold text-text-primary",
|
|
32
32
|
children: g.name
|
|
33
33
|
}),
|
|
34
|
-
|
|
34
|
+
N && /* @__PURE__ */ h("span", {
|
|
35
35
|
className: "text-xs text-text-muted bg-bg-sunken px-2 py-0.5 rounded",
|
|
36
|
-
children: ["Rev #",
|
|
36
|
+
children: ["Rev #", N.revisionNumber]
|
|
37
37
|
}),
|
|
38
38
|
/* @__PURE__ */ m("div", {
|
|
39
39
|
className: "relative",
|
|
@@ -46,32 +46,33 @@ function g({ site: g, pages: _ = [], selectedPageSlug: v = "", onSelectPage: y,
|
|
|
46
46
|
}), /* @__PURE__ */ h("div", {
|
|
47
47
|
className: "flex items-center gap-2",
|
|
48
48
|
children: [
|
|
49
|
-
|
|
49
|
+
j,
|
|
50
|
+
N && E && /* @__PURE__ */ h("button", {
|
|
50
51
|
type: "button",
|
|
51
|
-
onClick:
|
|
52
|
-
disabled:
|
|
52
|
+
onClick: R,
|
|
53
|
+
disabled: P,
|
|
53
54
|
className: "flex items-center gap-1.5 px-3 py-1.5 text-sm bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors disabled:opacity-50",
|
|
54
55
|
title: g.visibility === "PUBLIC" ? "Copy public link" : "Copy signed link (expires)",
|
|
55
|
-
children: [
|
|
56
|
+
children: [I ? /* @__PURE__ */ m(o, { className: "size-3.5 text-status-success-text" }) : P ? /* @__PURE__ */ m(u, { className: "size-3.5 animate-spin" }) : /* @__PURE__ */ m(l, { className: "size-3.5" }), I ? "Copied!" : M("vibecontrols.docs.preview.copyLink", "Copy Link")]
|
|
56
57
|
}),
|
|
57
|
-
|
|
58
|
+
N && /* @__PURE__ */ h("button", {
|
|
58
59
|
type: "button",
|
|
59
60
|
onClick: D,
|
|
60
61
|
className: "flex items-center gap-1.5 px-3 py-1.5 text-sm bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors",
|
|
61
|
-
children: [/* @__PURE__ */ m(c, { className: "size-3.5" }),
|
|
62
|
+
children: [/* @__PURE__ */ m(c, { className: "size-3.5" }), M("vibecontrols.docs.preview.openFullScreen", "Open Full Screen")]
|
|
62
63
|
}),
|
|
63
64
|
/* @__PURE__ */ h("button", {
|
|
64
65
|
type: "button",
|
|
65
66
|
onClick: C,
|
|
66
67
|
className: "flex items-center gap-1.5 px-3 py-1.5 text-sm bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors",
|
|
67
|
-
children: [/* @__PURE__ */ m(s, { className: "size-3.5" }),
|
|
68
|
+
children: [/* @__PURE__ */ m(s, { className: "size-3.5" }), M("vibecontrols.docs.preview.edit", "Edit")]
|
|
68
69
|
}),
|
|
69
70
|
/* @__PURE__ */ h("button", {
|
|
70
71
|
type: "button",
|
|
71
72
|
onClick: w,
|
|
72
73
|
disabled: A,
|
|
73
74
|
className: "flex items-center gap-1.5 px-3 py-1.5 text-sm bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50",
|
|
74
|
-
children: [/* @__PURE__ */ m(d, { className: `size-3.5 ${A ? "animate-spin" : ""}` }),
|
|
75
|
+
children: [/* @__PURE__ */ m(d, { className: `size-3.5 ${A ? "animate-spin" : ""}` }), M("vibecontrols.docs.preview.compileDocs", "Compile Docs")]
|
|
75
76
|
}),
|
|
76
77
|
/* @__PURE__ */ m("button", {
|
|
77
78
|
type: "button",
|
|
@@ -83,7 +84,7 @@ function g({ site: g, pages: _ = [], selectedPageSlug: v = "", onSelectPage: y,
|
|
|
83
84
|
]
|
|
84
85
|
})]
|
|
85
86
|
}),
|
|
86
|
-
_.length > 1 &&
|
|
87
|
+
_.length > 1 && N && /* @__PURE__ */ m("div", {
|
|
87
88
|
className: "flex items-center gap-1 overflow-x-auto pb-1 border-b border-border-primary",
|
|
88
89
|
children: _.map((e, t) => /* @__PURE__ */ m("button", {
|
|
89
90
|
type: "button",
|
|
@@ -92,10 +93,10 @@ function g({ site: g, pages: _ = [], selectedPageSlug: v = "", onSelectPage: y,
|
|
|
92
93
|
children: e.title
|
|
93
94
|
}, e.id))
|
|
94
95
|
}),
|
|
95
|
-
|
|
96
|
+
z && N ? /* @__PURE__ */ m(t, {
|
|
96
97
|
className: "overflow-hidden",
|
|
97
98
|
children: /* @__PURE__ */ m("iframe", {
|
|
98
|
-
srcDoc:
|
|
99
|
+
srcDoc: z,
|
|
99
100
|
className: "w-full border-0",
|
|
100
101
|
style: {
|
|
101
102
|
height: "calc(100vh - 380px)",
|
|
@@ -103,8 +104,8 @@ function g({ site: g, pages: _ = [], selectedPageSlug: v = "", onSelectPage: y,
|
|
|
103
104
|
},
|
|
104
105
|
title: "Documentation Preview",
|
|
105
106
|
sandbox: "allow-same-origin allow-forms allow-popups"
|
|
106
|
-
}, `${
|
|
107
|
-
}) :
|
|
107
|
+
}, `${N.id}-${v}`)
|
|
108
|
+
}) : N && S ? /* @__PURE__ */ m(t, {
|
|
108
109
|
className: "p-8 text-center",
|
|
109
110
|
children: /* @__PURE__ */ h("div", {
|
|
110
111
|
className: "flex flex-col items-center gap-2 text-text-muted",
|
|
@@ -113,7 +114,7 @@ function g({ site: g, pages: _ = [], selectedPageSlug: v = "", onSelectPage: y,
|
|
|
113
114
|
children: "Loading documentation preview…"
|
|
114
115
|
})]
|
|
115
116
|
})
|
|
116
|
-
}) :
|
|
117
|
+
}) : N && !S && !x ? /* @__PURE__ */ m(t, {
|
|
117
118
|
className: "p-8 text-center",
|
|
118
119
|
children: /* @__PURE__ */ h("div", {
|
|
119
120
|
className: "flex flex-col items-center gap-3 text-text-secondary",
|
|
@@ -174,7 +175,7 @@ function g({ site: g, pages: _ = [], selectedPageSlug: v = "", onSelectPage: y,
|
|
|
174
175
|
children: [
|
|
175
176
|
/* @__PURE__ */ m("p", {
|
|
176
177
|
className: "text-text-secondary mb-1 font-medium",
|
|
177
|
-
children:
|
|
178
|
+
children: M("vibecontrols.docs.preview.noPublished", "No published documentation yet")
|
|
178
179
|
}),
|
|
179
180
|
/* @__PURE__ */ h("p", {
|
|
180
181
|
className: "text-sm text-text-muted mb-4",
|
|
@@ -188,7 +189,7 @@ function g({ site: g, pages: _ = [], selectedPageSlug: v = "", onSelectPage: y,
|
|
|
188
189
|
type: "button",
|
|
189
190
|
onClick: C,
|
|
190
191
|
className: "px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors",
|
|
191
|
-
children:
|
|
192
|
+
children: M("vibecontrols.docs.preview.startEditing", "Start Editing")
|
|
192
193
|
})
|
|
193
194
|
]
|
|
194
195
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocsPreviewPanel.js","names":[],"sources":["../../../src/components/docs/DocsPreviewPanel.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Edit3,\n RefreshCw,\n Settings,\n ExternalLink,\n Loader2,\n AlertTriangle,\n XCircle,\n Link2,\n Check,\n} from 'lucide-react';\nimport { Card } from '@/components/shared';\nimport { DocsCompileStatus } from './DocsCompileStatus';\nimport { createDocsPreviewHtml } from './previewHtml';\nimport type { DocsSite, DocsRevision, DocsPage } from './types';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface DocsPreviewPanelProps {\n site: DocsSite;\n pages?: DocsPage[];\n selectedPageSlug?: string;\n onSelectPage?: (slug: string) => void;\n docsBaseUrl: string | null;\n docsHtml: string | null;\n docsContentLoading?: boolean;\n onEdit: () => void;\n onCompile: () => void;\n onSettings: () => void;\n onGetShareUrl?: () => Promise<string | null>;\n onOpenFullScreen: () => void;\n compileRevision: DocsRevision | null;\n onPollRevision?: (id: string) => Promise<DocsRevision | null>;\n compiling: boolean;\n}\n\nexport function DocsPreviewPanel({\n site,\n pages = [],\n selectedPageSlug = '',\n onSelectPage,\n docsBaseUrl,\n docsHtml,\n docsContentLoading,\n onEdit,\n onCompile,\n onSettings,\n onGetShareUrl,\n onOpenFullScreen,\n compileRevision,\n onPollRevision,\n compiling,\n}: DocsPreviewPanelProps) {\n const tr = useTr();\n const currentRev = site.currentRevision;\n const [copying, setCopying] = useState(false);\n const [copied, setCopied] = useState(false);\n\n const handleCopyLink = async () => {\n if (!onGetShareUrl) return;\n setCopying(true);\n try {\n const url = await onGetShareUrl();\n if (url) {\n await navigator.clipboard.writeText(url);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }\n } finally {\n setCopying(false);\n }\n };\n const previewHtml = docsHtml ? createDocsPreviewHtml(docsHtml) : null;\n\n const renderPreviewArea = () => {\n // Inline srcDoc preview: extracts prose content from the compiled HTML and renders\n // it with self-contained typography styles in a sandboxed iframe. The gateway src\n // approach requires the full gateway stack (not available in local dev) and cannot\n // send auth headers from a browser iframe, so srcdoc is the reliable path.\n if (previewHtml && currentRev) {\n return (\n <Card className=\"overflow-hidden\">\n <iframe\n key={`${currentRev.id}-${selectedPageSlug}`}\n srcDoc={previewHtml}\n className=\"w-full border-0\"\n style={{ height: 'calc(100vh - 380px)', minHeight: '400px' }}\n title=\"Documentation Preview\"\n sandbox=\"allow-same-origin allow-forms allow-popups\"\n />\n </Card>\n );\n }\n\n // Revision exists but content is still loading\n if (currentRev && docsContentLoading) {\n return (\n <Card className=\"p-8 text-center\">\n <div className=\"flex flex-col items-center gap-2 text-text-muted\">\n <Loader2 className=\"size-5 animate-spin\" />\n <p className=\"text-sm\">Loading documentation preview…</p>\n </div>\n </Card>\n );\n }\n\n // Revision exists but content failed to load (not loading, not available)\n if (currentRev && !docsContentLoading && !docsHtml) {\n return (\n <Card className=\"p-8 text-center\">\n <div className=\"flex flex-col items-center gap-3 text-text-secondary\">\n <AlertTriangle className=\"size-5 text-status-warning-text\" />\n <p className=\"text-sm\">\n The preview could not be loaded. The site may still be processing, or the build\n artifact may have expired.\n </p>\n <button\n type=\"button\"\n onClick={onCompile}\n disabled={compiling}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md text-sm hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n Recompile Docs\n </button>\n </div>\n </Card>\n );\n }\n\n // Last compile failed with no prior successful revision — show failure prominently\n if (compileRevision?.status === 'FAILED') {\n return (\n <Card className=\"p-8 text-center\">\n <div className=\"flex flex-col items-center gap-3\">\n <XCircle className=\"size-8 text-status-error-text\" />\n <div>\n <p className=\"font-medium text-text-primary mb-1\">Build failed</p>\n {compileRevision.errorMessage && (\n <p className=\"text-sm text-status-error-text bg-status-error-bg rounded px-3 py-2 text-left max-w-md mx-auto mb-3\">\n {compileRevision.errorMessage}\n </p>\n )}\n <p className=\"text-sm text-text-muted\">\n Fix your pages in the editor and try compiling again.\n </p>\n </div>\n <div className=\"flex gap-2\">\n <button\n type=\"button\"\n onClick={onEdit}\n className=\"px-4 py-2 bg-bg-sunken text-text-primary rounded-md text-sm hover:bg-bg-sunken/80 transition-colors\"\n >\n Edit Pages\n </button>\n <button\n type=\"button\"\n onClick={onCompile}\n disabled={compiling}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md text-sm hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n Retry Compile\n </button>\n </div>\n </div>\n </Card>\n );\n }\n\n // No revision yet — prompt to start editing\n return (\n <Card className=\"p-8 text-center\">\n <p className=\"text-text-secondary mb-1 font-medium\">\n {tr('vibecontrols.docs.preview.noPublished', 'No published documentation yet')}\n </p>\n <p className=\"text-sm text-text-muted mb-4\">\n Add pages in the editor, then click <strong>Compile</strong> to build and publish your\n docs site. Compiled output is stored and served from S3 — compiling takes 1–3 minutes.\n </p>\n <button\n type=\"button\"\n onClick={onEdit}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n {tr('vibecontrols.docs.preview.startEditing', 'Start Editing')}\n </button>\n </Card>\n );\n };\n\n return (\n <div className=\"space-y-4\">\n {/* Action bar */}\n <div className=\"flex items-center justify-between flex-wrap gap-2\">\n <div className=\"flex items-center gap-3\">\n <h3 className=\"font-semibold text-text-primary\">{site.name}</h3>\n {currentRev && (\n <span className=\"text-xs text-text-muted bg-bg-sunken px-2 py-0.5 rounded\">\n Rev #{currentRev.revisionNumber}\n </span>\n )}\n <div className=\"relative\">\n <DocsCompileStatus revision={compileRevision} onPoll={onPollRevision} />\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n {currentRev && onGetShareUrl && (\n <button\n type=\"button\"\n onClick={handleCopyLink}\n disabled={copying}\n className=\"flex items-center gap-1.5 px-3 py-1.5 text-sm bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors disabled:opacity-50\"\n title={\n site.visibility === 'PUBLIC' ? 'Copy public link' : 'Copy signed link (expires)'\n }\n >\n {copied ? (\n <Check className=\"size-3.5 text-status-success-text\" />\n ) : copying ? (\n <Loader2 className=\"size-3.5 animate-spin\" />\n ) : (\n <Link2 className=\"size-3.5\" />\n )}\n {copied ? 'Copied!' : tr('vibecontrols.docs.preview.copyLink', 'Copy Link')}\n </button>\n )}\n {currentRev && (\n <button\n type=\"button\"\n onClick={onOpenFullScreen}\n className=\"flex items-center gap-1.5 px-3 py-1.5 text-sm bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors\"\n >\n <ExternalLink className=\"size-3.5\" />\n {tr('vibecontrols.docs.preview.openFullScreen', 'Open Full Screen')}\n </button>\n )}\n <button\n type=\"button\"\n onClick={onEdit}\n className=\"flex items-center gap-1.5 px-3 py-1.5 text-sm bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors\"\n >\n <Edit3 className=\"size-3.5\" />\n {tr('vibecontrols.docs.preview.edit', 'Edit')}\n </button>\n <button\n type=\"button\"\n onClick={onCompile}\n disabled={compiling}\n className=\"flex items-center gap-1.5 px-3 py-1.5 text-sm bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n <RefreshCw className={`size-3.5 ${compiling ? 'animate-spin' : ''}`} />\n {tr('vibecontrols.docs.preview.compileDocs', 'Compile Docs')}\n </button>\n <button\n type=\"button\"\n onClick={onSettings}\n className=\"p-1.5 text-text-secondary hover:text-text-primary transition-colors\"\n title=\"Site settings\"\n >\n <Settings className=\"size-4\" />\n </button>\n </div>\n </div>\n\n {/* Page navigation tabs — shown when there are multiple compiled pages */}\n {pages.length > 1 && currentRev && (\n <div className=\"flex items-center gap-1 overflow-x-auto pb-1 border-b border-border-primary\">\n {pages.map((page, i) => {\n const isSelected = i === 0 ? selectedPageSlug === '' : selectedPageSlug === page.slug;\n return (\n <button\n type=\"button\"\n key={page.id}\n onClick={() => onSelectPage?.(i === 0 ? '' : page.slug)}\n className={`shrink-0 px-3 py-1.5 text-sm rounded-t-md whitespace-nowrap transition-colors ${\n isSelected\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'text-text-secondary hover:text-text-primary hover:bg-bg-sunken'\n }`}\n >\n {page.title}\n </button>\n );\n })}\n </div>\n )}\n\n {renderPreviewArea()}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DocsPreviewPanel.js","names":[],"sources":["../../../src/components/docs/DocsPreviewPanel.tsx"],"sourcesContent":["import { useState, type ReactNode } from 'react';\nimport {\n Edit3,\n RefreshCw,\n Settings,\n ExternalLink,\n Loader2,\n AlertTriangle,\n XCircle,\n Link2,\n Check,\n} from 'lucide-react';\nimport { Card } from '@/components/shared';\nimport { DocsCompileStatus } from './DocsCompileStatus';\nimport { createDocsPreviewHtml } from './previewHtml';\nimport type { DocsSite, DocsRevision, DocsPage } from './types';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface DocsPreviewPanelProps {\n site: DocsSite;\n pages?: DocsPage[];\n selectedPageSlug?: string;\n onSelectPage?: (slug: string) => void;\n docsBaseUrl: string | null;\n docsHtml: string | null;\n docsContentLoading?: boolean;\n onEdit: () => void;\n onCompile: () => void;\n onSettings: () => void;\n onGetShareUrl?: () => Promise<string | null>;\n onOpenFullScreen: () => void;\n compileRevision: DocsRevision | null;\n onPollRevision?: (id: string) => Promise<DocsRevision | null>;\n compiling: boolean;\n /** Generic grant-based Share affordance (owner-keyed; supplied by the host). */\n shareSlot?: ReactNode;\n}\n\nexport function DocsPreviewPanel({\n site,\n pages = [],\n selectedPageSlug = '',\n onSelectPage,\n docsBaseUrl,\n docsHtml,\n docsContentLoading,\n onEdit,\n onCompile,\n onSettings,\n onGetShareUrl,\n onOpenFullScreen,\n compileRevision,\n onPollRevision,\n compiling,\n shareSlot,\n}: DocsPreviewPanelProps) {\n const tr = useTr();\n const currentRev = site.currentRevision;\n const [copying, setCopying] = useState(false);\n const [copied, setCopied] = useState(false);\n\n const handleCopyLink = async () => {\n if (!onGetShareUrl) return;\n setCopying(true);\n try {\n const url = await onGetShareUrl();\n if (url) {\n await navigator.clipboard.writeText(url);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }\n } finally {\n setCopying(false);\n }\n };\n const previewHtml = docsHtml ? createDocsPreviewHtml(docsHtml) : null;\n\n const renderPreviewArea = () => {\n // Inline srcDoc preview: extracts prose content from the compiled HTML and renders\n // it with self-contained typography styles in a sandboxed iframe. The gateway src\n // approach requires the full gateway stack (not available in local dev) and cannot\n // send auth headers from a browser iframe, so srcdoc is the reliable path.\n if (previewHtml && currentRev) {\n return (\n <Card className=\"overflow-hidden\">\n <iframe\n key={`${currentRev.id}-${selectedPageSlug}`}\n srcDoc={previewHtml}\n className=\"w-full border-0\"\n style={{ height: 'calc(100vh - 380px)', minHeight: '400px' }}\n title=\"Documentation Preview\"\n sandbox=\"allow-same-origin allow-forms allow-popups\"\n />\n </Card>\n );\n }\n\n // Revision exists but content is still loading\n if (currentRev && docsContentLoading) {\n return (\n <Card className=\"p-8 text-center\">\n <div className=\"flex flex-col items-center gap-2 text-text-muted\">\n <Loader2 className=\"size-5 animate-spin\" />\n <p className=\"text-sm\">Loading documentation preview…</p>\n </div>\n </Card>\n );\n }\n\n // Revision exists but content failed to load (not loading, not available)\n if (currentRev && !docsContentLoading && !docsHtml) {\n return (\n <Card className=\"p-8 text-center\">\n <div className=\"flex flex-col items-center gap-3 text-text-secondary\">\n <AlertTriangle className=\"size-5 text-status-warning-text\" />\n <p className=\"text-sm\">\n The preview could not be loaded. The site may still be processing, or the build\n artifact may have expired.\n </p>\n <button\n type=\"button\"\n onClick={onCompile}\n disabled={compiling}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md text-sm hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n Recompile Docs\n </button>\n </div>\n </Card>\n );\n }\n\n // Last compile failed with no prior successful revision — show failure prominently\n if (compileRevision?.status === 'FAILED') {\n return (\n <Card className=\"p-8 text-center\">\n <div className=\"flex flex-col items-center gap-3\">\n <XCircle className=\"size-8 text-status-error-text\" />\n <div>\n <p className=\"font-medium text-text-primary mb-1\">Build failed</p>\n {compileRevision.errorMessage && (\n <p className=\"text-sm text-status-error-text bg-status-error-bg rounded px-3 py-2 text-left max-w-md mx-auto mb-3\">\n {compileRevision.errorMessage}\n </p>\n )}\n <p className=\"text-sm text-text-muted\">\n Fix your pages in the editor and try compiling again.\n </p>\n </div>\n <div className=\"flex gap-2\">\n <button\n type=\"button\"\n onClick={onEdit}\n className=\"px-4 py-2 bg-bg-sunken text-text-primary rounded-md text-sm hover:bg-bg-sunken/80 transition-colors\"\n >\n Edit Pages\n </button>\n <button\n type=\"button\"\n onClick={onCompile}\n disabled={compiling}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md text-sm hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n Retry Compile\n </button>\n </div>\n </div>\n </Card>\n );\n }\n\n // No revision yet — prompt to start editing\n return (\n <Card className=\"p-8 text-center\">\n <p className=\"text-text-secondary mb-1 font-medium\">\n {tr('vibecontrols.docs.preview.noPublished', 'No published documentation yet')}\n </p>\n <p className=\"text-sm text-text-muted mb-4\">\n Add pages in the editor, then click <strong>Compile</strong> to build and publish your\n docs site. Compiled output is stored and served from S3 — compiling takes 1–3 minutes.\n </p>\n <button\n type=\"button\"\n onClick={onEdit}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n {tr('vibecontrols.docs.preview.startEditing', 'Start Editing')}\n </button>\n </Card>\n );\n };\n\n return (\n <div className=\"space-y-4\">\n {/* Action bar */}\n <div className=\"flex items-center justify-between flex-wrap gap-2\">\n <div className=\"flex items-center gap-3\">\n <h3 className=\"font-semibold text-text-primary\">{site.name}</h3>\n {currentRev && (\n <span className=\"text-xs text-text-muted bg-bg-sunken px-2 py-0.5 rounded\">\n Rev #{currentRev.revisionNumber}\n </span>\n )}\n <div className=\"relative\">\n <DocsCompileStatus revision={compileRevision} onPoll={onPollRevision} />\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n {shareSlot}\n {currentRev && onGetShareUrl && (\n <button\n type=\"button\"\n onClick={handleCopyLink}\n disabled={copying}\n className=\"flex items-center gap-1.5 px-3 py-1.5 text-sm bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors disabled:opacity-50\"\n title={\n site.visibility === 'PUBLIC' ? 'Copy public link' : 'Copy signed link (expires)'\n }\n >\n {copied ? (\n <Check className=\"size-3.5 text-status-success-text\" />\n ) : copying ? (\n <Loader2 className=\"size-3.5 animate-spin\" />\n ) : (\n <Link2 className=\"size-3.5\" />\n )}\n {copied ? 'Copied!' : tr('vibecontrols.docs.preview.copyLink', 'Copy Link')}\n </button>\n )}\n {currentRev && (\n <button\n type=\"button\"\n onClick={onOpenFullScreen}\n className=\"flex items-center gap-1.5 px-3 py-1.5 text-sm bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors\"\n >\n <ExternalLink className=\"size-3.5\" />\n {tr('vibecontrols.docs.preview.openFullScreen', 'Open Full Screen')}\n </button>\n )}\n <button\n type=\"button\"\n onClick={onEdit}\n className=\"flex items-center gap-1.5 px-3 py-1.5 text-sm bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors\"\n >\n <Edit3 className=\"size-3.5\" />\n {tr('vibecontrols.docs.preview.edit', 'Edit')}\n </button>\n <button\n type=\"button\"\n onClick={onCompile}\n disabled={compiling}\n className=\"flex items-center gap-1.5 px-3 py-1.5 text-sm bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n <RefreshCw className={`size-3.5 ${compiling ? 'animate-spin' : ''}`} />\n {tr('vibecontrols.docs.preview.compileDocs', 'Compile Docs')}\n </button>\n <button\n type=\"button\"\n onClick={onSettings}\n className=\"p-1.5 text-text-secondary hover:text-text-primary transition-colors\"\n title=\"Site settings\"\n >\n <Settings className=\"size-4\" />\n </button>\n </div>\n </div>\n\n {/* Page navigation tabs — shown when there are multiple compiled pages */}\n {pages.length > 1 && currentRev && (\n <div className=\"flex items-center gap-1 overflow-x-auto pb-1 border-b border-border-primary\">\n {pages.map((page, i) => {\n const isSelected = i === 0 ? selectedPageSlug === '' : selectedPageSlug === page.slug;\n return (\n <button\n type=\"button\"\n key={page.id}\n onClick={() => onSelectPage?.(i === 0 ? '' : page.slug)}\n className={`shrink-0 px-3 py-1.5 text-sm rounded-t-md whitespace-nowrap transition-colors ${\n isSelected\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'text-text-secondary hover:text-text-primary hover:bg-bg-sunken'\n }`}\n >\n {page.title}\n </button>\n );\n })}\n </div>\n )}\n\n {renderPreviewArea()}\n </div>\n );\n}\n"],"mappings":"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"}
|