@burdenoff/microfe-vibecontrols 2026.525.7 → 2026.525.9
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/docs/DocsEditPanel.js +75 -48
- package/dist/components/docs/DocsEditPanel.js.map +1 -1
- package/dist/components/docs/DocsFullScreenViewer.js +210 -0
- package/dist/components/docs/DocsFullScreenViewer.js.map +1 -0
- package/dist/components/docs/DocsPageEditor.js +153 -36
- package/dist/components/docs/DocsPageEditor.js.map +1 -1
- package/dist/components/docs/DocsPageTree.js +40 -39
- package/dist/components/docs/DocsPageTree.js.map +1 -1
- package/dist/components/docs/DocsPreviewPanel.js +88 -70
- package/dist/components/docs/DocsPreviewPanel.js.map +1 -1
- package/dist/components/docs/DocsRevisionHistory.js +125 -0
- package/dist/components/docs/DocsRevisionHistory.js.map +1 -0
- package/dist/components/docs/DocsTabPanel.js +123 -83
- package/dist/components/docs/DocsTabPanel.js.map +1 -1
- package/dist/components/idp-components/ComponentForm.js +222 -192
- package/dist/components/idp-components/ComponentForm.js.map +1 -1
- package/dist/components/idp-components/DependencyGraphTab.js +296 -0
- package/dist/components/idp-components/DependencyGraphTab.js.map +1 -0
- package/dist/components/idp-components/index.js +1 -0
- package/dist/components/notes/NoteCard.js +75 -49
- package/dist/components/notes/NoteCard.js.map +1 -1
- package/dist/components/notes/NoteEditor.js +202 -171
- package/dist/components/notes/NoteEditor.js.map +1 -1
- package/dist/components/notes/NoteList.js +100 -75
- package/dist/components/notes/NoteList.js.map +1 -1
- package/dist/components/notes/NotesTabPanel.js +227 -179
- package/dist/components/notes/NotesTabPanel.js.map +1 -1
- package/dist/components/templates/PublishTemplateForm.js +121 -84
- package/dist/components/templates/PublishTemplateForm.js.map +1 -1
- package/dist/components/templates/TemplateWizard.js +195 -96
- package/dist/components/templates/TemplateWizard.js.map +1 -1
- package/dist/generated/wspace-operations.js +1592 -1467
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/generated/wspace-types.js +12 -10
- package/dist/generated/wspace-types.js.map +1 -1
- package/dist/index.js +10 -10
- package/dist/pages/CatalogDetailPage.js +502 -313
- package/dist/pages/CatalogDetailPage.js.map +1 -1
- package/dist/pages/CatalogDocsPage.js +13 -181
- package/dist/pages/CatalogDocsPage.js.map +1 -1
- package/dist/pages/ComponentDetailPage.js +355 -324
- package/dist/pages/ComponentDetailPage.js.map +1 -1
- package/dist/pages/ComponentDocsPage.js +13 -181
- package/dist/pages/ComponentDocsPage.js.map +1 -1
- package/dist/pages/TemplateDetailPage.js +327 -194
- package/dist/pages/TemplateDetailPage.js.map +1 -1
- package/dist/pages/VibeDocsPage.js +13 -181
- package/dist/pages/VibeDocsPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -3,95 +3,122 @@ import { DocsCompileStatus as t } from "./DocsCompileStatus.js";
|
|
|
3
3
|
import { DocsPageTree as n } from "./DocsPageTree.js";
|
|
4
4
|
import { DocsPageEditor as r } from "./DocsPageEditor.js";
|
|
5
5
|
import { DocsSettingsPanel as i } from "./DocsSettingsPanel.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { DocsRevisionHistory as a } from "./DocsRevisionHistory.js";
|
|
7
|
+
import { useEffect as o, useState as s } from "react";
|
|
8
|
+
import { ArrowLeft as c, History as l, RefreshCw as u, Settings as d, Trash2 as f } from "lucide-react";
|
|
9
|
+
import { jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
9
10
|
//#region src/components/docs/DocsEditPanel.tsx
|
|
10
|
-
function
|
|
11
|
-
let
|
|
12
|
-
return
|
|
13
|
-
if (
|
|
14
|
-
|
|
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 A = e(), [j, M] = s(g[0]?.id || null), [N, P] = s(!1), [F, I] = s(!1), L = g.find((e) => e.id === j) || null;
|
|
13
|
+
return o(() => {
|
|
14
|
+
if (g.length === 0) {
|
|
15
|
+
j && M(null);
|
|
15
16
|
return;
|
|
16
17
|
}
|
|
17
|
-
(!
|
|
18
|
-
}, [
|
|
18
|
+
(!j || !g.some((e) => e.id === j)) && M(g[0].id);
|
|
19
|
+
}, [g, j]), /* @__PURE__ */ m("div", {
|
|
19
20
|
className: "flex flex-col h-full",
|
|
20
21
|
style: { minHeight: "calc(100vh - 380px)" },
|
|
21
22
|
children: [
|
|
22
|
-
/* @__PURE__ */
|
|
23
|
+
/* @__PURE__ */ m("div", {
|
|
23
24
|
className: "flex items-center justify-between px-4 py-2 border-b border-border-default bg-bg-surface",
|
|
24
|
-
children: [/* @__PURE__ */
|
|
25
|
+
children: [/* @__PURE__ */ m("div", {
|
|
25
26
|
className: "flex items-center gap-3",
|
|
26
27
|
children: [
|
|
27
|
-
/* @__PURE__ */
|
|
28
|
-
onClick:
|
|
28
|
+
/* @__PURE__ */ m("button", {
|
|
29
|
+
onClick: _,
|
|
29
30
|
className: "flex items-center gap-1.5 text-sm text-text-secondary hover:text-text-primary transition-colors",
|
|
30
|
-
children: [/* @__PURE__ */
|
|
31
|
+
children: [/* @__PURE__ */ p(c, { className: "w-4 h-4" }), A("vibecontrols.docs.edit.preview", "Preview")]
|
|
31
32
|
}),
|
|
32
|
-
/* @__PURE__ */
|
|
33
|
+
/* @__PURE__ */ p("span", {
|
|
33
34
|
className: "text-text-muted",
|
|
34
35
|
children: "|"
|
|
35
36
|
}),
|
|
36
|
-
/* @__PURE__ */
|
|
37
|
+
/* @__PURE__ */ p("span", {
|
|
37
38
|
className: "text-sm font-medium text-text-primary",
|
|
38
|
-
children:
|
|
39
|
+
children: h.name
|
|
39
40
|
})
|
|
40
41
|
]
|
|
41
|
-
}), /* @__PURE__ */
|
|
42
|
+
}), /* @__PURE__ */ m("div", {
|
|
42
43
|
className: "flex items-center gap-2",
|
|
43
44
|
children: [
|
|
44
|
-
/* @__PURE__ */
|
|
45
|
+
/* @__PURE__ */ p("div", {
|
|
45
46
|
className: "relative",
|
|
46
|
-
children: /* @__PURE__ */
|
|
47
|
-
revision:
|
|
48
|
-
onPoll:
|
|
47
|
+
children: /* @__PURE__ */ p(t, {
|
|
48
|
+
revision: D,
|
|
49
|
+
onPoll: O
|
|
49
50
|
})
|
|
50
51
|
}),
|
|
51
|
-
/* @__PURE__ */
|
|
52
|
-
onClick:
|
|
53
|
-
disabled:
|
|
52
|
+
/* @__PURE__ */ m("button", {
|
|
53
|
+
onClick: S,
|
|
54
|
+
disabled: k,
|
|
54
55
|
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",
|
|
55
|
-
children: [/* @__PURE__ */ u
|
|
56
|
+
children: [/* @__PURE__ */ p(u, { className: `w-3.5 h-3.5 ${k ? "animate-spin" : ""}` }), A("vibecontrols.docs.edit.compile", "Compile")]
|
|
56
57
|
}),
|
|
57
|
-
/* @__PURE__ */
|
|
58
|
-
onClick: () =>
|
|
58
|
+
/* @__PURE__ */ p("button", {
|
|
59
|
+
onClick: () => {
|
|
60
|
+
I((e) => !e), P(!1);
|
|
61
|
+
},
|
|
62
|
+
className: `p-1.5 transition-colors ${F ? "text-action-primary-text-alt" : "text-text-secondary hover:text-text-primary"}`,
|
|
63
|
+
title: "Build history",
|
|
64
|
+
children: /* @__PURE__ */ p(l, { className: "w-4 h-4" })
|
|
65
|
+
}),
|
|
66
|
+
/* @__PURE__ */ p("button", {
|
|
67
|
+
onClick: () => {
|
|
68
|
+
P(!0), I(!1);
|
|
69
|
+
},
|
|
59
70
|
className: "p-1.5 text-text-secondary hover:text-text-primary transition-colors",
|
|
60
71
|
title: "Settings",
|
|
61
|
-
children: /* @__PURE__ */
|
|
72
|
+
children: /* @__PURE__ */ p(d, { className: "w-4 h-4" })
|
|
73
|
+
}),
|
|
74
|
+
/* @__PURE__ */ p("button", {
|
|
75
|
+
onClick: T,
|
|
76
|
+
className: "p-1.5 text-text-muted hover:text-status-danger-text transition-colors",
|
|
77
|
+
title: "Delete site",
|
|
78
|
+
children: /* @__PURE__ */ p(f, { className: "w-4 h-4" })
|
|
62
79
|
})
|
|
63
80
|
]
|
|
64
81
|
})]
|
|
65
82
|
}),
|
|
66
|
-
/* @__PURE__ */
|
|
83
|
+
F && /* @__PURE__ */ p("div", {
|
|
84
|
+
className: "border-b border-border-default bg-bg-base max-h-64 overflow-y-auto",
|
|
85
|
+
children: /* @__PURE__ */ p(a, {
|
|
86
|
+
revisions: h.revisions ?? [],
|
|
87
|
+
currentRevisionId: h.currentRevisionId,
|
|
88
|
+
onRollback: w,
|
|
89
|
+
rollingBack: E
|
|
90
|
+
})
|
|
91
|
+
}),
|
|
92
|
+
/* @__PURE__ */ m("div", {
|
|
67
93
|
className: "flex-1 grid grid-cols-[260px_1fr] min-h-0",
|
|
68
|
-
children: [/* @__PURE__ */
|
|
94
|
+
children: [/* @__PURE__ */ p("div", {
|
|
69
95
|
className: "border-r border-border-default overflow-hidden",
|
|
70
|
-
children: /* @__PURE__ */
|
|
71
|
-
pages:
|
|
72
|
-
selectedPageId:
|
|
73
|
-
onSelectPage:
|
|
74
|
-
onAddPage:
|
|
75
|
-
|
|
96
|
+
children: /* @__PURE__ */ p(n, {
|
|
97
|
+
pages: g,
|
|
98
|
+
selectedPageId: j,
|
|
99
|
+
onSelectPage: M,
|
|
100
|
+
onAddPage: y,
|
|
101
|
+
pageAdding: b,
|
|
102
|
+
onDeletePage: x
|
|
76
103
|
})
|
|
77
|
-
}), /* @__PURE__ */
|
|
104
|
+
}), /* @__PURE__ */ p("div", {
|
|
78
105
|
className: "overflow-hidden",
|
|
79
|
-
children: /* @__PURE__ */
|
|
80
|
-
page:
|
|
81
|
-
onSave:
|
|
106
|
+
children: /* @__PURE__ */ p(r, {
|
|
107
|
+
page: L,
|
|
108
|
+
onSave: v
|
|
82
109
|
})
|
|
83
110
|
})]
|
|
84
111
|
}),
|
|
85
|
-
/* @__PURE__ */
|
|
86
|
-
site:
|
|
87
|
-
open:
|
|
88
|
-
onClose: () =>
|
|
89
|
-
onSave:
|
|
112
|
+
/* @__PURE__ */ p(i, {
|
|
113
|
+
site: h,
|
|
114
|
+
open: N,
|
|
115
|
+
onClose: () => P(!1),
|
|
116
|
+
onSave: C
|
|
90
117
|
})
|
|
91
118
|
]
|
|
92
119
|
});
|
|
93
120
|
}
|
|
94
121
|
//#endregion
|
|
95
|
-
export {
|
|
122
|
+
export { h as DocsEditPanel };
|
|
96
123
|
|
|
97
124
|
//# sourceMappingURL=DocsEditPanel.js.map
|
|
@@ -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 } from 'lucide-react';\nimport { DocsPageTree } from './DocsPageTree';\nimport { DocsPageEditor } from './DocsPageEditor';\nimport { DocsSettingsPanel } from './DocsSettingsPanel';\nimport { DocsCompileStatus } from './DocsCompileStatus';\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 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 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 onDeletePage,\n onCompile,\n onSaveSettings,\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\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
|
|
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 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=\"w-4 h-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 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={`w-3.5 h-3.5 ${compiling ? 'animate-spin' : ''}`} />\n {tr('vibecontrols.docs.edit.compile', 'Compile')}\n </button>\n <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=\"w-4 h-4\" />\n </button>\n <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=\"w-4 h-4\" />\n </button>\n <button\n onClick={onDeleteSite}\n className=\"p-1.5 text-text-muted hover:text-status-danger-text transition-colors\"\n title=\"Delete site\"\n >\n <Trash2 className=\"w-4 h-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":";;;;;;;;;;AAoCA,SAAgB,EAAc,EAC5B,SACA,UACA,WACA,eACA,cACA,eACA,iBACA,cACA,mBACA,eACA,iBACA,gBACA,oBACA,mBACA,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,SAAS;OACT,WAAU;iBAFZ,CAIE,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA,EAChC,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;MACE,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,GAAD;QAAmB,UAAU;QAAiB,QAAQ;QAAkB,CAAA;OACpE,CAAA;MACN,kBAAC,UAAD;OACE,SAAS;OACT,UAAU;OACV,WAAU;iBAHZ,CAKE,kBAAC,GAAD,EAAW,WAAW,eAAe,IAAY,iBAAiB,MAAQ,CAAA,EACzE,EAAG,kCAAkC,UAAU,CACzC;;MACT,kBAAC,UAAD;OACE,eAAe;AAEb,QADA,GAAgB,MAAM,CAAC,EAAE,EACzB,EAAgB,GAAM;;OAExB,WAAW,2BAA2B,IAAc,iCAAiC;OACrF,OAAM;iBAEN,kBAAC,GAAD,EAAS,WAAU,WAAY,CAAA;OACxB,CAAA;MACT,kBAAC,UAAD;OACE,eAAe;AAEb,QADA,EAAgB,GAAK,EACrB,EAAe,GAAM;;OAEvB,WAAU;OACV,OAAM;iBAEN,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA;OACzB,CAAA;MACT,kBAAC,UAAD;OACE,SAAS;OACT,WAAU;OACV,OAAM;iBAEN,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA;OACvB,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"}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { useDocsContentQuery as e, useGetVibeDocsSiteQuery as t } from "../../generated/wspace-operations.js";
|
|
2
|
+
import { LoadingState as n } from "../shared/LoadingState.js";
|
|
3
|
+
import { ErrorState as r } from "../shared/ErrorState.js";
|
|
4
|
+
import { EntityTagPicker as i } from "../shared/EntityTagPicker.js";
|
|
5
|
+
import "../shared/index.js";
|
|
6
|
+
import { VIBE_PERMISSIONS as a } from "../../constants/permissions.js";
|
|
7
|
+
import { createDocsPreviewHtml as o } from "./previewHtml.js";
|
|
8
|
+
import { useCallback as s, useEffect as c, useRef as l, useState as u } from "react";
|
|
9
|
+
import { useI18n as d } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
10
|
+
import { ArrowLeft as f, Edit3 as p, FileText as m, Maximize2 as h, Minimize2 as g, Tag as _ } from "lucide-react";
|
|
11
|
+
import { useNavigate as v } from "react-router-dom";
|
|
12
|
+
import { usePermissions as y } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
13
|
+
import { jsx as b, jsxs as x } from "react/jsx-runtime";
|
|
14
|
+
//#region src/components/docs/DocsFullScreenViewer.tsx
|
|
15
|
+
function S({ ownerType: S, ownerId: C, backLabel: w, backPath: T, editPath: E }) {
|
|
16
|
+
let { t: D } = d(), O = v(), { hasPermission: k, isLoading: A } = y(), [j, M] = u(!1), [N, P] = u(""), F = l(null), I = s((e, t) => {
|
|
17
|
+
let n = D(e);
|
|
18
|
+
return n === e ? t : n;
|
|
19
|
+
}, [D]);
|
|
20
|
+
c(() => {
|
|
21
|
+
let e = () => M(!!document.fullscreenElement);
|
|
22
|
+
return document.addEventListener("fullscreenchange", e), () => document.removeEventListener("fullscreenchange", e);
|
|
23
|
+
}, []);
|
|
24
|
+
let L = s(async () => {
|
|
25
|
+
if (F.current?.requestFullscreen) try {
|
|
26
|
+
await F.current.requestFullscreen();
|
|
27
|
+
} catch {
|
|
28
|
+
M(!0);
|
|
29
|
+
}
|
|
30
|
+
else M(!0);
|
|
31
|
+
}, []), R = s(async () => {
|
|
32
|
+
document.fullscreenElement ? await document.exitFullscreen() : M(!1);
|
|
33
|
+
}, []), { data: z, loading: B, error: V } = t({
|
|
34
|
+
variables: {
|
|
35
|
+
ownerType: S,
|
|
36
|
+
ownerId: C
|
|
37
|
+
},
|
|
38
|
+
skip: !C,
|
|
39
|
+
fetchPolicy: "cache-and-network"
|
|
40
|
+
}), H = z?.vibecontrolsDocsSiteByOwner ?? null, U = [...H?.pages ?? []].sort((e, t) => e.sidebarPosition - t.sidebarPosition), { data: W, loading: G, error: K } = e({
|
|
41
|
+
variables: {
|
|
42
|
+
siteId: H?.id || "",
|
|
43
|
+
path: N
|
|
44
|
+
},
|
|
45
|
+
skip: !H?.id || !H.currentRevisionId,
|
|
46
|
+
fetchPolicy: "network-only"
|
|
47
|
+
}), q = W?.docsContent?.html ?? null, J = q ? o(q) : null;
|
|
48
|
+
if (A) return /* @__PURE__ */ b("div", {
|
|
49
|
+
className: "flex items-center justify-center min-h-[400px]",
|
|
50
|
+
children: /* @__PURE__ */ b("p", {
|
|
51
|
+
className: "text-text-secondary",
|
|
52
|
+
children: "Loading permissions..."
|
|
53
|
+
})
|
|
54
|
+
});
|
|
55
|
+
if (!k(a.DOCS_SITE_READ)) return /* @__PURE__ */ b("div", {
|
|
56
|
+
className: "flex items-center justify-center min-h-[400px]",
|
|
57
|
+
children: /* @__PURE__ */ x("div", {
|
|
58
|
+
className: "text-center space-y-2",
|
|
59
|
+
children: [/* @__PURE__ */ b("h2", {
|
|
60
|
+
className: "text-lg font-semibold text-foreground",
|
|
61
|
+
children: "Access Denied"
|
|
62
|
+
}), /* @__PURE__ */ b("p", {
|
|
63
|
+
className: "text-sm text-text-secondary",
|
|
64
|
+
children: "You don't have permission to access this page."
|
|
65
|
+
})]
|
|
66
|
+
})
|
|
67
|
+
});
|
|
68
|
+
if (B && !H) return /* @__PURE__ */ b("div", {
|
|
69
|
+
className: "p-6",
|
|
70
|
+
children: /* @__PURE__ */ b(n, { message: I("docs.loadingDocumentation", "Loading documentation...") })
|
|
71
|
+
});
|
|
72
|
+
if (V) return /* @__PURE__ */ b("div", {
|
|
73
|
+
className: "p-6",
|
|
74
|
+
children: /* @__PURE__ */ b(r, {
|
|
75
|
+
title: I("docs.failedLoadDocs", "Failed to load docs"),
|
|
76
|
+
message: V.message
|
|
77
|
+
})
|
|
78
|
+
});
|
|
79
|
+
if (!H || !H.currentRevisionId) return /* @__PURE__ */ x("div", {
|
|
80
|
+
className: "p-6",
|
|
81
|
+
children: [/* @__PURE__ */ x("button", {
|
|
82
|
+
onClick: () => O(T),
|
|
83
|
+
className: "flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors mb-4",
|
|
84
|
+
children: [/* @__PURE__ */ b(f, { className: "w-4 h-4" }), w]
|
|
85
|
+
}), /* @__PURE__ */ x("div", {
|
|
86
|
+
className: "text-center py-12",
|
|
87
|
+
children: [/* @__PURE__ */ b("p", {
|
|
88
|
+
className: "text-text-secondary",
|
|
89
|
+
children: I("docs.noPublished", "No published documentation available.")
|
|
90
|
+
}), /* @__PURE__ */ b("button", {
|
|
91
|
+
onClick: () => O(T),
|
|
92
|
+
className: "mt-4 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors",
|
|
93
|
+
children: w
|
|
94
|
+
})]
|
|
95
|
+
})]
|
|
96
|
+
});
|
|
97
|
+
let Y = `calc(100vh - ${j || j ? "48px" : "96px"})`;
|
|
98
|
+
return /* @__PURE__ */ x("div", {
|
|
99
|
+
ref: F,
|
|
100
|
+
className: `flex flex-col bg-bg-surface ${j && !document.fullscreenElement ? "fixed inset-0 z-50" : ""}`,
|
|
101
|
+
children: [
|
|
102
|
+
/* @__PURE__ */ x("div", {
|
|
103
|
+
className: "flex flex-col gap-3 border-b border-border-default bg-bg-surface px-4 py-2 flex-shrink-0 sm:flex-row sm:items-center sm:justify-between",
|
|
104
|
+
children: [/* @__PURE__ */ x("div", {
|
|
105
|
+
className: "flex min-w-0 flex-wrap items-center gap-2 sm:gap-3",
|
|
106
|
+
children: [
|
|
107
|
+
/* @__PURE__ */ x("button", {
|
|
108
|
+
onClick: () => O(T),
|
|
109
|
+
className: "flex items-center gap-1.5 text-sm text-text-secondary hover:text-text-primary transition-colors",
|
|
110
|
+
children: [/* @__PURE__ */ b(f, { className: "w-4 h-4" }), w]
|
|
111
|
+
}),
|
|
112
|
+
/* @__PURE__ */ b("span", {
|
|
113
|
+
className: "text-border-default",
|
|
114
|
+
children: "|"
|
|
115
|
+
}),
|
|
116
|
+
/* @__PURE__ */ b("span", {
|
|
117
|
+
className: "min-w-0 break-words text-sm font-medium text-text-primary",
|
|
118
|
+
children: H.name
|
|
119
|
+
}),
|
|
120
|
+
H.currentRevision && /* @__PURE__ */ x("span", {
|
|
121
|
+
className: "text-xs text-text-muted bg-bg-sunken px-2 py-0.5 rounded",
|
|
122
|
+
children: ["Rev #", H.currentRevision.revisionNumber]
|
|
123
|
+
})
|
|
124
|
+
]
|
|
125
|
+
}), /* @__PURE__ */ x("div", {
|
|
126
|
+
className: "flex w-full items-center gap-2 sm:w-auto sm:justify-end",
|
|
127
|
+
children: [/* @__PURE__ */ x("button", {
|
|
128
|
+
onClick: () => O(E),
|
|
129
|
+
className: "flex flex-1 items-center justify-center gap-1.5 rounded-md bg-bg-sunken px-3 py-1.5 text-sm text-text-primary transition-colors hover:bg-bg-sunken/80 sm:flex-none",
|
|
130
|
+
children: [/* @__PURE__ */ b(p, { className: "w-3.5 h-3.5" }), I("common.edit", "Edit")]
|
|
131
|
+
}), j ? /* @__PURE__ */ x("button", {
|
|
132
|
+
onClick: R,
|
|
133
|
+
className: "flex items-center gap-1.5 rounded-md border border-border-default px-3 py-1.5 text-sm text-text-primary transition-colors hover:bg-bg-sunken",
|
|
134
|
+
children: [/* @__PURE__ */ b(g, { className: "w-3.5 h-3.5" }), I("docs.exitFullscreen", "Exit Fullscreen")]
|
|
135
|
+
}) : /* @__PURE__ */ b("button", {
|
|
136
|
+
onClick: L,
|
|
137
|
+
className: "p-1.5 text-text-secondary hover:text-text-primary transition-colors",
|
|
138
|
+
title: I("docs.fullscreen", "Fullscreen"),
|
|
139
|
+
children: /* @__PURE__ */ b(h, { className: "w-4 h-4" })
|
|
140
|
+
})]
|
|
141
|
+
})]
|
|
142
|
+
}),
|
|
143
|
+
!j && /* @__PURE__ */ x("div", {
|
|
144
|
+
className: "flex items-start gap-2 border-b border-border-default bg-bg-surface px-4 py-2 flex-shrink-0",
|
|
145
|
+
children: [/* @__PURE__ */ b(_, { className: "w-4 h-4 mt-1 text-text-secondary flex-shrink-0" }), /* @__PURE__ */ b("div", {
|
|
146
|
+
className: "min-w-0 flex-1",
|
|
147
|
+
children: /* @__PURE__ */ b(i, {
|
|
148
|
+
entityType: "VIBECONTROLS_DOCSSITE",
|
|
149
|
+
entityId: H.id
|
|
150
|
+
})
|
|
151
|
+
})]
|
|
152
|
+
}),
|
|
153
|
+
/* @__PURE__ */ x("div", {
|
|
154
|
+
className: "flex flex-1 min-h-0",
|
|
155
|
+
children: [U.length > 1 && /* @__PURE__ */ x("aside", {
|
|
156
|
+
className: "w-56 flex-shrink-0 border-r border-border-default bg-bg-surface overflow-y-auto",
|
|
157
|
+
style: { height: Y },
|
|
158
|
+
children: [/* @__PURE__ */ b("div", {
|
|
159
|
+
className: "px-3 py-2 border-b border-border-default",
|
|
160
|
+
children: /* @__PURE__ */ b("span", {
|
|
161
|
+
className: "text-xs font-semibold text-text-muted uppercase tracking-wide",
|
|
162
|
+
children: "Pages"
|
|
163
|
+
})
|
|
164
|
+
}), /* @__PURE__ */ b("nav", {
|
|
165
|
+
className: "py-1",
|
|
166
|
+
children: U.map((e, t) => /* @__PURE__ */ x("button", {
|
|
167
|
+
onClick: () => P(t === 0 ? "" : e.slug),
|
|
168
|
+
className: `w-full flex items-center gap-2 px-3 py-2 text-sm text-left transition-colors ${(t === 0 ? N === "" : N === e.slug) ? "bg-action-primary-bg text-action-primary-text font-medium" : "text-text-secondary hover:text-text-primary hover:bg-bg-sunken"}`,
|
|
169
|
+
children: [/* @__PURE__ */ b(m, { className: "w-3.5 h-3.5 shrink-0 opacity-60" }), /* @__PURE__ */ b("span", {
|
|
170
|
+
className: "truncate",
|
|
171
|
+
children: e.title
|
|
172
|
+
})]
|
|
173
|
+
}, e.id))
|
|
174
|
+
})]
|
|
175
|
+
}), /* @__PURE__ */ b("div", {
|
|
176
|
+
className: "flex-1 flex flex-col min-w-0",
|
|
177
|
+
children: J ? /* @__PURE__ */ b("iframe", {
|
|
178
|
+
srcDoc: J,
|
|
179
|
+
className: "w-full border-0 flex-1",
|
|
180
|
+
style: {
|
|
181
|
+
height: Y,
|
|
182
|
+
minHeight: "400px"
|
|
183
|
+
},
|
|
184
|
+
title: `${H.name} Documentation`,
|
|
185
|
+
sandbox: "allow-same-origin allow-forms allow-popups"
|
|
186
|
+
}, `${H.currentRevisionId}-${N}`) : G ? /* @__PURE__ */ b("div", {
|
|
187
|
+
className: "flex-1 flex items-center justify-center",
|
|
188
|
+
style: { height: Y },
|
|
189
|
+
children: /* @__PURE__ */ b(n, { message: I("docs.loadingDocumentation", "Loading documentation...") })
|
|
190
|
+
}) : K ? /* @__PURE__ */ b("div", {
|
|
191
|
+
className: "flex-1 flex items-center justify-center",
|
|
192
|
+
style: { height: Y },
|
|
193
|
+
children: /* @__PURE__ */ b("p", {
|
|
194
|
+
className: "text-sm text-status-danger-text",
|
|
195
|
+
children: I("docs.failedLoadDocumentation", "Failed to load documentation")
|
|
196
|
+
})
|
|
197
|
+
}) : /* @__PURE__ */ b("div", {
|
|
198
|
+
className: "flex-1 flex items-center justify-center text-text-muted",
|
|
199
|
+
style: { height: Y },
|
|
200
|
+
children: I("common.loading", "Loading...")
|
|
201
|
+
})
|
|
202
|
+
})]
|
|
203
|
+
})
|
|
204
|
+
]
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
//#endregion
|
|
208
|
+
export { S as DocsFullScreenViewer };
|
|
209
|
+
|
|
210
|
+
//# sourceMappingURL=DocsFullScreenViewer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DocsFullScreenViewer.js","names":[],"sources":["../../../src/components/docs/DocsFullScreenViewer.tsx"],"sourcesContent":["import { useState, useCallback, useEffect, useRef } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { VIBE_PERMISSIONS } from '../../constants/permissions';\nimport { ArrowLeft, Edit3, Maximize2, Minimize2, Tag, FileText } from 'lucide-react';\nimport { LoadingState, ErrorState } from '@/components/shared';\nimport { EntityTagPicker } from '@/components/shared/EntityTagPicker';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { createDocsPreviewHtml } from './previewHtml';\nimport { useDocsContentQuery, useGetVibeDocsSiteQuery } from '@/generated/wspace-operations';\nimport { VibecontrolsDocsSiteOwnerType } from '@/generated/wspace-types';\n\ninterface DocsFullScreenViewerProps {\n ownerType: 'VIBE' | 'CATALOG' | 'COMPONENT';\n ownerId: string;\n backLabel: string;\n backPath: string;\n editPath: string;\n}\n\nexport function DocsFullScreenViewer({\n ownerType,\n ownerId,\n backLabel,\n backPath,\n editPath,\n}: DocsFullScreenViewerProps) {\n const { t } = useI18n();\n const navigate = useNavigate();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const [fullscreen, setFullscreen] = useState(false);\n const [selectedPageSlug, setSelectedPageSlug] = useState('');\n const containerRef = useRef<HTMLDivElement>(null);\n\n const tr = useCallback(\n (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n },\n [t]\n );\n\n useEffect(() => {\n const handleChange = () => setFullscreen(!!document.fullscreenElement);\n document.addEventListener('fullscreenchange', handleChange);\n return () => document.removeEventListener('fullscreenchange', handleChange);\n }, []);\n\n const enterFullscreen = useCallback(async () => {\n if (containerRef.current?.requestFullscreen) {\n try {\n await containerRef.current.requestFullscreen();\n } catch {\n setFullscreen(true);\n }\n } else {\n setFullscreen(true);\n }\n }, []);\n\n const exitFullscreen = useCallback(async () => {\n if (document.fullscreenElement) {\n await document.exitFullscreen();\n } else {\n setFullscreen(false);\n }\n }, []);\n\n const {\n data: siteData,\n loading: siteLoading,\n error: siteError,\n } = useGetVibeDocsSiteQuery({\n variables: { ownerType: ownerType as VibecontrolsDocsSiteOwnerType, ownerId },\n skip: !ownerId,\n fetchPolicy: 'cache-and-network',\n });\n\n const site = siteData?.vibecontrolsDocsSiteByOwner ?? null;\n const pages = site?.pages ?? [];\n const sortedPages = [...pages].sort((a, b) => a.sidebarPosition - b.sidebarPosition);\n\n const {\n data: docsContentData,\n loading: docsContentLoading,\n error: docsContentError,\n } = useDocsContentQuery({\n variables: { siteId: site?.id || '', path: selectedPageSlug },\n skip: !site?.id || !site.currentRevisionId,\n fetchPolicy: 'network-only',\n });\n const docsHtml = docsContentData?.docsContent?.html ?? null;\n const previewHtml = docsHtml ? createDocsPreviewHtml(docsHtml) : null;\n\n if (permissionsLoading)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <p className=\"text-text-secondary\">Loading permissions...</p>\n </div>\n );\n\n if (!hasPermission(VIBE_PERMISSIONS.DOCS_SITE_READ))\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold text-foreground\">Access Denied</h2>\n <p className=\"text-sm text-text-secondary\">\n You don't have permission to access this page.\n </p>\n </div>\n </div>\n );\n\n if (siteLoading && !site)\n return (\n <div className=\"p-6\">\n <LoadingState message={tr('docs.loadingDocumentation', 'Loading documentation...')} />\n </div>\n );\n\n if (siteError)\n return (\n <div className=\"p-6\">\n <ErrorState\n title={tr('docs.failedLoadDocs', 'Failed to load docs')}\n message={siteError.message}\n />\n </div>\n );\n\n if (!site || !site.currentRevisionId)\n return (\n <div className=\"p-6\">\n <button\n onClick={() => navigate(backPath)}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors mb-4\"\n >\n <ArrowLeft className=\"w-4 h-4\" />\n {backLabel}\n </button>\n <div className=\"text-center py-12\">\n <p className=\"text-text-secondary\">\n {tr('docs.noPublished', 'No published documentation available.')}\n </p>\n <button\n onClick={() => navigate(backPath)}\n className=\"mt-4 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n {backLabel}\n </button>\n </div>\n </div>\n );\n\n const topBarHeight = fullscreen ? '48px' : !fullscreen ? '96px' : '48px';\n const contentHeight = `calc(100vh - ${topBarHeight})`;\n\n const renderContent = () => {\n if (previewHtml) {\n return (\n <iframe\n key={`${site.currentRevisionId}-${selectedPageSlug}`}\n srcDoc={previewHtml}\n className=\"w-full border-0 flex-1\"\n style={{ height: contentHeight, minHeight: '400px' }}\n title={`${site.name} Documentation`}\n sandbox=\"allow-same-origin allow-forms allow-popups\"\n />\n );\n }\n if (docsContentLoading) {\n return (\n <div className=\"flex-1 flex items-center justify-center\" style={{ height: contentHeight }}>\n <LoadingState message={tr('docs.loadingDocumentation', 'Loading documentation...')} />\n </div>\n );\n }\n if (docsContentError) {\n return (\n <div className=\"flex-1 flex items-center justify-center\" style={{ height: contentHeight }}>\n <p className=\"text-sm text-status-danger-text\">\n {tr('docs.failedLoadDocumentation', 'Failed to load documentation')}\n </p>\n </div>\n );\n }\n return (\n <div\n className=\"flex-1 flex items-center justify-center text-text-muted\"\n style={{ height: contentHeight }}\n >\n {tr('common.loading', 'Loading...')}\n </div>\n );\n };\n\n return (\n <div\n ref={containerRef}\n className={`flex flex-col bg-bg-surface ${fullscreen && !document.fullscreenElement ? 'fixed inset-0 z-50' : ''}`}\n >\n {/* Top bar */}\n <div className=\"flex flex-col gap-3 border-b border-border-default bg-bg-surface px-4 py-2 flex-shrink-0 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex min-w-0 flex-wrap items-center gap-2 sm:gap-3\">\n <button\n onClick={() => navigate(backPath)}\n className=\"flex items-center gap-1.5 text-sm text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"w-4 h-4\" />\n {backLabel}\n </button>\n <span className=\"text-border-default\">|</span>\n <span className=\"min-w-0 break-words text-sm font-medium text-text-primary\">\n {site.name}\n </span>\n {site.currentRevision && (\n <span className=\"text-xs text-text-muted bg-bg-sunken px-2 py-0.5 rounded\">\n Rev #{site.currentRevision.revisionNumber}\n </span>\n )}\n </div>\n <div className=\"flex w-full items-center gap-2 sm:w-auto sm:justify-end\">\n <button\n onClick={() => navigate(editPath)}\n className=\"flex flex-1 items-center justify-center gap-1.5 rounded-md bg-bg-sunken px-3 py-1.5 text-sm text-text-primary transition-colors hover:bg-bg-sunken/80 sm:flex-none\"\n >\n <Edit3 className=\"w-3.5 h-3.5\" />\n {tr('common.edit', 'Edit')}\n </button>\n {fullscreen ? (\n <button\n onClick={exitFullscreen}\n className=\"flex items-center gap-1.5 rounded-md border border-border-default px-3 py-1.5 text-sm text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n <Minimize2 className=\"w-3.5 h-3.5\" />\n {tr('docs.exitFullscreen', 'Exit Fullscreen')}\n </button>\n ) : (\n <button\n onClick={enterFullscreen}\n className=\"p-1.5 text-text-secondary hover:text-text-primary transition-colors\"\n title={tr('docs.fullscreen', 'Fullscreen')}\n >\n <Maximize2 className=\"w-4 h-4\" />\n </button>\n )}\n </div>\n </div>\n\n {/* Tags — hidden in fullscreen */}\n {!fullscreen && (\n <div className=\"flex items-start gap-2 border-b border-border-default bg-bg-surface px-4 py-2 flex-shrink-0\">\n <Tag className=\"w-4 h-4 mt-1 text-text-secondary flex-shrink-0\" />\n <div className=\"min-w-0 flex-1\">\n <EntityTagPicker entityType=\"VIBECONTROLS_DOCSSITE\" entityId={site.id} />\n </div>\n </div>\n )}\n\n {/* Body: sidebar + content */}\n <div className=\"flex flex-1 min-h-0\">\n {/* Page sidebar — only shown when there are multiple pages */}\n {sortedPages.length > 1 && (\n <aside\n className=\"w-56 flex-shrink-0 border-r border-border-default bg-bg-surface overflow-y-auto\"\n style={{ height: contentHeight }}\n >\n <div className=\"px-3 py-2 border-b border-border-default\">\n <span className=\"text-xs font-semibold text-text-muted uppercase tracking-wide\">\n Pages\n </span>\n </div>\n <nav className=\"py-1\">\n {sortedPages.map((page, i) => {\n const isSelected =\n i === 0 ? selectedPageSlug === '' : selectedPageSlug === page.slug;\n return (\n <button\n key={page.id}\n onClick={() => setSelectedPageSlug(i === 0 ? '' : page.slug)}\n className={`w-full flex items-center gap-2 px-3 py-2 text-sm text-left transition-colors ${\n isSelected\n ? 'bg-action-primary-bg text-action-primary-text font-medium'\n : 'text-text-secondary hover:text-text-primary hover:bg-bg-sunken'\n }`}\n >\n <FileText className=\"w-3.5 h-3.5 shrink-0 opacity-60\" />\n <span className=\"truncate\">{page.title}</span>\n </button>\n );\n })}\n </nav>\n </aside>\n )}\n\n {/* Content area */}\n <div className=\"flex-1 flex flex-col min-w-0\">{renderContent()}</div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|