Files
qiming/qiming-vite-plugin-design-mode/packages/client-vue/src/composables/README.md
2026-06-01 13:43:09 +08:00

239 lines
6.5 KiB
Markdown

# Vue3 Design Mode Composables
Vue3 Composition API equivalents of the React design mode hooks.
## Overview
This directory contains Vue3 composables that provide the same functionality as the React hooks in `/src/client/`. These composables enable design mode functionality in Vue3 applications.
## Composables
### 1. `useDesignMode.ts` (912 lines)
**Purpose**: Global design mode state management and bridge communication.
**Ported from**: `src/client/DesignModeContext.tsx` (1,079 lines)
**Key Features**:
- Global state management using `reactive()` and `provide/inject`
- Bridge communication with parent window via postMessage
- Message handling for style/content updates
- Batch update support with debouncing
- Health check and connection monitoring
**Usage**:
```typescript
import { createDesignMode, useDesignMode } from './composables';
// In root component
const designMode = createDesignMode({
enabled: true,
iframeMode: {
enabled: true,
enableSelection: true,
enableDirectEdit: true,
},
batchUpdate: {
enabled: true,
debounceMs: 300,
},
});
// In child components
const {
isDesignMode,
selectedElement,
toggleDesignMode,
selectElement,
modifyElementClass,
updateElementContent
} = useDesignMode();
```
**Key Methods**:
- `toggleDesignMode()` - Toggle design mode on/off
- `selectElement(element)` - Select an element for editing
- `modifyElementClass(element, newClass)` - Update element classes
- `updateElementContent(element, newContent)` - Update element text content
- `batchUpdateElements(updates)` - Batch multiple updates
- `resetModifications()` - Reload page to reset changes
### 2. `useSelectionManager.ts` (539 lines)
**Purpose**: Element selection and interaction handling.
**Ported from**: `src/client/SelectionManager.tsx` (597 lines)
**Key Features**:
- Click and hover event handling
- Element validation (must have source mapping + static-content/static-class)
- Visual highlighting with outline and shadow
- Keyboard shortcuts (Esc to clear, Ctrl/Cmd+A to select)
- Element info extraction with hierarchy
- Component root detection for library components
**Usage**:
```typescript
import { useSelectionManager } from './composables';
const {
selectedElement,
hoverElement,
selectElement,
clearSelection,
extractElementInfo,
addSelectionListener,
} = useSelectionManager(document.body, {
enableSelection: true,
enableHover: true,
selectionDelay: 0,
excludeSelectors: ['script', 'style', 'meta'],
includeOnlyElements: false,
});
// Listen to selection changes
const unsubscribe = addSelectionListener((element) => {
if (element) {
const info = extractElementInfo(element);
console.log('Selected:', info);
}
});
```
**Key Methods**:
- `selectElement(element)` - Select and highlight element
- `clearSelection()` - Clear current selection
- `extractElementInfo(element)` - Get detailed element information
- `addSelectionListener(callback)` - Subscribe to selection changes
### 3. `useEditManager.ts` (367 lines)
**Purpose**: Content editing with contentEditable mode.
**Ported from**: `src/client/managers/EditManager.ts` (365 lines)
**Key Features**:
- ContentEditable mode for inline text editing
- Real-time sync to related elements (list items with same element-id)
- Throttled notifications (300ms) during typing
- Enter saves, Escape cancels
- Click outside to save
- Automatic peer element synchronization
**Usage**:
```typescript
import { useEditManager } from './composables';
const processUpdate = async (update: UpdateState) => {
// Handle update logic
return { success: true };
};
const {
handleDirectEdit,
editTextContent,
updateContent,
updateStyle,
updateAttribute,
} = useEditManager(processUpdate, config);
// Double-click to edit
element.addEventListener('dblclick', () => {
handleDirectEdit(element, 'content');
});
```
**Key Methods**:
- `handleDirectEdit(element, type)` - Trigger edit mode
- `editTextContent(element)` - Enable contentEditable editing
- `updateContent(element, newValue)` - Programmatic content update
- `updateStyle(element, newClass)` - Programmatic style update
- `updateAttribute(element, name, value)` - Update element attribute
### 4. `useObserverManager.ts` (98 lines)
**Purpose**: DOM mutation observation.
**Ported from**: `src/client/managers/ObserverManager.ts` (81 lines)
**Key Features**:
- MutationObserver setup for DOM changes
- Watches: childList, characterData, attributes (class, style)
- Skips elements with `data-ignore-mutation` attribute
- Callbacks for content/style edits and node additions
**Usage**:
```typescript
import { useObserverManager } from './composables';
const { enable, disable, isEnabled } = useObserverManager(
(target, type) => {
console.log(`Edit detected: ${type} on`, target);
},
(node) => {
console.log('Node added:', node);
}
);
// Start observing
enable();
// Stop observing
disable();
```
**Key Methods**:
- `enable()` - Start observing DOM mutations
- `disable()` - Stop observing and disconnect
## Key Differences from React Version
### State Management
- **React**: `useState`, `useCallback`, `useEffect`
- **Vue3**: `ref`, `reactive`, `computed`, `watch`, `onMounted`, `onBeforeUnmount`
### Context/Injection
- **React**: `createContext`, `useContext`, `Provider`
- **Vue3**: `provide`, `inject`, `InjectionKey`
### Lifecycle
- **React**: `useEffect` with cleanup
- **Vue3**: `onMounted`, `onBeforeUnmount`
### Reactivity
- **React**: Explicit state setters
- **Vue3**: Direct mutation of `ref.value` or `reactive` properties
## Integration with Shared Code
All composables import shared utilities from `/src/client-shared/`:
- `bridge.ts` - PostMessage communication
- `attributeNames.ts` - Data attribute name resolution
- `sourceInfo.ts` - Source mapping extraction
- `sourceInfoResolver.ts` - Usage-site resolution
- `elementUtils.ts` - Element validation helpers
## Type Safety
All composables are fully typed with TypeScript, importing types from:
- `/src/types/messages.ts` - Message type definitions
- `/src/types/UpdateTypes.ts` - Update operation types
## Testing
To test these composables:
1. Import in a Vue3 component
2. Call `createDesignMode()` in the root component
3. Use `useDesignMode()` in child components
4. Verify bridge communication with parent window
5. Test element selection and editing
## Future Enhancements
- [ ] Add Vue3-specific optimizations (e.g., `shallowRef` for large objects)
- [ ] Create Vue3 component wrappers for easier integration
- [ ] Add Pinia store integration option
- [ ] Implement Vue DevTools integration
- [ ] Add unit tests with Vitest