@ooopenlab/quiz-form-fields
v1.0.0
Published
Form field type definitions and components for SuperQuiz modules
Maintainers
Readme
測驗表單欄位程式庫
用於建立測驗編輯器和表單的可重複使用表單欄位元件。
概述
此程式庫提供一系列可重複使用的表單欄位元件,用於不同的測驗模組。所有元件都遵循一致的 API 和樣式方法。
元件
TextInput
具有驗證和錯誤處理的基本文字輸入元件。
import { TextInput } from '@ooopenlab/quiz-form-fields';
<TextInput
label="測驗標題"
value={title}
onChange={setTitle}
required={true}
maxLength={50}
placeholder="輸入測驗標題..."
/>Textarea
具有自動調整大小選項的多行文字輸入元件。
import { Textarea } from '@ooopenlab/quiz-form-fields';
<Textarea
label="描述"
value={description}
onChange={setDescription}
rows={4}
autoResize={true}
maxLength={200}
/>元件屬性
所有元件都擴展 BaseFormFieldProps:
interface BaseFormFieldProps {
label?: string;
value?: any;
onChange?: (value: any) => void;
required?: boolean;
disabled?: boolean;
error?: string;
placeholder?: string;
className?: string;
}計畫中的元件
Select- 下拉選擇NumberInput- 具有最小/最大驗證的數值輸入ColorPicker- 具有預設值的顏色選擇ImageUploader- 具有預覽的檔案上傳RichTextEditor- 所見即所得文字編輯器
與模組系統的使用
表單欄位會根據模組欄位定義自動渲染:
// 在模組定義中
private getCoverFields(): FormField[] {
return [
{
type: 'text',
label: '測驗標題',
key: 'title',
required: true,
validation: {
max: 50,
message: '標題不能超過 50 個字元'
}
}
];
}表單渲染器會根據 type 欄位自動使用適當的元件。
發現可用欄位(FieldType Registry)
主程式的 ModalEditor 透過一組既定的欄位型別字串來對應實作元件。為了讓模組與 CLI 能「知道有哪些欄位可用」,本庫提供了統一的型別與查詢 API:
import { type FieldType, listFieldTypes, isFieldTypeSupported } from '@ooopenlab/quiz-form-fields';
const allTypes: FieldType[] = listFieldTypes(); // ['color','image','tab',...]
function needs(type: string) {
if (!isFieldTypeSupported(type)) throw new Error(`不支援的欄位型別: ${type}`);
// OK to use
}同時,@ooopenlab/quiz-modules 也將 FormField.type 鎖定為 FieldType,避免輸入不存在的欄位型別。
樣式
元件使用 CSS 類別進行樣式設定:
.form-field- 容器包裝器.form-label- 標籤樣式.form-input- 輸入元素樣式.form-error- 錯誤訊息樣式
依賴規則與循環依賴預防
允許的依賴關係
- quiz-form-fields (
type:ui):- ✅ 可以使用
@ooopenlab/quiz-shared(工具和常數) - 🚫 不可依賴 quiz-modules 或其他業務邏輯程式庫
- 🚫 不可依賴同層級的 UI 程式庫
- ✅ 可以使用
依賴規則
// ✅ 正確使用方式
import { debounce, sanitizeHtml, QUIZ_CONSTANTS } from '@ooopenlab/quiz-shared';
import React, { useState } from 'react'; // 標準 React
// 🚫 避免的依賴模式
// import { SomeModule } from '@ooopenlab/quiz-modules'; // 避免依賴上層業務邏輯
// import { OtherUILib } from '@ooopenlab/other-ui-lib'; // 避免依賴同層級 UI 程式庫架構設計原則
純 UI 元件:
- 只負責視覺呈現和使用者互動
- 不包含業務邏輯
- 透過 props 接收資料和回調
可重複使用:
- 元件設計要通用,不綁定特定業務場景
- 透過配置參數支援不同使用情境
- 保持 API 穩定性
依賴最小化:
- 只依賴必要的共用工具(quiz-shared)
- 避免引入過多外部依賴
- 保持輕量級
防止循環依賴的檢查清單
- [ ] 新元件只使用 quiz-shared 中的工具
- [ ] 不在元件中寫入業務邏輯
- [ ] 不直接引用 quiz-modules 的任何內容
- [ ] 使用
nx graph --focus=quiz-form-fields檢查依賴 - [ ] 確保 tags 正確設定為
"type:ui" - [ ] 元件保持無狀態或最小狀態
與上層模組的整合
// quiz-modules 中使用 quiz-form-fields 的正確方式
import { TextInput } from '@ooopenlab/quiz-form-fields';
export class SomeModule {
getCoverComponent(): ModuleComponent {
return {
name: 'cover',
fields: [
{
type: 'text',
component: TextInput, // 引用 UI 元件
// ... 業務邏輯配置
}
]
};
}
}檔案結構
libs/quiz-form-fields/
├── src/
│ ├── types.ts # 類型定義
│ ├── components/
│ │ ├── TextInput.tsx # 文字輸入元件
│ │ └── Textarea.tsx # 文字區域元件
│ └── index.ts # 公開 API 匯出
├── project.json # NX 專案設定
└── README.md # 此檔案