# TASK-005 Session Plan for Cline ## Context You are migrating `ComponentsPanel.ts` from a legacy jQuery/underscore.js View to a modern React component. This is a prerequisite for TASK-004's migration badges feature. **Philosophy:** "When we touch a component, we clean it properly" - full React rewrite, no jQuery, proper TypeScript. --- ## Session 1: Foundation (Start Here) ### Goal Create the component structure and get it rendering in the sidebar. ### Steps 1. **Create directory structure:** ``` packages/noodl-editor/src/editor/src/views/panels/ComponentsPanel/ ├── ComponentsPanel.tsx ├── ComponentsPanel.module.scss ├── components/ ├── hooks/ ├── types.ts └── index.ts ``` 2. **Define types in `types.ts`:** ```typescript import { ComponentModel } from '@noodl-models/componentmodel'; export interface ComponentItemData { id: string; name: string; localName: string; component: ComponentModel; isRoot: boolean; isPage: boolean; isCloudFunction: boolean; isVisual: boolean; hasWarnings: boolean; } export interface FolderItemData { name: string; path: string; isOpen: boolean; isComponentFolder: boolean; component?: ComponentModel; children: TreeNode[]; } export type TreeNode = | { type: 'component'; data: ComponentItemData } | { type: 'folder'; data: FolderItemData }; export interface ComponentsPanelProps { options?: { showSheetList?: boolean; hideSheets?: string[]; }; } ``` 3. **Create basic `ComponentsPanel.tsx`:** ```typescript import React from 'react'; import css from './ComponentsPanel.module.scss'; export function ComponentsPanel({ options }: ComponentsPanelProps) { return (
Components
{/* Tree will go here */}
ComponentsPanel React migration in progress...
); } ``` 4. **Update `router.setup.ts`:** ```typescript // Change import import { ComponentsPanel } from './views/panels/ComponentsPanel'; // In register call, panel should now be the React component SidebarModel.instance.register({ id: 'components', name: 'Components', order: 1, icon: IconName.Components, onOpen: () => { /* ... */ }, panelProps: { options: { showSheetList: true, hideSheets: ['__cloud__'] } }, panel: ComponentsPanel // React component }); ``` 5. **Port base styles to `ComponentsPanel.module.scss`** from `styles/componentspanel.css` ### Verify - [ ] Panel appears when clicking Components icon in sidebar - [ ] Placeholder text visible - [ ] No console errors --- ## Session 2: Tree Rendering ### Goal Render the actual component tree from ProjectModel. ### Steps 1. **Create `hooks/useComponentsPanel.ts`:** - Subscribe to ProjectModel using `useModernModel` - Build tree structure from components - Track expanded folders in useState - Track selected item in useState 2. **Port tree building logic** from `ComponentsPanel.ts`: - `addComponentToFolderStructure()` - `getFolderForComponentWithName()` - Handle sheet filtering 3. **Create `components/ComponentTree.tsx`:** - Recursive renderer - Pass tree data and handlers 4. **Create `components/ComponentItem.tsx`:** - Single row for component - Icon based on type (use getComponentIconType) - Selection state - Warning indicator 5. **Create `components/FolderItem.tsx`:** - Folder row with caret - Expand/collapse on click - Render children when expanded ### Verify - [ ] Tree structure matches original - [ ] Folders expand/collapse - [ ] Selection works - [ ] Icons correct --- ## Session 3: Context Menus ### Goal Implement all context menu functionality. ### Steps 1. **Create `components/AddComponentMenu.tsx`:** - Uses ComponentTemplates.instance.getTemplates() - Renders PopupMenu with template options + Folder 2. **Wire header "+" button** to show AddComponentMenu 3. **Add context menu to ComponentItem:** - Right-click handler - Menu: Add submenu, Make home, Rename, Duplicate, Delete 4. **Add context menu to FolderItem:** - Right-click handler - Menu: Add submenu, Make home (if folder component), Rename, Duplicate, Delete 5. **Port action handlers:** - `performAdd()` - create component/folder - `onDeleteClicked()` - with confirmation - `onDuplicateClicked()` / `onDuplicateFolderClicked()` ### Verify - [ ] All menu items appear - [ ] Actions work correctly - [ ] Undo works --- ## Session 4: Drag-Drop ### Goal Implement drag-drop for reorganizing components. ### Steps 1. **Create `hooks/useDragDrop.ts`:** - Track drag state - Integrate with PopupLayer.instance 2. **Add drag handlers to items:** - mousedown/mousemove pattern from original - Call PopupLayer.startDragging() 3. **Add drop zone handlers:** - Folders are drop targets - Top-level area is drop target - Show visual feedback 4. **Port drop logic:** - `getAcceptableDropType()` - validation - `dropOn()` - execution with undo ### Verify - [ ] Dragging shows label - [ ] Valid targets highlight - [ ] Invalid targets show feedback - [ ] Drops work correctly - [ ] Undo works --- ## Session 5: Inline Rename + Sheets ### Goal Complete rename functionality and sheet selector. ### Steps 1. **Create `hooks/useRenameMode.ts`:** - Track which item is being renamed - Handle Enter/Escape/blur 2. **Add rename input UI:** - Replaces label when in rename mode - Auto-select text - Validation 3. **Create `components/SheetSelector.tsx`:** - Tab list from ProjectModel sheets - Handle hideSheets option - Switch current sheet on click 4. **Integrate SheetSelector:** - Only show if options.showSheetList - Filter tree by current sheet ### Verify - [ ] Rename via double-click works - [ ] Rename via menu works - [ ] Sheets display and switch correctly --- ## Session 6: Polish + Cleanup ### Goal Final cleanup, remove old files, prepare for TASK-004. ### Steps 1. **Style polish:** - Match exact spacing/sizing - Hover and focus states 2. **Code cleanup:** - Remove any `any` types - Add JSDoc comments - Consistent naming 3. **Remove old files:** - Delete `views/panels/componentspanel/ComponentsPanel.ts` - Delete `templates/componentspanel.html` - Update remaining imports 4. **TASK-004 preparation:** - Add `migrationStatus` to ComponentItemData - Add badge placeholder in ComponentItem - Document extension points 5. **Update CHANGELOG.md** ### Verify - [ ] All functionality works - [ ] No errors - [ ] Old files removed - [ ] Ready for badges feature --- ## Key Files Reference **Read these first:** - `views/panels/componentspanel/ComponentsPanel.ts` - Logic to port - `templates/componentspanel.html` - UI structure reference - `views/panels/componentspanel/ComponentsPanelFolder.ts` - Data model - `views/panels/componentspanel/ComponentTemplates.ts` - Template definitions **Pattern references:** - `views/panels/SearchPanel/SearchPanel.tsx` - Modern panel example - `views/SidePanel/SidePanel.tsx` - Container that hosts panels - `views/PopupLayer/PopupMenu.tsx` - Context menu component - `hooks/useModel.ts` - useModernModel hook --- ## Confidence Checkpoints After each session, verify: 1. No TypeScript errors: `npx tsc --noEmit` 2. App launches: `npm run dev` 3. Panel renders in sidebar 4. Previous functionality still works **Before removing old files:** Test EVERYTHING twice.