商品テーブルリストブロック
ListProductsTableコンポーネントは、ReactとTypeScriptで構築された完全にカスタマイズ可能でアクセシブルな商品テーブルインターフェースです。モダンなデザインパターン、ソート可能なカラム、アクションドロップダウン、タブ、公開ステータス管理、ページネーションサポート、ローディング状態、高度な商品管理アプリケーション用の柔軟なカスタマイズオプションを備えた完全な表形式商品リスティング体験を提供します。
🚀 インストール
npm install @nodeblocks/frontend-list-products-table-block@0.1.1
📖 使用方法
import {ListProductsTable} from '@nodeblocks/frontend-list-products-table-block';
- 基本的な使用方法
- 高度な使用方法
function BasicListProductsTable() {
const [currentTab, setCurrentTab] = useState('published');
const [isLoading, setIsLoading] = useState(false);
const productData = [
{
id: '1',
title: 'プレミアムオフィスチェア',
category: '家具',
createdAt: '2024-01-15T10:30:00Z',
updatedAt: '2024-01-16T14:20:00Z',
numberOfApplicants: '5',
publication: {
since: '2024-01-15T00:00:00Z',
until: '2024-03-15T23:59:59Z',
status: 'ACTIVE'
}
},
{
id: '2',
title: 'ワイヤレスヘッドホン',
category: '電子機器',
createdAt: '2024-01-14T09:15:00Z',
updatedAt: '2024-01-14T09:15:00Z',
numberOfApplicants: '12',
publication: {
since: '2024-01-20T00:00:00Z',
until: '2024-04-20T23:59:59Z',
status: 'INACTIVE'
}
}
];
const tabs = [
{ label: '公開商品' },
{ label: '下書き商品' },
{ label: 'アーカイブ商品' }
];
const labels = {
emptyStateMessage: '商品が見つかりません',
actions: {
createProduct: '商品を作成'
},
headerRow: {
title: '商品タイトル',
publicationPeriod: '公開期間',
createdAt: '作成日',
updatedAt: '更新日',
numberOfApplicants: '申込者数'
},
rowActions: {
public: '公開する',
private: '非公開にする',
edit: '商品を編集',
archive: '商品をアーカイブ',
unarchive: '商品をアーカイブ解除'
},
unsetData: {
since: '未設定',
until: '未設定',
date: '公開期間なし'
}
};
const handleProductPublic = (productId, title) => {
console.log('商品を公開しました:', productId, title);
};
const handleProductPrivate = (productId, title) => {
console.log('商品を非公開にしました:', productId, title);
};
const handleProductArchive = (productId, title) => {
console.log('商品をアーカイブしました:', productId, title);
};
const handleProductUnarchive = (productId) => {
console.log('商品をアーカイブ解除しました:', productId);
};
const handleNavigate = (path) => {
console.log('ナビゲート先:', path);
};
const getRowHref = (row) => `/products/${row.id}`;
const getUpdateRowHref = (row) => `/products/${row.id}/edit`;
return (
<ListProductsTable
listProductsTableTitle="商品管理"
labels={labels}
isLoading={isLoading}
onNavigate={handleNavigate}
onProductPublic={handleProductPublic}
onProductPrivate={handleProductPrivate}
onProductArchive={handleProductArchive}
onProductUnarchive={handleProductUnarchive}
data={productData}
rowHref={getRowHref}
updateRowHref={getUpdateRowHref}
tabs={tabs}
currentTab={currentTab}
onTabChange={setCurrentTab}
createHref="#products/new">
<ListProductsTable.Header style={{display: 'flex', justifyContent: 'space-between'}}>
<ListProductsTable.Title />
<ListProductsTable.Action />
</ListProductsTable.Header>
<ListProductsTable.Content>
{isLoading ? (
<ListProductsTable.Loader />
) : (
<>
<ListProductsTable.Tabs />
<ListProductsTable.Table />
</>
)}
</ListProductsTable.Content>
</ListProductsTable>
);
}
function AdvancedProductsTable() {
const [currentTab, setCurrentTab] = useState('published');
const [isLoading, setIsLoading] = useState(false);
const productData = [
{
id: '3',
title: '🎧 プレミアムノイズキャンセリングヘッドホン',
category: '電子機器',
createdAt: '2024-01-15T10:30:00Z',
updatedAt: '2024-01-16T14:20:00Z',
numberOfApplicants: '24',
publication: {
since: '2024-01-15T00:00:00Z',
until: '2024-03-15T23:59:59Z',
status: 'ACTIVE'
}
},
{
id: '4',
title: '💻 MacBook Pro 16" M3 Max',
category: 'コンピューティング',
createdAt: '2024-01-14T09:15:00Z',
updatedAt: '2024-01-14T09:15:00Z',
numberOfApplicants: '45',
publication: {
since: '2024-01-20T00:00:00Z',
until: '2024-04-20T23:59:59Z',
status: 'INACTIVE'
}
},
{
id: '6',
title: '🎮 PlayStation 5 Pro コンソール',
category: 'ゲーミング',
createdAt: '2024-01-13T08:45:00Z',
updatedAt: '2024-01-15T16:30:00Z',
numberOfApplicants: '67',
publication: {
since: '2024-01-13T00:00:00Z',
until: '2024-05-13T23:59:59Z',
status: 'ACTIVE'
}
}
];
const tabs = [
{ label: '🚀 公開中商品', key: 'published' },
{ label: '📝 下書き商品', key: 'draft' },
{ label: '📦 アーカイブ商品', key: 'archived' }
];
const labels = {
emptyStateMessage: 'このカテゴリに商品が見つかりません',
actions: {
createProduct: '✨ 新しい商品を追加'
},
headerRow: {
title: '商品情報',
publicationPeriod: '販売期間',
createdAt: '作成日',
updatedAt: '最終更新',
numberOfApplicants: '関心数'
},
rowActions: {
public: '公開',
private: '非公開にする',
edit: '詳細を編集',
archive: 'アーカイブ',
unarchive: '復元'
},
unsetData: {
since: '開始日未定',
until: '終了日未定',
date: '公開期間が設定されていません'
}
};
return (
<ListProductsTable
listProductsTableTitle="🛍️ プレミアム商品ダッシュボード"
labels={labels}
isLoading={isLoading}
onNavigate={(path) => console.log('ナビゲート先:', path)}
onProductPublic={(id, title) => console.log('公開中:', title)}
onProductPrivate={(id, title) => console.log('非公開にする:', title)}
onProductArchive={(id, title) => console.log('アーカイブ中:', title)}
onProductUnarchive={(id) => console.log('商品を復元中:', id)}
data={productData}
rowHref={(row) => `/products/${row.id}`}
updateRowHref={(row) => `/products/${row.id}/edit`}
tabs={tabs}
currentTab={currentTab}
onTabChange={setCurrentTab}
createHref="#products/new">
{({ defaultBlocks, defaultBlockOrder }) => ({
blocks: {
...defaultBlocks,
// グラデーションスタイリングで強化されたヘッダー
header: {
...defaultBlocks.header,
props: {
...defaultBlocks.header.props,
style: {
background: 'white',
borderRadius: '20px',
padding: '32px',
color: 'white',
marginBottom: '24px',
width: 'calc(100% - 48px)',
margin: '0 auto',
marginTop: '24px',
boxShadow: '0 15px 35px rgba(0,0,0,0.1)',
border: '0.5px solid rgb(0, 0, 0)',
}
}
},
// モダンなスタイリングで強化されたコンテンツ
content: {
...defaultBlocks.content,
props: {
...defaultBlocks.content.props,
style: {
background: 'white',
borderRadius: '16px',
padding: '24px',
boxShadow: '0 10px 35px rgba(0,0,0,0.05)',
width: 'calc(100% - 48px)',
margin: '0 auto',
borderRadius: '16px',
border: '0.5px solid rgb(0, 0, 0)',
}
}
}
},
blockOrder: defaultBlockOrder
})}
</ListProductsTable>
);
}
🔧 プロパティリファレンス
メインコンポーネントのプロパティ
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
listProductsTableTitle | ReactNode | 必須 | 商品テーブルセクションのタイトル |
labels | TableLabels | 必須 | テーブルヘッダー、アクション、メッセージ用のラベルオブジェクト |
isLoading | boolean | undefined | テーブルが現在ローディング中かどうか |
onNavigate | (to: string) => void | 必須 | ナビゲーション用のコールバック関数 |
onProductPublic | ProductAction | 必須 | 商品が公開されたときのコールバック関数 |
onProductPrivate | ProductAction | 必須 | 商品が非公開にされたときのコールバック関数 |
onProductArchive | ProductAction | 必須 | 商品がアーカイブされたときのコールバック関数 |
onProductUnarchive | (productId: string) => void | 必須 | 商品がアーカイブ解除されたときのコールバック関数 |
data | ListProductsTableRowData[] | 必須 | 商品データオブジェクトの配列 |
rowHref | (row: ListProductsTableRowData) => string | 必須 | 行リンクURLを生成する関数 |
updateRowHref | (row: ListProductsTableRowData) => string | 必須 | 更新行リンクURLを生成する関数 |
tabs | Tab[] | 必須 | タブ設定オブジェクトの配列 |
currentTab | string | undefined | 現在アクティブなタブ識別子 |
onTabChange | (tab: string) => void | undefined | タブが変更されたときのコールバック関数 |
createHref | string | 必須 | 新しい商品作成用のURL |
pagination | {currentPage: number; onPageChange: (page: number) => void; totalPages: number} | コンテキストから | ページネーション設定 |
className | string | undefined | コンテナスタイリング用の追加CSSクラス名 |
children | BlocksOverride | undefined | デフォルトレンダリングをオーバーライドするカスタムブロックコンポーネント |
サブコンポーネント
ListProductsTableコンポーネントは、独立して使用できる複数のサブコンポーネントを提供します:
ListProductsTable.Header
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | undefined | デフォルトヘッダーレンダリングをオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
ListProductsTable.Title
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | undefined | デフォルトタイトルレンダリングをオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
size | enum | "3XL" | タイトルのタイポグラフィサイズ |
color | enum | "low-emphasis" | タイトルのカラーテーマ |
weight | enum | "bold" | タイトルの太さ |
ListProductsTable.Action
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | undefined | デフォルトアクションレンダリングをオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
createHref | string | コンテキストから | 作成アクションボタンのURL |
labels | TableLabels | コンテキストから | アクションテキスト用のラベル |
direction | enum | "row" | アクションボタンのフレックス方向 |
alignItems | enum | "stretch" | コンテナ内のアイテムの整列 |
gapSize | enum | "S" | コンテナ内のアイテム間のギャップ |
ListProductsTable.Content
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | undefined | デフォルトコンテンツレンダリングをオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
isLoading | boolean | コンテキストから | コンテキストからのローディング状態 |
ListProductsTable.Loader
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | 円形プログレスインジケーター | カスタムローディングインジケーターコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
direction | enum | "row" | アクションボタンのフレックス方向 |
alignItems | enum | "stretch" | コンテナ内のアイテムの整列 |
gapSize | enum | "S" | コンテナ内のアイテム間のギャップ |
ListProductsTable.Tabs
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
tabs | Tab[] | コンテキストから | タブ設定オブジェクトの配列 |
currentTab | string | コンテキストから | 現在アクティブなタブ識別子 |
onTabChange | (tab: string) => void | コンテキストから | タブ変更コールバック関数 |
tabWidth | string | "stretch" | タブの幅動作 |
className | string | undefined | スタイリング用の追加CSSクラス名 |
ListProductsTable.Table
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
className | string | undefined | スタイリング用の追加CSSクラス名 |
onProductPublic | (id: string, title: string) => void | コンテキストから | 商品が公開されたときのコールバック関数 |
onProductPrivate | (id: string, title: string) => void | コンテキストから | 商品が非公開にされたときのコールバック関数 |
onProductArchive | (id: string, title: string) => void | コンテキストから | 商品がアーカイブされたときのコールバック関数 |
onProductUnarchive | (id: string) => void | コンテキストから | 商品がアーカイブ解除されたときのコールバック関数 |
data | ListProductsTableRowData[] | コンテキストから | テーブルデータの配列 |
dropdownMenuItems | (cell: ListProductsTableRowData) => Array<DropDownMenuItems> | コンテキストから | ドロップダウンメニューアイテムを生成する関数 |
dropdownMenuState | {openedDropdownMenuId: string} | コンテキストから | 現在開いているドロップダウンメニュー |
setDropdownMenuState | ({openedDropdownMenuId: string}) => void | コンテキストから | 開いているドロップダウンメニューが変更されたときのコールバック関数 |
emptyState | {icon?: IconType; message: string} | コンテキストから | 空状態の設定 |
isLoading | boolean | コンテキストから | ローディング状態 |
onNavigate | (to: string) => void | コンテキストから | ナビゲーションコールバック関数 |
pagination | {currentPage: number; onPageChange: (page: number) => void; totalPages: number} | コンテキストから | ページネーション設定 |
rowHref | `(cell: ListProductsTableRowData) => string | undefined | null` |
updateRowHref | `(cell: ListProductsTableRowData) => string | undefined | null` |
🔧 TypeScript サポート
包括的な型定義による完全なTypeScriptサポート:
import {ListProductsTable} from '@nodeblocks/frontend-list-products-table-block';
interface Tab {
isDisabled?: boolean;
key?: string;
label: string;
subtitle?: string;
}
interface ListProductsTableRowData {
category: string;
createdAt: string;
id: string;
numberOfApplicants: string;
publication?: {
since?: string;
status?: string;
until?: string;
};
title: string;
updatedAt: string;
}
interface CustomProductTableProps {
products: ListProductsTableRowData[];
onPublishProduct: (productId: string) => void;
onUnpublishProduct: (productId: string) => void;
onArchiveProduct: (productId: string) => void;
onRestoreProduct: (productId: string) => void;
tableTabs: Array<Tab>;
currentActiveTab: string;
onTabSwitch: (tab: string) => void;
isTableLoading: boolean;
}
const ProductTableComponent = ({
products,
onPublishProduct,
onUnpublishProduct,
onArchiveProduct,
onRestoreProduct,
tableTabs,
currentActiveTab,
onTabSwitch,
isTableLoading,
}: CustomProductTableProps) => {
const tableLabels = {
emptyStateMessage: '利用可能な商品がありません',
actions: {createProduct: '新しい商品'},
headerRow: {
title: '商品名',
publicationPeriod: '公開日',
createdAt: '作成日',
updatedAt: '最終更新',
numberOfApplicants: '総申込者数',
},
rowActions: {
public: '公開',
private: '非公開',
edit: '編集',
archive: 'アーカイブ',
unarchive: '復元',
},
unsetData: {
since: '開始日未設定',
until: '終了日未設定',
date: '公開期間が設定されていません',
},
};
return (
<ListProductsTable
listProductsTableTitle="商品ダッシュボード"
labels={tableLabels}
isLoading={isTableLoading}
onNavigate={path => console.log('ナビゲート:', path)}
onProductPublic={onPublishProduct}
onProductPrivate={onUnpublishProduct}
onProductArchive={onArchiveProduct}
onProductUnarchive={onRestoreProduct}
data={products}
rowHref={row => `/products/${row.id}`}
updateRowHref={row => `/products/${row.id}/edit`}
tabs={tableTabs}
currentTab={currentActiveTab}
onTabChange={onTabSwitch}
createHref="/products/create">
<ListProductsTable.Header />
<ListProductsTable.Content />
</ListProductsTable>
);
};
React、TypeScript、モダンなウェブ標準を使用して❤️で構築されました。