feat(foundry): refine map application controls
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
||||
AppHeader,
|
||||
ApplicationPanel,
|
||||
ApplicationShell,
|
||||
ApplicationSidePanel,
|
||||
Button,
|
||||
Checker,
|
||||
ColorField,
|
||||
@@ -318,6 +319,9 @@ export function CatalogApp() {
|
||||
const [mapTemplateSaveState, setMapTemplateSaveState] = useState<"idle" | "loading" | "saving" | "saved" | "error">("loading");
|
||||
const mapTemplatePreviewRef = useRef<MapFixturePreviewHandle>(null);
|
||||
const applicationMapPreviewRef = useRef<MapFixturePreviewHandle>(null);
|
||||
const [mapSettingsPanelHost, setMapSettingsPanelHost] = useState<HTMLDivElement | null>(null);
|
||||
const [mapHeaderActionsHost, setMapHeaderActionsHost] = useState<HTMLDivElement | null>(null);
|
||||
const [mapSettingsPanelOpen, setMapSettingsPanelOpen] = useState(false);
|
||||
const [createModuleOpen, setCreateModuleOpen] = useState(false);
|
||||
const [createModuleName, setCreateModuleName] = useState("");
|
||||
const [createModuleSlug, setCreateModuleSlug] = useState("");
|
||||
@@ -355,6 +359,7 @@ export function CatalogApp() {
|
||||
const [workspaceWindowDemoOpen, setWorkspaceWindowDemoOpen] = useState(true);
|
||||
const [workspaceWindowDemoMaximized, setWorkspaceWindowDemoMaximized] = useState(false);
|
||||
const [workspaceWindowDemoRect, setWorkspaceWindowDemoRect] = useState<WorkspaceWindowRect>({ x: 24, y: 24, width: 340, height: 230 });
|
||||
const [sidePanelDemoOpen, setSidePanelDemoOpen] = useState(true);
|
||||
const [createModalOpen, setCreateModalOpen] = useState(false);
|
||||
const [confirmOpen, setConfirmOpen] = useState(false);
|
||||
const [shareAccessOpen, setShareAccessOpen] = useState(false);
|
||||
@@ -1413,6 +1418,23 @@ export function CatalogApp() {
|
||||
</div>
|
||||
<p className="catalog-preview__explanation">Rectangle, maximize, close и stacking остаются состоянием приложения; дизайн-система владеет одинаковой bounded-геометрией и доступным управлением.</p>
|
||||
</Preview>
|
||||
<Preview title="Application side panel" note="end / push / controlled" className="catalog-preview--wide catalog-side-panel-preview">
|
||||
<div className="catalog-side-panel-demo">
|
||||
{sidePanelDemoOpen ? (
|
||||
<ApplicationSidePanel
|
||||
eyebrow="MAP / SETTINGS"
|
||||
title="Настройки карты"
|
||||
description="Theme-aware application panel"
|
||||
onClose={() => setSidePanelDemoOpen(false)}
|
||||
>
|
||||
<Inspector variant="panel" sections={environmentSections.slice(0, 3)} defaultOpen={[environmentSections[0]?.id ?? ""]} singleOpen />
|
||||
</ApplicationSidePanel>
|
||||
) : (
|
||||
<Button shape="pill" icon={<Icon name="panel" />} onClick={() => setSidePanelDemoOpen(true)}>Открыть правую панель</Button>
|
||||
)}
|
||||
</div>
|
||||
<p className="catalog-preview__explanation">Панель занимает отдельную end-колонку ApplicationShell, сдвигает рабочую область, наследует тему и не входит в z-index stack окон карты.</p>
|
||||
</Preview>
|
||||
<Preview title="Inspector" note="modeless / draggable" className="catalog-preview--wide catalog-preview--compact catalog-inspector-launcher">
|
||||
<p className="catalog-preview__explanation">Настройки приложения и Toolbar открываются в отдельном перемещаемом Inspector и сохраняются одним серверным layout.</p>
|
||||
<Button variant="primary" shape="pill" icon={<Icon name="panel" />} onClick={() => setInspectorOpen(true)}>Открыть Inspector</Button>
|
||||
@@ -1794,6 +1816,9 @@ export function CatalogApp() {
|
||||
expanded
|
||||
initialLayout={mapDesignLayout}
|
||||
features={Object.fromEntries(template.features.map((feature) => [feature.id, feature.required ? true : feature.defaultVisible]))}
|
||||
settingsPanelHost={mapSettingsPanelHost}
|
||||
headerActionsHost={mapHeaderActionsHost}
|
||||
onSettingsPanelOpenChange={setMapSettingsPanelOpen}
|
||||
/>
|
||||
<div className="catalog-page-template__actions">
|
||||
<Button variant="primary" shape="pill" icon={<Icon name="plus" />} onClick={() => { void createApplicationDraft(template); }}>Создать Application Draft</Button>
|
||||
@@ -1807,7 +1832,12 @@ export function CatalogApp() {
|
||||
title={template.title}
|
||||
description={template.description}
|
||||
>
|
||||
<MapFixturePreview features={Object.fromEntries(template.features.map((feature) => [feature.id, feature.required ? true : feature.defaultVisible]))} />
|
||||
<MapFixturePreview
|
||||
features={Object.fromEntries(template.features.map((feature) => [feature.id, feature.required ? true : feature.defaultVisible]))}
|
||||
settingsPanelHost={mapSettingsPanelHost}
|
||||
headerActionsHost={mapHeaderActionsHost}
|
||||
onSettingsPanelOpenChange={setMapSettingsPanelOpen}
|
||||
/>
|
||||
<div className="catalog-page-template__actions">
|
||||
<Button variant="primary" shape="pill" icon={<Icon name="plus" />} onClick={() => { void createApplicationDraft(template); }}>Создать Application Draft</Button>
|
||||
<span>Только утверждённые features и slots — без свободного canvas.</span>
|
||||
@@ -1860,6 +1890,9 @@ export function CatalogApp() {
|
||||
initialLayout={resolvedMapLayout}
|
||||
features={page.features}
|
||||
expanded
|
||||
settingsPanelHost={mapSettingsPanelHost}
|
||||
headerActionsHost={mapHeaderActionsHost}
|
||||
onSettingsPanelOpenChange={setMapSettingsPanelOpen}
|
||||
/>
|
||||
{applicationMode === "edit" ? (
|
||||
<SettingsCard eyebrow="PAGE SETTINGS" title={page.title} description={`${template.title} · ${template.version}`}>
|
||||
@@ -1888,6 +1921,8 @@ export function CatalogApp() {
|
||||
navigationOpen={guidelineOpen}
|
||||
contentOpen={workspace.contentOpen}
|
||||
contentExpanded={panelExpanded}
|
||||
endPanelOpen={mapSettingsPanelOpen}
|
||||
endPanel={<div ref={setMapSettingsPanelHost} className="catalog-map-settings-panel-host" />}
|
||||
header={
|
||||
<AppHeader
|
||||
brand={<img src="/nodedc-logo.svg" alt="NODE.DC" />}
|
||||
@@ -2035,6 +2070,7 @@ export function CatalogApp() {
|
||||
description={`${activePageTemplate.category} · contract ${activePageTemplate.schemaVersion} · template ${activePageTemplate.version}`}
|
||||
expanded={panelExpanded}
|
||||
onExpandedChange={workspace.setContentExpanded}
|
||||
headerTools={activePageTemplate.id === "map" ? <div ref={setMapHeaderActionsHost} className="catalog-map-header-actions-host" /> : undefined}
|
||||
utilityActions={activePageTemplate.id === "map" ? [{
|
||||
label: mapTemplateSaveState === "saving" ? "Сохраняем Map-фрагмент в Design Profile" : mapTemplateSaveState === "error" ? "Повторить сохранение Map-фрагмента" : "Сохранить дизайн Map в Design Profile",
|
||||
icon: "save",
|
||||
@@ -2053,6 +2089,7 @@ export function CatalogApp() {
|
||||
description={activeApplicationPage ? `${activeApplication.metadata.name} · ${activeApplicationPage.template.id}@${activeApplicationPage.template.version}` : `/${activeApplication.metadata.slug} · manifest ${activeApplication.schemaVersion}`}
|
||||
expanded={panelExpanded}
|
||||
onExpandedChange={workspace.setContentExpanded}
|
||||
headerTools={activeApplicationPage?.template.id === "map" ? <div ref={setMapHeaderActionsHost} className="catalog-map-header-actions-host" /> : undefined}
|
||||
utilityActions={[{
|
||||
label: applicationSaveState === "saving" ? "Сохранение…" : applicationSaveState === "error" ? "Повторить сохранение" : "Сохранить",
|
||||
icon: "save",
|
||||
|
||||
Reference in New Issue
Block a user