Rewrote sync_microsoft_skills.py (v4) to use each SKILL.md's frontmatter 'name' field as the flat directory name under skills/, replacing the nested skills/official/microsoft/<lang>/<category>/<service>/ hierarchy. This fixes CI failures caused by the indexing, validation, and catalog scripts expecting skills/<id>/SKILL.md (depth 1). Changes: - Rewrite scripts/sync_microsoft_skills.py for flat output with collision detection - Update scripts/tests/inspect_microsoft_repo.py for flat name mapping - Update scripts/tests/test_comprehensive_coverage.py for name uniqueness checks - Delete skills/official/ nested directory - Add 129 Microsoft skills as flat directories (e.g. skills/azure-mgmt-botservice-dotnet/) - Move attribution files to docs/ (LICENSE-MICROSOFT, microsoft-skills-attribution.json) - Rebuild skills_index.json, CATALOG.md, README.md (845 total skills)
67 lines
1.9 KiB
Markdown
67 lines
1.9 KiB
Markdown
---
|
|
name: react-flow-node-ts
|
|
description: Create React Flow node components with TypeScript types, handles, and Zustand integration. Use when building custom nodes for React Flow canvas, creating visual workflow editors, or implementing node-based UI components.
|
|
---
|
|
|
|
# React Flow Node
|
|
|
|
Create React Flow node components following established patterns with proper TypeScript types and store integration.
|
|
|
|
## Quick Start
|
|
|
|
Copy templates from [assets/](assets/) and replace placeholders:
|
|
- `{{NodeName}}` → PascalCase component name (e.g., `VideoNode`)
|
|
- `{{nodeType}}` → kebab-case type identifier (e.g., `video-node`)
|
|
- `{{NodeData}}` → Data interface name (e.g., `VideoNodeData`)
|
|
|
|
## Templates
|
|
|
|
- [assets/template.tsx](assets/template.tsx) - Node component
|
|
- [assets/types.template.ts](assets/types.template.ts) - TypeScript definitions
|
|
|
|
## Node Component Pattern
|
|
|
|
```tsx
|
|
export const MyNode = memo(function MyNode({
|
|
id,
|
|
data,
|
|
selected,
|
|
width,
|
|
height,
|
|
}: MyNodeProps) {
|
|
const updateNode = useAppStore((state) => state.updateNode);
|
|
const canvasMode = useAppStore((state) => state.canvasMode);
|
|
|
|
return (
|
|
<>
|
|
<NodeResizer isVisible={selected && canvasMode === 'editing'} />
|
|
<div className="node-container">
|
|
<Handle type="target" position={Position.Top} />
|
|
{/* Node content */}
|
|
<Handle type="source" position={Position.Bottom} />
|
|
</div>
|
|
</>
|
|
);
|
|
});
|
|
```
|
|
|
|
## Type Definition Pattern
|
|
|
|
```typescript
|
|
export interface MyNodeData extends Record<string, unknown> {
|
|
title: string;
|
|
description?: string;
|
|
}
|
|
|
|
export type MyNode = Node<MyNodeData, 'my-node'>;
|
|
```
|
|
|
|
## Integration Steps
|
|
|
|
1. Add type to `src/frontend/src/types/index.ts`
|
|
2. Create component in `src/frontend/src/components/nodes/`
|
|
3. Export from `src/frontend/src/components/nodes/index.ts`
|
|
4. Add defaults in `src/frontend/src/store/app-store.ts`
|
|
5. Register in canvas `nodeTypes`
|
|
6. Add to AddBlockMenu and ConnectMenu
|