restore the code editor screen, drop the dead theme picker, unshadow AppRegistry
Three unrelated type errors that each pointed at something actually broken: - Dashboard.CodeEditor was deleted inab03b17("Projects") while the /code-editor route and the dock's Editor item kept pointing at it, so the route rendered undefined. Screen restored. - Appearance.tsx imported 'themes', a workspace deleted in0746844. Nothing reads settings.appearance.colorTheme and no theme CSS survives, so the picker was writing a value with no consumer. Removed it and the setting; colorMode stays, it is live. - officerdev exported both a component and a type named AppRegistry, so `import { AppRegistry }` resolved to the type and <AppRegistry /> failed to typecheck. Renamed the Record type to AppRegistryMap. Also declares "*.css" so side-effect stylesheet imports resolve. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
78130f21ce
commit
1fa3a659bc
Vendored
+4
@@ -8,6 +8,10 @@ declare module "*.svg" {
|
|||||||
export = path;
|
export = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Plain stylesheets are imported for their side effect only; the bundler injects them. The more
|
||||||
|
// specific "*.module.css" declaration below still wins for CSS modules.
|
||||||
|
declare module "*.css";
|
||||||
|
|
||||||
declare module "*.module.css" {
|
declare module "*.module.css" {
|
||||||
/**
|
/**
|
||||||
* A record of class names to their corresponding CSS module classes
|
* A record of class names to their corresponding CSS module classes
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { CodeEditorView } from 'officerdev';
|
||||||
|
import { Widget } from 'widgets/Widget';
|
||||||
|
|
||||||
|
export const CodeEditor = () => (
|
||||||
|
<div className="h-full w-full flex items-center justify-center">
|
||||||
|
<Widget title="Code Editor" className="h-[70vh] w-[70vw] overflow-hidden" resizable moveable>
|
||||||
|
<CodeEditorView className="h-full w-full" />
|
||||||
|
</Widget>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
import { useSettings } from 'state/useSettings';
|
|
||||||
import { themes } from 'themes';
|
|
||||||
|
|
||||||
export const Appearance = () => {
|
|
||||||
const { settings, saveSettings } = useSettings();
|
|
||||||
|
|
||||||
const handleColorThemeChange = (colorTheme: string) => {
|
|
||||||
saveSettings({ ...settings, appearance: { ...settings.appearance, colorTheme } });
|
|
||||||
};
|
|
||||||
|
|
||||||
const activeColorTheme = settings.appearance.colorTheme ?? 'DuckPond';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="grid grid-cols-2 sm:grid-cols-3 gap-2 pt-2">
|
|
||||||
{themes.map((t) => (
|
|
||||||
<button
|
|
||||||
key={t.id}
|
|
||||||
type="button"
|
|
||||||
onClick={() => handleColorThemeChange(t.id)}
|
|
||||||
className={`rounded-md px-3 py-2.5 text-sm font-medium cursor-pointer transition-colors ${
|
|
||||||
activeColorTheme === t.id
|
|
||||||
? 'bg-duck-teal text-white ring-2 ring-duck-teal/50'
|
|
||||||
: 'bg-secondary text-secondary-foreground hover:bg-secondary/80'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{t.name}
|
|
||||||
</button>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -11,6 +11,7 @@ export * from './TaskLogs';
|
|||||||
export * from './Tasks';
|
export * from './Tasks';
|
||||||
|
|
||||||
export * from './Files';
|
export * from './Files';
|
||||||
|
export * from './CodeEditor';
|
||||||
export * from './ChatHistory';
|
export * from './ChatHistory';
|
||||||
export * from './Dashboards';
|
export * from './Dashboards';
|
||||||
export * from './Projects';
|
export * from './Projects';
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import type { AppRegistry, AppRegistryEntry } from '../../components/Workspace';
|
import type { AppRegistryMap, AppRegistryEntry } from '../../components/Workspace';
|
||||||
import { useGlobal } from 'hooks/useGlobal';
|
import { useGlobal } from 'hooks/useGlobal';
|
||||||
|
|
||||||
export type AppRegistryMeta = { key: string } & AppRegistryEntry;
|
export type AppRegistryMeta = { key: string } & AppRegistryEntry;
|
||||||
|
|
||||||
export function useAppRegistry(initialApps: AppRegistryMeta[] = []) {
|
export function useAppRegistry(initialApps: AppRegistryMeta[] = []) {
|
||||||
const [registry, setRegistry] = useGlobal<AppRegistry>('APP_REGISTRY', () => metasToRegistry(initialApps));
|
const [registry, setRegistry] = useGlobal<AppRegistryMap>('APP_REGISTRY', () => metasToRegistry(initialApps));
|
||||||
|
|
||||||
const registerApp = (key: string, entry: AppRegistryEntry) => {
|
const registerApp = (key: string, entry: AppRegistryEntry) => {
|
||||||
setRegistry((prev) => ({ ...prev, [key]: entry }));
|
setRegistry((prev) => ({ ...prev, [key]: entry }));
|
||||||
@@ -15,5 +15,5 @@ export function useAppRegistry(initialApps: AppRegistryMeta[] = []) {
|
|||||||
|
|
||||||
export type UseAppRegistryType = ReturnType<typeof useAppRegistry>;
|
export type UseAppRegistryType = ReturnType<typeof useAppRegistry>;
|
||||||
|
|
||||||
const metasToRegistry = (metas: AppRegistryMeta[]): AppRegistry =>
|
const metasToRegistry = (metas: AppRegistryMeta[]): AppRegistryMap =>
|
||||||
Object.fromEntries(metas.map(({ key, ...entry }) => [key, entry]));
|
Object.fromEntries(metas.map(({ key, ...entry }) => [key, entry]));
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { AppRegistry } from './types';
|
import type { AppRegistryMap } from './types';
|
||||||
|
|
||||||
type AppPickerProps = {
|
type AppPickerProps = {
|
||||||
registry: AppRegistry;
|
registry: AppRegistryMap;
|
||||||
onSelect: (appType: string) => void;
|
onSelect: (appType: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import type { ComponentType } from 'react';
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import { ArrowLeftRight, ChevronLeft, X, Minus } from 'lucide-react';
|
import { ArrowLeftRight, ChevronLeft, X, Minus } from 'lucide-react';
|
||||||
import type { LayoutPanel, AppRegistry, PanelComponents, PanelComponentEntry } from './types';
|
import type { LayoutPanel, AppRegistryMap, PanelComponents, PanelComponentEntry } from './types';
|
||||||
import { useWorkspace } from './WorkspaceContext';
|
import { useWorkspace } from './WorkspaceContext';
|
||||||
import { Card } from '@/components/Card';
|
import { Card } from '@/components/Card';
|
||||||
import { AppPicker } from './AppPicker';
|
import { AppPicker } from './AppPicker';
|
||||||
@@ -16,7 +16,7 @@ import {
|
|||||||
|
|
||||||
type PanelSlotProps = {
|
type PanelSlotProps = {
|
||||||
panel: LayoutPanel;
|
panel: LayoutPanel;
|
||||||
registry: AppRegistry;
|
registry: AppRegistryMap;
|
||||||
components?: PanelComponents;
|
components?: PanelComponents;
|
||||||
interactive: boolean;
|
interactive: boolean;
|
||||||
locked: boolean;
|
locked: boolean;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import type { LayoutNode, AppRegistry, PanelComponents } from './types';
|
import type { LayoutNode, AppRegistryMap, PanelComponents } from './types';
|
||||||
import { updateSizes } from './layout-utils';
|
import { updateSizes } from './layout-utils';
|
||||||
import { WorkspaceProvider } from './WorkspaceContext';
|
import { WorkspaceProvider } from './WorkspaceContext';
|
||||||
import { WorkspaceRenderer } from './WorkspaceRenderer';
|
import { WorkspaceRenderer } from './WorkspaceRenderer';
|
||||||
@@ -8,7 +8,7 @@ import { useAppRegistry } from '../../AppRegistry/useAppRegistry';
|
|||||||
type WorkspaceLayoutProps = {
|
type WorkspaceLayoutProps = {
|
||||||
layout: LayoutNode;
|
layout: LayoutNode;
|
||||||
onLayoutChange: (layout: LayoutNode) => void;
|
onLayoutChange: (layout: LayoutNode) => void;
|
||||||
registry?: AppRegistry;
|
registry?: AppRegistryMap;
|
||||||
components?: PanelComponents;
|
components?: PanelComponents;
|
||||||
dashboardId?: string;
|
dashboardId?: string;
|
||||||
cwd?: string;
|
cwd?: string;
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { useCallback, useRef } from 'react';
|
import { useCallback, useRef } from 'react';
|
||||||
import { ResizablePanel, ResizablePanelGroup, ResizableHandle } from '@/components/ui/resizable';
|
import { ResizablePanel, ResizablePanelGroup, ResizableHandle } from '@/components/ui/resizable';
|
||||||
import type { LayoutNode, AppRegistry, PanelComponents } from './types';
|
import type { LayoutNode, AppRegistryMap, PanelComponents } from './types';
|
||||||
import { countPanels } from './layout-utils';
|
import { countPanels } from './layout-utils';
|
||||||
import { PanelSlot } from './PanelSlot';
|
import { PanelSlot } from './PanelSlot';
|
||||||
|
|
||||||
type WorkspaceRendererProps = {
|
type WorkspaceRendererProps = {
|
||||||
layout: LayoutNode;
|
layout: LayoutNode;
|
||||||
registry: AppRegistry;
|
registry: AppRegistryMap;
|
||||||
components?: PanelComponents;
|
components?: PanelComponents;
|
||||||
interactive?: boolean;
|
interactive?: boolean;
|
||||||
locked?: boolean;
|
locked?: boolean;
|
||||||
@@ -58,7 +58,7 @@ export const WorkspaceRenderer = ({
|
|||||||
|
|
||||||
type LayoutNodeRendererProps = {
|
type LayoutNodeRendererProps = {
|
||||||
node: LayoutNode;
|
node: LayoutNode;
|
||||||
registry: AppRegistry;
|
registry: AppRegistryMap;
|
||||||
components?: PanelComponents;
|
components?: PanelComponents;
|
||||||
interactive: boolean;
|
interactive: boolean;
|
||||||
locked: boolean;
|
locked: boolean;
|
||||||
@@ -72,7 +72,7 @@ type LayoutNodeRendererProps = {
|
|||||||
onResized: (groupId: string, sizes: number[]) => void;
|
onResized: (groupId: string, sizes: number[]) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getFixedHeight = (node: LayoutNode, registry: AppRegistry): number | undefined => {
|
const getFixedHeight = (node: LayoutNode, registry: AppRegistryMap): number | undefined => {
|
||||||
if (node.type === 'panel' && node.appType) return registry[node.appType]?.fixedHeight;
|
if (node.type === 'panel' && node.appType) return registry[node.appType]?.fixedHeight;
|
||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export type { LayoutNode, LayoutGroup, LayoutPanel, DashboardDefinition, DashboardState, ProjectType, ProjectDefinition, AppRegistry, AppRegistryEntry, PanelComponents, PanelComponentEntry, EphemeralPanels, HomeRoot } from './types';
|
export type { LayoutNode, LayoutGroup, LayoutPanel, DashboardDefinition, DashboardState, ProjectType, ProjectDefinition, AppRegistryMap, AppRegistryEntry, PanelComponents, PanelComponentEntry, EphemeralPanels, HomeRoot } from './types';
|
||||||
export type { DropPosition } from './layout-utils';
|
export type { DropPosition } from './layout-utils';
|
||||||
export { createDefaultLayout, splitPanel, removePanel, setApp, updateSizes, swapPanels, movePanel, pruneEmptyPanels, countPanels, hasAnyApp } from './layout-utils';
|
export { createDefaultLayout, splitPanel, removePanel, setApp, updateSizes, swapPanels, movePanel, pruneEmptyPanels, countPanels, hasAnyApp } from './layout-utils';
|
||||||
export type { DefaultFileSort } from './WorkspaceContext';
|
export type { DefaultFileSort } from './WorkspaceContext';
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export type AppRegistryEntry = {
|
|||||||
availableOnPanel?: boolean;
|
availableOnPanel?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AppRegistry = Record<string, AppRegistryEntry>;
|
export type AppRegistryMap = Record<string, AppRegistryEntry>;
|
||||||
|
|
||||||
export type PanelComponentEntry = {
|
export type PanelComponentEntry = {
|
||||||
component: ComponentType;
|
component: ComponentType;
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ export type {
|
|||||||
DashboardState,
|
DashboardState,
|
||||||
ProjectType,
|
ProjectType,
|
||||||
ProjectDefinition,
|
ProjectDefinition,
|
||||||
AppRegistry,
|
AppRegistryMap,
|
||||||
AppRegistryEntry,
|
AppRegistryEntry,
|
||||||
PanelComponents,
|
PanelComponents,
|
||||||
PanelComponentEntry,
|
PanelComponentEntry,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { AppRegistry } from './components/Workspace';
|
import type { AppRegistryMap } from './components/Workspace';
|
||||||
|
|
||||||
export function useAppRegistry(): AppRegistry {
|
export function useAppRegistry(): AppRegistryMap {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ export type UserSettings = {
|
|||||||
};
|
};
|
||||||
appearance: {
|
appearance: {
|
||||||
colorMode: 'light' | 'dark';
|
colorMode: 'light' | 'dark';
|
||||||
colorTheme: string;
|
|
||||||
};
|
};
|
||||||
languages: {
|
languages: {
|
||||||
spoken: string[];
|
spoken: string[];
|
||||||
@@ -105,7 +104,6 @@ export const DEFAULT_SETTINGS: UserSettings = {
|
|||||||
},
|
},
|
||||||
appearance: {
|
appearance: {
|
||||||
colorMode: 'light',
|
colorMode: 'light',
|
||||||
colorTheme: 'DuckPond',
|
|
||||||
},
|
},
|
||||||
languages: {
|
languages: {
|
||||||
spoken: ['en'],
|
spoken: ['en'],
|
||||||
|
|||||||
Reference in New Issue
Block a user