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 in ab03b17 ("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 in 0746844. 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:
brunorezio
2026-07-25 23:30:20 +01:00
co-authored by Claude Opus 5
parent 78130f21ce
commit 1fa3a659bc
14 changed files with 33 additions and 51 deletions
@@ -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 './Files';
export * from './CodeEditor';
export * from './ChatHistory';
export * from './Dashboards';
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';
export type AppRegistryMeta = { key: string } & AppRegistryEntry;
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) => {
setRegistry((prev) => ({ ...prev, [key]: entry }));
@@ -15,5 +15,5 @@ export function useAppRegistry(initialApps: AppRegistryMeta[] = []) {
export type UseAppRegistryType = ReturnType<typeof useAppRegistry>;
const metasToRegistry = (metas: AppRegistryMeta[]): AppRegistry =>
const metasToRegistry = (metas: AppRegistryMeta[]): AppRegistryMap =>
Object.fromEntries(metas.map(({ key, ...entry }) => [key, entry]));
@@ -1,7 +1,7 @@
import type { AppRegistry } from './types';
import type { AppRegistryMap } from './types';
type AppPickerProps = {
registry: AppRegistry;
registry: AppRegistryMap;
onSelect: (appType: string) => void;
};
@@ -2,7 +2,7 @@ import type { ComponentType } from 'react';
import { useCallback } from 'react';
import { createPortal } from 'react-dom';
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 { Card } from '@/components/Card';
import { AppPicker } from './AppPicker';
@@ -16,7 +16,7 @@ import {
type PanelSlotProps = {
panel: LayoutPanel;
registry: AppRegistry;
registry: AppRegistryMap;
components?: PanelComponents;
interactive: boolean;
locked: boolean;
@@ -1,5 +1,5 @@
import { useCallback } from 'react';
import type { LayoutNode, AppRegistry, PanelComponents } from './types';
import type { LayoutNode, AppRegistryMap, PanelComponents } from './types';
import { updateSizes } from './layout-utils';
import { WorkspaceProvider } from './WorkspaceContext';
import { WorkspaceRenderer } from './WorkspaceRenderer';
@@ -8,7 +8,7 @@ import { useAppRegistry } from '../../AppRegistry/useAppRegistry';
type WorkspaceLayoutProps = {
layout: LayoutNode;
onLayoutChange: (layout: LayoutNode) => void;
registry?: AppRegistry;
registry?: AppRegistryMap;
components?: PanelComponents;
dashboardId?: string;
cwd?: string;
@@ -1,12 +1,12 @@
import { useCallback, useRef } from 'react';
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 { PanelSlot } from './PanelSlot';
type WorkspaceRendererProps = {
layout: LayoutNode;
registry: AppRegistry;
registry: AppRegistryMap;
components?: PanelComponents;
interactive?: boolean;
locked?: boolean;
@@ -58,7 +58,7 @@ export const WorkspaceRenderer = ({
type LayoutNodeRendererProps = {
node: LayoutNode;
registry: AppRegistry;
registry: AppRegistryMap;
components?: PanelComponents;
interactive: boolean;
locked: boolean;
@@ -72,7 +72,7 @@ type LayoutNodeRendererProps = {
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;
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 { createDefaultLayout, splitPanel, removePanel, setApp, updateSizes, swapPanels, movePanel, pruneEmptyPanels, countPanels, hasAnyApp } from './layout-utils';
export type { DefaultFileSort } from './WorkspaceContext';
@@ -60,7 +60,7 @@ export type AppRegistryEntry = {
availableOnPanel?: boolean;
};
export type AppRegistry = Record<string, AppRegistryEntry>;
export type AppRegistryMap = Record<string, AppRegistryEntry>;
export type PanelComponentEntry = {
component: ComponentType;
+1 -1
View File
@@ -104,7 +104,7 @@ export type {
DashboardState,
ProjectType,
ProjectDefinition,
AppRegistry,
AppRegistryMap,
AppRegistryEntry,
PanelComponents,
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 {};
}
-2
View File
@@ -68,7 +68,6 @@ export type UserSettings = {
};
appearance: {
colorMode: 'light' | 'dark';
colorTheme: string;
};
languages: {
spoken: string[];
@@ -105,7 +104,6 @@ export const DEFAULT_SETTINGS: UserSettings = {
},
appearance: {
colorMode: 'light',
colorTheme: 'DuckPond',
},
languages: {
spoken: ['en'],