メインコンテンツまでスキップ

ListOrganizationsブロック

ListOrganizations は、BaseTable 上に構築された組織管理テーブルで、任意のタブ、検索チップ、行アクション、ページネーションを備えています。

インストール

npm install @nodeblocks/frontend-list-organization-block

必要なもの

項目用途
labelsヘッダーセル、ステータス、行アクション、検索フィールド、空状態のコピー
dataテーブル行(ListOrganizationsRowData[]
listOrganizationsTitleヘッダータイトル
searchValue + 検索チップ + ハンドラー (任意)制御された検索ドラフト、チップリスト、送信/削除フロー
tabs + currentTab + onTabChange (任意)任意のワークフロー/ステータスフィルター UI
statusMatch (任意)生の行 status 値をステータス列のアクティブ/非アクティブテキストにマッピングする
pagination (任意)制御されたページ状態
行アクション + ナビゲーションハンドラー (任意)labels.rowActions + resolveRowAction + アクションハンドラー、および行クリックナビゲーション
制御コンポーネント

ListOrganizations はテーブル状態を保持しません。タブ選択、検索ドラフト/チップ、ページネーションをアプリ側で管理し、ハンドラー(onTabChangeonSearchFieldChangeonSearchSubmitpagination.onPageChange)を渡して状態を更新してください。

行の形とステータスラベル

行は ListOrganizationsRowData の形状(idcreatedAtnamejoinDatestatus)を使用します。デフォルトでは、生成されるステータス列は生の値 'active''inactive' をアクティブ/非アクティブラベルとして扱います。API が異なるステータス値を使用する場合は statusMatch を渡してください。statusMatch はタブのフィルターや行アクションの選択には使用されません。これらのチェックは生の row.status 値と整合させてください。

コード例

ライブエディター
function Example() {
  const allOrganizationData = Array.from({length: 20}, (_, i) => ({
    id: String(i + 1),
    createdAt: new Date(2024, 0, i + 1).toISOString(),
    name: `組織 ${i + 1}`,
    joinDate: new Date(2024, 0, i + 5).toISOString(),
    status: i % 2 === 0 ? 'active' : 'inactive',
  }));

  const tabs = [
    {key: 'all', label: 'すべての組織'},
    {key: 'active', label: 'アクティブ'},
    {key: 'inactive', label: '非アクティブ'},
  ];

  const labels = {
    emptyStateMessage: '組織が見つかりません',
    searchFieldPlaceholder: '組織を検索...',
    rowActions: {
      activate: '組織を有効化',
      deactivate: '組織を無効化',
    },
    headerRow: {
      createdAt: '作成日',
      name: '組織名',
      joinDate: '参加日',
      status: 'ステータス',
    },
    cellData: {
      statusActive: 'アクティブ',
      statusInactive: '非アクティブ',
    },
  };

  const [currentTab, setCurrentTab] = React.useState('all');
  const [searchValue, setSearchValue] = React.useState('');
  const [currentPage, setCurrentPage] = React.useState(1);
  const [lastAction, setLastAction] = React.useState('検索・有効化・ナビゲーションのフィードバックがここに表示されます。');
  const itemsPerPage = 5;

  const filteredByTab = allOrganizationData.filter(row => {
    if (currentTab === 'active') return row.status === 'active';
    if (currentTab === 'inactive') return row.status === 'inactive';
    return true;
  });

  const filtered = searchValue.trim()
    ? filteredByTab.filter(row => {
        const keyword = searchValue.toLowerCase();
        return row.name.toLowerCase().includes(keyword) || row.status.toLowerCase().includes(keyword);
      })
    : filteredByTab;

  const totalPages = Math.max(1, Math.ceil(filtered.length / itemsPerPage));
  const start = (currentPage - 1) * itemsPerPage;
  const data = filtered.slice(start, start + itemsPerPage);

  return (
    <>
      <ListOrganizations
        listOrganizationsTitle="組織管理"
        labels={labels}
        data={data}
        tabs={tabs}
        currentTab={currentTab}
        onTabChange={tab => {
          setCurrentTab(tab);
          setCurrentPage(1);
        }}
        searchValue={searchValue}
        onSearchFieldChange={setSearchValue}
        onSearchSubmit={() => setLastAction(`検索が送信されました: ${searchValue}`)}
        statusMatch={{active: 'active', inactive: 'inactive'}}
        resolveRowAction={row => (row.status === 'active' ? ['deactivate'] : ['activate'])}
        onItemActivate={rowId => setLastAction(`組織を有効化: ${rowId}`)}
        onItemDeactivate={rowId => setLastAction(`組織を無効化: ${rowId}`)}
        pagination={{
          currentPage,
          totalPages,
          onPageChange: setCurrentPage,
        }}
        rowHref={row => `/organizations/${row.id}`}
        onNavigate={to => setLastAction(`ナビゲート: ${to}`)}
      />
      <div style={{marginTop: 12, color: '#475569', fontSize: 13}}>{lastAction}</div>
    </>
  );
}
結果
Loading...

主要プロパティ

コアプロパティ

プロパティ必須デフォルト説明
labels{ emptyStateMessage: string; searchFieldPlaceholder: string; rowActions?: { activate: string; deactivate: string }; headerRow: { createdAt: string; name: string; joinDate: string; status: string }; cellData: { statusActive: string; statusInactive: string } }はい-検索、テーブルセル、行アクション、空状態の UI コピー
dataListOrganizationsRowData[]はい-テーブル行
listOrganizationsTitleReactNodeはい-ヘッダータイトル
isLoadingbooleanいいえundefinedコンテンツ/ページネーションのローディング状態
searchValuestringいいえundefined制御された検索入力値
onSearchFieldChange(value: string) => voidいいえundefined検索入力の変更ハンドラー
onSearchSubmit() => voidいいえundefined検索アイコンのクリックまたは Enter キーでトリガー
searchChipsTitleReactNodeいいえundefinedアクティブな検索チップの上のラベル
searchChipsBaseTableSearchChip[]いいえundefinedアクティブな検索チップ
onSearchChipDelete(chip: BaseTableSearchChip, index: number, event: SyntheticEvent) => voidいいえundefinedチップ削除ハンドラー
tabs{ key: string; label: string; isDisabled?: boolean; subtitle?: string }[]いいえundefined任意のタブ定義
currentTabstringいいえundefinedアクティブなタブキー
onTabChange(tab: string) => voidいいえundefinedタブ変更ハンドラー
statusMatch{ active: string; inactive: string }いいえ{ active: 'active', inactive: 'inactive' }生の row.status 値を生成されるステータス列のアクティブ/非アクティブテキストにマッピングする
pagination{ currentPage: number; totalPages: number; onPageChange: (page: number) => void; className?: string }いいえundefinedページコントロール(ページは 1 から数える)
rowHref(row: ListOrganizationsRowData) => stringいいえundefined行リンクを構築する。onNavigate が必要
onNavigate(to: string) => voidいいえundefined行クリックで rowHref が解決されたときに呼ばれる
shouldShowDropdownMenu(row: ListOrganizationsRowData) => booleanいいえundefined行ごとに行メニューを表示/非表示
resolveRowAction(row: ListOrganizationsRowData) => ('activate' | 'deactivate')[] | undefinedいいえundefinedレンダリングする行アクションの種類
onItemActivate(rowId: string) => voidいいえundefinedactivate アクションのハンドラー
onItemDeactivate(rowId: string) => voidいいえundefineddeactivate アクションのハンドラー

ListOrganizationsRowData の形状:

プロパティ必須デフォルト説明
idstringはい-一意の行 ID
createdAtstringはい-作成日列で使用する ISO 日時文字列
namestringはい-組織名
joinDatestringはい-参加日列で使用する ISO 日時文字列
statusstringはい-生のステータス値。statusMatch はステータス列の表示のみを制御し、タブと行アクションは独自の比較を使用する

コンテンツプロパティ

labels キー:

プロパティ必須デフォルト説明
labels.emptyStateMessagestringはい-空のテーブルのメッセージ
labels.searchFieldPlaceholderstringはい-検索入力のプレースホルダー
labels.rowActions.activatestringいいえundefined有効化アクションのラベル
labels.rowActions.deactivatestringいいえundefined無効化アクションのラベル
labels.headerRow.createdAtstringはい-作成日ヘッダー
labels.headerRow.namestringはい-名前列ヘッダー
labels.headerRow.joinDatestringはい-参加日ヘッダー
labels.headerRow.statusstringはい-ステータス列ヘッダー
labels.cellData.statusActivestringはい-アクティブ行のセルラベル
labels.cellData.statusInactivestringはい-非アクティブ行のセルラベル

サブコンポーネント:

コンポーネントプロパティ必須デフォルト説明
TitlelistOrganizationsTitleReactNodeいいえルートの listOrganizationsTitleBaseTableheaderTitle 経由)タイトルテキスト(children が優先)
TitlechildrenReactNodeいいえルートのタイトルカスタムタイトルマークアップ
Actionlabels{ emptyStateMessage: string; searchFieldPlaceholder: string; rowActions?: { activate: string; deactivate: string }; headerRow: { createdAt: string; name: string; joinDate: string; status: string }; cellData: { statusActive: string; statusInactive: string } }いいえルートの labels検索入力のコピー
ActionsearchValuestringいいえルートの searchValue制御された検索入力
ActiononSearchFieldChange(value: string) => voidいいえルートのハンドラー検索入力の変更
ActiononSearchSubmit() => voidいいえルートのハンドラー検索の送信
ActionchildrenReactNodeいいえ組み込みの検索コントロールカスタムアクションコンテンツ
SearchChipssearchChipsTitleReactNodeいいえルートの searchChipsTitleチップグループのタイトル
SearchChipssearchChipsBaseTableSearchChip[]いいえルートの searchChipsチップデータ
SearchChipsonSearchChipDelete(chip: BaseTableSearchChip, index: number, event: SyntheticEvent) => voidいいえルートのハンドラーチップ削除コールバック
Tabsvaluestringいいえルートの currentTabアクティブなタブ値のオーバーライド
TabsonChangeTabsProps['onChange']いいえルートの onTabChangeMUI タブ変更コールバック
TabstabPropsMUI Tab props excluding label, value, and disabledいいえundefined各 MUI タブに転送される props
Tablelabelsルートの labels と同じ形状いいえルートの labels列/行なしオーバーレイ/行アクションラベルを生成する
TablestatusMatch{ active: string; inactive: string }いいえ{ active: 'active', inactive: 'inactive' }生の row.status 値のステータス列表示マッピング
TablecolumnsBaseTableColumn<ListOrganizationsRowData>[]いいえlabels + statusMatch から生成グリッド列のオーバーライド
TablerowActions(row: ListOrganizationsRowData) => BaseTableRowAction<ListOrganizationsRowData>[]いいえ行アクションプロップから生成行アクションのオーバーライド
TableactionColumnBaseTableActionColumnいいえ行アクションがある場合 { pin: 'right' }アクション列の設定
TablerowMenuReactNode or functionいいえデフォルトメニューカスタム行メニュー UI
TableonRowClick(row: ListOrganizationsRowData) => voidいいえrowHref + onNavigate から導出行クリックコールバック
LoaderchildrenReactNodeいいえデフォルトローダーローディングコンテンツ
Paginationpagination{ currentPage: number; totalPages: number; onPageChange: (page: number) => void; className?: string }いいえルートの paginationページネーションコントロール
PaginationdataListOrganizationsRowData[]いいえルートの data行数のソース
PaginationisLoadingbooleanいいえルートの isLoadingローディング中または行がない場合はページネーションを非表示

TitleActionHeaderLoaderSearchChipsTabsContentTablePaginationListOrganizations.Title などです。ListOrganizations.Tabs はルートの tabs プロップからタブ定義を読み取ります。

レイアウトと構成プロパティ

プロパティ必須デフォルト説明
childrenBlocksOverride | ReactNodeいいえundefined複合 JSX の子、または blocksblockOrder を返す関数オーバーライド
classNamestringいいえundefinedルートコンテナ(nbb-list-organizations-container)のクラス
sxSxPropsいいえundefinedルート用の MUI システムスタイル

ListOrganizationsheaderTitle、検索アクション、任意のタブ、行、行アクション、行なしオーバーレイ、任意のページネーションを備えた BaseTable ルートをレンダリングします。StackProps のパススルー(children を除く)を継承します。defaultBlockOrderheadersearchChipstabscontentpagination です。

デフォルト UI ブロック

ブロックベース備考
ListOrganizations (ルート)BaseTableルートテーブルラッパー
ListOrganizations.TitleBaseTable.Header.TitlelistOrganizationsTitle からのタイトル
ListOrganizations.ActionBaseTable.Header.Actions + TextField検索アイコン送信付きの検索フィールド
ListOrganizations.HeaderBaseTable.Headerタイトル/アクションをラップ
ListOrganizations.SearchChipsBaseTable.SearchChipsアクティブなキーワードチップブロック
ListOrganizations.TabsBaseTable.Tabstabs からの任意のタブ
ListOrganizations.LoaderBaseTable.Content.Loaderローディング状態
ListOrganizations.ContentBaseTable.Contentコンテンツラッパー
ListOrganizations.TableBaseTable.Content.Grid生成された列/アクション付きデータグリッド
ListOrganizations.PaginationBaseTable.Paginationページコントロール
行なしオーバーレイアイコンPersonOutlineddata が空のときに使用

TypeScript

import {
ListOrganizations,
ListOrganizationsRowData,
BaseTableSearchChip,
} from '@nodeblocks/frontend-list-organization-block';

const rows: ListOrganizationsRowData[] = [
{
id: '1',
createdAt: new Date().toISOString(),
name: '組織 1',
joinDate: new Date().toISOString(),
status: 'active',
},
];

const chips: BaseTableSearchChip[] = [{key: 'keyword-1', label: '組織 1'}];

<ListOrganizations
listOrganizationsTitle="組織管理"
labels={{
emptyStateMessage: '組織が見つかりません',
searchFieldPlaceholder: '組織を検索...',
rowActions: {activate: '組織を有効化', deactivate: '組織を無効化'},
headerRow: {
createdAt: '作成日',
name: '組織名',
joinDate: '参加日',
status: 'ステータス',
},
cellData: {statusActive: 'アクティブ', statusInactive: '非アクティブ'},
}}
data={rows}
searchChipsTitle="検索キーワード"
searchChips={chips}
statusMatch={{active: 'active', inactive: 'inactive'}}
/>;