npm package: @hrspd-gss/web-click-wizard-editor
Description: 基於 bole-clickwizard-designer 的簡易 Web 點擊自動化流程編輯器
Author: bole-clickwizard-designer
Latest version: 1.0.8

# web-click-wizard-editor

基於 `bole-clickwizard-designer` 的 Web 點擊自動化流程編輯器元件庫。

## 核心設計理念

這是一個**元件庫**，設計原則是：

- **極簡 API**：元件只接收值和 callback，不管理狀態
- **使用者控制**：狀態管理和儲存方式由使用者的 app 決定
- **可組合**：提供核心元件和預設 UI，可依需求選用

## 主要匯出

### 核心元件

| 元件 | 說明 |
|------|------|
| `WorkflowEditorCore` | 純編輯核心，不含工具列 |
| `workflowRuntimeService` | 執行服務，可跨頁/跨功能呼叫 |

### 預設 UI 元件

| 元件 | 說明 |
|------|------|
| `WorkflowEditorPanel` | 編輯面板，含工具列和按鈕 |
| `WorkflowExecutionPanel` | 執行面板，含視覺化和歷史記錄 |
| `ExtensionSettingsModal` | Extension 設定 Modal |
| `JsonPreviewDrawer` | JSON 預覽抽屜 |

### 類型和工具

| 匯出 | 說明 |
|------|------|
| `nodeTypeConfigs` | 預設節點類型設定 |
| `ExecutionHistoryStorage` | 執行歷史儲存介面 |
| `createLocalStorageExecutionHistoryStorage` | localStorage 實作 |
| `ExtensionStatus` | 連線狀態類型 |

## 快速開始

### 安裝

```bash
npm install @hrspd-gss/web-click-wizard-editor
```

### 載入 CSS

```ts
import '@hrspd-gss/bole-clickwizard-designer/dist/bole-clickwizard-designer.css';
import '@hrspd-gss/web-click-wizard-editor/dist/web-click-wizard-editor.css';
```

### 基本使用

```tsx
import { useEffect, useRef, useState } from 'react';
import type { WorkflowEditorRef } from '@hrspd-gss/bole-clickwizard-designer';
import {
  WorkflowEditorPanel,
  WorkflowExecutionPanel,
  ExtensionSettingsModal,
  nodeTypeConfigs,
  workflowRuntimeService,
  type ExtensionStatus,
} from '@hrspd-gss/web-click-wizard-editor';

function MyEditor() {
  const editorRef = useRef<WorkflowEditorRef>(null);
  const [workflow, setWorkflow] = useState(defaultWorkflow);
  const [runOpen, setRunOpen] = useState(false);
  const [settingsOpen, setSettingsOpen] = useState(false);

  // 你的 app 管理這些狀態
  const [extensionId, setExtensionId] = useState('');
  const [jwtToken, setJwtToken] = useState('');
  const [extensionStatus, setExtensionStatus] = useState<ExtensionStatus>('unknown');

  // 載入時檢查連線
  useEffect(() => {
    if (!extensionId) {
      setExtensionStatus('error');
      return;
    }
    setExtensionStatus('checking');
    workflowRuntimeService.checkConnection(extensionId).then(result => {
      setExtensionStatus(result.connected ? 'connected' : 'error');
    });
  }, [extensionId]);

  return (
    <>
      <WorkflowEditorPanel
        workflow={workflow}
        editorRef={editorRef}
        nodeTypeConfigs={nodeTypeConfigs}
        extensionStatus={extensionStatus}
        onWorkflowChange={setWorkflow}
        onOpenRunDialog={() => setRunOpen(true)}
        onOpenExtensionSettings={() => setSettingsOpen(true)}
      />

      <WorkflowExecutionPanel
        isOpen={runOpen}
        onClose={() => setRunOpen(false)}
        workflow={workflow}
        getCurrentWorkflow={() => editorRef.current?.getWorkflow() || workflow}
        extensionId={extensionId}
        jwtToken={jwtToken}
      />

      <ExtensionSettingsModal
        isOpen={settingsOpen}
        onClose={() => setSettingsOpen(false)}
        extensionId={extensionId}
        jwtToken={jwtToken}
        onSave={(newId, newToken) => {
          setExtensionId(newId);
          setJwtToken(newToken);
          // 儲存到你的 storage
        }}
      />
    </>
  );
}
```

## 元件 API

### WorkflowEditorPanel

| Prop | 類型 | 說明 |
|------|------|------|
| `workflow` | `Workflow` | 流程資料 |
| `editorRef` | `RefObject<WorkflowEditorRef>` | 編輯器 ref |
| `nodeTypeConfigs` | `NodeTypeConfig[]` | 節點類型設定 |
| `extensionStatus` | `ExtensionStatus` | 連線狀態 |
| `onWorkflowChange` | `(workflow: Workflow) => void` | 流程變更 callback |
| `onOpenRunDialog` | `() => void` | 開啟執行對話框 |
| `onOpenExtensionSettings` | `() => void` | 開啟設定 |

### WorkflowExecutionPanel

| Prop | 類型 | 說明 |
|------|------|------|
| `isOpen` | `boolean` | 是否顯示 |
| `onClose` | `() => void` | 關閉 callback |
| `workflow` | `Workflow` | 流程資料 |
| `getCurrentWorkflow` | `() => Workflow` | 取得最新流程 |
| `extensionId` | `string` | Extension ID |
| `jwtToken` | `string` (optional) | JWT Token |
| `historyStorage` | `ExecutionHistoryStorage` (optional) | 自訂歷史儲存 |

### ExtensionSettingsModal

| Prop | 類型 | 說明 |
|------|------|------|
| `isOpen` | `boolean` | 是否顯示 |
| `onClose` | `() => void` | 關閉 callback |
| `extensionId` | `string` | Extension ID |
| `jwtToken` | `string` (optional) | JWT Token |
| `onSave` | `(extensionId: string, jwtToken: string) => void` | 儲存 callback |

Modal 內部會自動處理連線檢查和狀態顯示。

## 進階整合

詳細的多頁整合範例請參考：

- [React Router 多頁整合範本](./docs/router-integration-example.md)