ライブラリ / DashKit

DashKit

インタラクティブなダッシュボードを構築するためのグリッドコンポーネント。

@gravity-ui/dashkit · npm package CI storybook

DashKit

ダッシュボードグリッド描画ライブラリです。

インストール

npm i @gravity-ui/dashkit @gravity-ui/uikit

説明

このライブラリは、ウィジェットをグリッド上に配置し、リサイズ、追加、削除するために使用されます。 ウィジェットはReactコンポーネントです。例えば、テキスト、グラフィック、画像などです。

新しいウィジェットはプラグインシステムを通じて追加されます。

プラグイン

カスタムウィジェットを作成するにはプラグインが必要です。

Props

type ItemManipulationCallback = (eventData: {
  layout: Layout[];
  oldItem: Layout;
  newItem: Layout;
  placeholder: Layout;
  e: MouseEvent;
  element: HTMLElement;
}) => void;

interface DashKitProps {
  config: Config;
  editMode: boolean;
  onItemEdit: ({id}: {id: string}) => void;
  onChange: (data: {config: Config; itemsStateAndParams: ItemsStateAndParams}) => void;
  onDrop: (dropProps: ItemDropProps) => void;
  onItemMountChange: (item: ConfigItem, state: {isAsync: boolead; isMounted: boolean}) => void;
  onItemRender: (item: ConfigItem) => void;

  onDragStart?: ItemManipulationCallback;
  onDrag?: ItemManipulationCallback;
  onDragStop?: ItemManipulationCallback;
  onResizeStart?: ItemManipulationCallback;
  onResize?: ItemManipulationCallback;
  onResizeStop?: ItemManipulationCallback;

  defaultGlobalParams: GlobalParams;
  globalParams: GlobalParams;
  itemsStateAndParams: ItemsStateAndParams;
  settings: SettingsProps;
  context: ContextProps;
  overlayControls?: Record<string, OverlayControlItem[]> | null;
  overlayMenuItems?: MenuItems[] | null;
  noOverlay?: boolean;

  focusable?: boolean;
  onItemFocus: (item: ConfigItem) => void;
  onItemBlur: (item: ConfigItem) => void;

  draggableHandleClassName?: string;
  getPreparedCopyItemOptions?: (options: PreparedCopyItemOptions) => PreparedCopyItemOptions;
  onCopyFulfill?: (error: null | Error, data?: PreparedCopyItemOptions) => void;
}
  • config: Configです。
  • editMode: 編集モードが有効かどうかを示します。
  • onItemEdit: ウィジェットの編集をクリックしたときに呼び出されます。
  • onChange: configまたはitemsStateAndParamsが変更されたときに呼び出されます。
  • onDrop: ActionPanelから(#DashKitDnDWrapper)を使用してアイテムがドロップされたときに呼び出されます。
  • onItemMountChange: アイテムのマウント状態が変更されたときに呼び出されます。
  • onItemRender: アイテムのレンダリングが完了したときに呼び出されます。
  • defaultGlobalParams, globalParams: すべてのウィジェットに影響を与えるパラメータです。DataLensでは、defaultGlobalParamsはダッシュボード設定でグローバルに設定されたパラメータです。globalParamsはURLで設定できるグローバルパラメータです。
  • itemsStateAndParams: itemsStateAndParamsです。
  • settings: DashKitの設定です。
  • context: すべてのウィジェットにプロップとして渡されるオブジェクトです。
  • overlayControls: 編集時にウィジェットコントロールをオーバーライドするオブジェクトです。渡されない場合は、基本的なコントロールが表示されます。nullを渡すと、閉じるボタンまたはカスタムメニューのみが表示されます。
  • overlayMenuItems: カスタムドロップダウンメニュー項目です。
  • noOverlay: trueの場合、編集中はオーバーレイとコントロールが表示されません。
  • focusable: trueの場合、グリッドアイテムはフォーカス可能になります。
  • onItemFocus: focusableがtrueでアイテムがフォーカスされたときに呼び出されます。
  • onItemBlur: focusableがtrueでアイテムからフォーカスが外れたときに呼び出されます。
  • draggableHandleClassName: ウィジェットをドラッグ可能にする要素のCSSクラス名です。
  • onDragStart: アイテムのドラッグが開始されたときにReactGridLayoutによって呼び出されます。
  • onDrag: アイテムのドラッグ中にReactGridLayoutによって呼び出されます。
  • onDragStop: アイテムのドラッグが停止したときにReactGridLayoutによって呼び出されます。
  • onResizeStart: アイテムのリサイズが開始されたときにReactGridLayoutによって呼び出されます。
  • onResize: アイテムのリサイズ中にReactGridLayoutによって呼び出されます。
  • onResizeStop: アイテムのリサイズが停止したときにReactGridLayoutによって呼び出されます。
  • getPreparedCopyItemOptions: ローカルストレージに保存する前に、コピーされたアイテムをシリアライズ可能なオブジェクトに変換するために呼び出されます。非推奨のcontext.getPreparedCopyItemOptionsプロップの代わりにこれを使用する必要があります。
  • onCopyFulfill: アイテムのコピーが完了したときに、成功した場合はerror=nullとdataが定義され、そうでない場合はerror: Errorとdataなしで呼び出されます。

使用方法

DashKitの設定

DashKitをReactコンポーネントとして使用する前に、設定が必要です。

  • 言語設定

    import {configure, Lang} from '@gravity-ui/uikit';
    
    configure({lang: Lang.En});
    
  • DashKit.setSettings

    グローバルなDashKit設定(ウィジェット間のマージン、デフォルトのウィジェットサイズ、ウィジェットオーバーレイメニューなど)に使用されます。

    import {DashKit} from '@gravity-ui/dashkit';
    
    DashKit.setSettings({
      gridLayout: {margin: [8, 8]},
      isMobile: true,
      // menu: [] as Array<MenuItem>,
    });
    
  • DashKit.registerPlugins

    プラグインの登録と設定

    import {DashKit} from '@gravity-ui/dashkit';
    import {pluginTitle, pluginText} from '@gravity-ui/dashkit';
    
    DashKit.registerPlugins(
      pluginTitle,
      pluginText.setSettings({
        apiHandler({text}) {
          return api.getMarkdown(text);
        },
      }),
    );
    
    DashKit.registerPlugins({
      type: 'custom',
      defaultLayout: {
        w: 10,
        h: 8,
      },
      renderer: function CustomPlugin() {
        return <div>Custom widget with custom controls</div>;
      },
    });
    

Config

export interface Config {
  salt: string; // 一意のIDを形成するためのソルト
  counter: number; // 一意のIDを形成するためのカウンター、増加し続けます
  items: ConfigItem[]; // 初期ウィジェットの状態
  layout: ConfigLayout[]; // グリッド上のウィジェットの位置 https://github.com/react-grid-layout
  aliases: ConfigAliases; // パラメータのエイリアス #Params参照
  connections: ConfigConnection[]; // ウィジェット間のリンク #Params参照
}

Configの例:

import {DashKitProps} from '@gravity-ui/dashkit';
const config: DashKitProps['config'] = {
  salt: '0.46703554571365613',
  counter: 4,
  items: [
    {
      id: 'tT',
      data: {
        size: 'm',
        text: 'Caption',
        showInTOC: true,
      },
      type: 'title',
      namespace: 'default',
      orderId: 1,
    },
    {
      id: 'Ea',
      data: {
        text: 'mode _editActive',
        _editActive: true,
      },
      type: 'text',
      namespace: 'default',
    },
    {
      id: 'zR',
      data: {
        text: '### Text',
      },
      type: 'text',
      namespace: 'default',
      orderId: 0,
    },
    {
      id: 'Dk',
      data: {
        foo: 'bar',
      },
      type: 'custom',
      namespace: 'default',
      orderId: 5,
    },
  ],
  layout: [
    {
      h: 2,
      i: 'tT',
      w: 36,
      x: 0,
      y: 0,
    },
    {
      h: 6,
      i: 'Ea',
      w: 12,
      x: 0,
      y: 2,
    },
    {
      h: 6,
      i: 'zR',
      w: 12,
      x: 12,
      y: 2,
    },
    {
      h: 4,
      i: 'Dk',
      w: 8,
      x: 0,
      y: 8,
    },
  ],
  aliases: {},
  connections: [],
};

configに新しいアイテムを追加する:

const newLayout = updateLayout: [
  {
    h: 6,
    i: 'Ea',
    w: 12,
    x: 0,
    y: 6,
  },
  {
    h: 4,
    i: 'Dk',
    w: 8,
    x: 0,
    y: 12,
  },
];

const newConfig = DashKit.setItem({
  item: {
    data: {
      text: `Some text`,
    },
    namespace: 'default',
    type: 'text',
    // Optional. If new item needed to be inserted in current layout with predefined dimensions
    layout: { // Current item inseterted before 'Ea'
      h: 6,
      w: 12,
      x: 0,
      y: 2,
    },,
  },
  config: config,
  options: {
    // Optional. New layout values for existing items when new element is dropped from ActionPanel
    updateLayout: newLayout,
  },
});

configの既存アイテムを変更する:

const newConfig = DashKit.setItem({
  item: {
    id: 'tT', // item.id
    data: {
      size: 'm',
      text: `New caption`,
    },
    namespace: 'default',
    type: 'title',
  },
  config: config,
});

configからアイテムを削除する:

import {DashKitProps} from '@gravity-ui/dashkit';

const oldItemsStateAndParams: DashKitProps['itemsStateAndParams'] = {};

const {config: newConfig, itemsStateAndParams} = DashKit.removeItem({
  id: 'tT', // item.id
  config: config,
  itemsStateAndParams: this.state.itemsStateAndParams,
});

Params

type Params = Record<string, string | string[]>;

DashKit は、ウィジェット、リンク、エイリアスのデフォルトパラメータに従ってパラメータを生成します。これらのパラメータは、ChartKit ライブラリに必要です。

生成順序:

  1. defaultGlobalParams
  2. デフォルトのウィジェットパラメータ item.default
  3. globalParams
  4. キューに従った itemsStateAndParams からのパラメータ。

itemsStateAndParams

ウィジェットのパラメータと状態、およびパラメータ変更キューを格納するオブジェクトです。 キューとメタ情報を格納するための __meta__ フィールドがあります。

interface StateAndParamsMeta = {
    __meta__: {
        queue: {id: string}[]; // queue
        version: number; // current version itemsStateAndParams
    };
}

また、ウィジェットの状態とパラメータも含まれます:

interface ItemsStateAndParamsBase {
  [itemId: string]: {
    state?: Record<string, any>;
    params?: Params;
  };
}
type ItemsStateAndParams = StateAndParamsMeta & ItemsStateAndParamsBase;

Experimental DashKit events

Experimental: this API can change in minor releases.

DashKit は、実験的なインスタンスイベント API を公開します。コンポーネントの ref を使用し、dashkitRef.current?.on(eventName, handler) で購読します。このメソッドは、アンサブスクライブコールバックを返します。

最初にサポートされるイベントは change です。これは、レイアウトが変更されたときに、onChange が呼び出される前に発行されます。ハンドラは、次のレイアウトと前のレイアウト全体を読み取ったり、レイアウトパッチを読み取ったり、preventDefault() を呼び出してデフォルトの onChange 呼び出しを停止したりできます。

import React from 'react';
import {DashKit} from '@gravity-ui/dashkit';
import type {DashKitChangeEvent} from '@gravity-ui/dashkit';

function Dashboard() {
  const dashkitRef = React.useRef<DashKit>(null);

  React.useEffect(() => {
    const unsubscribe = dashkitRef.current?.on('change', (event: DashKitChangeEvent) => {
      console.log(event.patches);

      if (event.patches.length > 0) {
        event.preventDefault();
      }
    });

    return () => unsubscribe?.();
  }, []);

  return <DashKit ref={dashkitRef} config={config} editMode={true} onChange={onChange} />;
}
type DashKitLayoutPatch = Pick<ConfigLayout, 'i'> &
  Partial<Pick<ConfigLayout, 'x' | 'y' | 'w' | 'h' | 'parent'>>;

type DashKitChangeEvent = {
  patches: DashKitLayoutPatch[];
  layout: ConfigLayout[];
  previousLayout: ConfigLayout[];
  preventDefault: () => void;
  readonly defaultPrevented: boolean;
};

Event-driven layout updates

preventDefault() を change イベントハンドラーで使用すると、config プロップを再初期化せずにレイアウトの更新を処理できるようになりました。DashKit は内部でベースラインを維持し、パッチをインクリメンタルに計算します。

function Dashboard() {
  const [config, setConfig] = useState(initialConfig);
  const dashkitRef = useRef<DashKit>(null);

  useEffect(() => {
    const unsubscribe = dashkitRef.current?.on('change', (event) => {
      event.preventDefault(); // onChange を呼び出さない

      // インクリメンタルなパッチのみをバックエンドに送信
      sendPatches(event.patches);

      // setConfig({ ...config, layout: event.layout }) を呼び出す必要はありません
      // DashKit は内部でビジュアル状態を維持します
    });

    return unsubscribe;
  }, []);

  return <DashKit ref={dashkitRef} config={config} editMode onChange={() => {}} />;
}

重要: 後でプロップから config.layout を更新した場合(例: サーバー同期から)、DashKit は内部ベースラインをリセットして新しいプロップと一致させます。これにより、イベント駆動型ワークフローと制御型ワークフローの両方との互換性が保証されます。

メニュー

編集モードでカスタム DashKit ウィジェットオーバーレイメニューを指定できます。

type MenuItem = {
  id: string; // 一意のID
  title?: string; // 文字列タイトル
  icon?: ReactNode; // アイコンのノード
  iconSize?: number | string; // アイコンサイズ(px単位の数値または単位付き文字列)
  handler?: (item: ConfigItem) => void; // カスタムアイテムアクションハンドラー
  visible?: (item: ConfigItem) => boolean; // メニューアイテムをフィルタリングするためのオプションの表示ハンドラー
  className?: string; // カスタムクラスプロパティ
};

// 設定でメニューアイテムの配列を使用
<Dashkit overlayMenuItems={[] as Array<MenuItem> | null} />

[非推奨]
// overlayMenuItems プロパティは setSettings のメニューよりも優先されます
DashKit.setSettings({menu: [] as Array<MenuItem>});

ActionPanel からのドラッグ可能なアイテム

DashKitDnDWrapper

type DraggedOverItem = {
  h: number;
  w: number;
  type: string;
  parent: string;
  i?: number;
};

interface DashKitDnDWrapperProps {
  dragImageSrc?: string; // オプションのカスタムドラッグ画像。デフォルトでは、ドラッグされたActionPanelアイテムがプレビューとして表示されます。
  onDragStart?: (dragProps: ItemDragProps) => void; // ActionPanelから要素がドラッグされたときに呼び出されるコールバック
  onDragEnd?: () => void; // 要素がドロップされたかドラッグがキャンセルされたときに呼び出されるコールバック
  onDropDragOver?: (
    draggedItem: DraggedOverItem,
    sharedItem: DraggedOverItem | null,
  ) => void | boolean;
}
  • dragImageSrc: オプションのカスタムドラッグ画像。デフォルトでは、ドラッグされた ActionPanel アイテムがプレビューとして表示されます。
  • onDragStart: ActionPanel から要素がドラッグされたときに呼び出されるコールバック。
  • onDragEnd: 要素がドロップされたかドラッグがキャンセルされたときに呼び出されるコールバック。
type ItemDragProps = {
  type: string; // プラグインタイプ
  layout?: {
    // オプション。プレビューと初期化のためのレイアウトアイテムサイズ
    w?: number;
    h?: number;
  };
  extra?: any; // カスタムユーザーコンテキスト
};
type ItemDropProps = {
  commit: () => void; // すべての設定操作が完了した後、呼び出す必要があるコールバック
  dragProps: ItemDragProps; // アイテムドラッグプロップ
  itemLayout: ConfigLayout; // 計算されたアイテムレイアウトの寸法
  newLayout: ConfigLayout[]; // 要素がドロップされた後の新しいレイアウト
};

例:

const overlayMenuItems = [
  {
    id: 'chart',
    icon: <Icon data={ChartColumn} />,
    title: 'Chart',
    qa: 'chart',
    dragProps: { // ItemDragProps
        type: 'custom', // 登録されたプラグインタイプ
    },
  }
]

const onDrop = (dropProps: ItemDropProps) => {
  // ... 要素を設定に追加
  dropProps.commit();
}

<DashKitDnDWrapper>
  <DashKit editMode={true} config={config} onChange={onChange} onDrop={onDrop} />
  <ActionPanel items={overlayMenuItems} />
</DashKitDnDWrapper>

CSS API

名前説明
Action panel 変数
--dashkit-action-panel-color背景色
--dashkit-action-panel-border-colorボーダー色
--dashkit-action-panel-border-radiusボーダー半径
Action panel アイテム変数
--dashkit-action-panel-item-color背景色
--dashkit-action-panel-item-text-colorテキスト色
--dashkit-action-panel-item-color-hoverホバー時の背景色
--dashkit-action-panel-item-color-draggingドラッグ時の背景色
--dashkit-action-panel-item-text-color-hoverホバー時のテキスト色
--dashkit-action-panel-item-text-color-draggingドラッグ時のテキスト色
Overlay 変数
--dashkit-overlay-border-colorボーダー色
--dashkit-overlay-color背景色
--dashkit-overlay-opacity不透明度
Grid アイテム変数
--dashkit-grid-item-edit-opacity不透明度
--dashkit-grid-item-border-radiusボーダー半径
Placeholder 変数
--dashkit-placeholder-color背景色
--dashkit-placeholder-opacity不透明度

使用例

.custom-theme-wrapper {
  --dashkit-grid-item-edit-opacit: 1;
  --dashkit-overlay-color: var(--g-color-base-float);
  --dashkit-overlay-border-color: var(--g-color-base-float);
  --dashkit-overlay-opacity: 0.5;

  --dashkit-action-panel-border-color: var(--g-color-line-info);
  --dashkit-action-panel-color: var(--g-color-base-float-accent);
  --dashkit-action-panel-border-radius: var(--g-border-radius-xxl);
}
// ....

const CustomThemeWrapper = (props: {
  dashkitProps: DashkitProps;
  actionPanelProps: ActionPanelProps;
}) => {
  return (
    <div className="custom-theme-wrapper">
      <Dashkit {...props.dashkitProps} />
      <ActionPanel {...props.actionPanelProps} />
    </div>
  );
};

開発

ビルドと監視

  • 依存関係のビルド npm ci
  • プロジェクトのビルド npm run build
  • Storybook のビルド npm run start

デフォルトでは、Storybook は http://localhost:7120/ で実行されます。 Storybook を実行中にプロジェクトの変更が常に反映されるとは限らないため、手動でプロジェクトを再ビルドしてから Storybook を再起動することをお勧めします。

開発マシンでの開発用 nginx 設定例

server {
    server_name dashkit.username.ru;

    include common/ssl;

    access_log /home/username/logs/common.access.log;
    error_log /home/username/logs/common.error.log;

    root /home/username/projects/dashkit;

    location / {
        try_files $uri @node;
    }

    location @node {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://127.0.0.1:7120;
        proxy_redirect off;
    }
}

ライセンス

MIT ライセンスで配布されています。詳細は LICENSE を参照してください。

AI エージェント向け

プラグインシステムを介して、レスポンシブなグリッドにリサイズ可能でドラッグ可能なウィジェットを配置するダッシュボードグリッドコンポーザーです。個々のチャートやパネルを手作業で配置する代わりに、ユーザーが編集可能なダッシュボードを構築する際に使用してください。

使用する場面

  • ウィジェットがグリッド上に配置、リサイズ、再配置される設定可能なダッシュボードのレンダリング (react-grid-layout 上に構築)。
  • ユーザー編集可能なレイアウト: アクションパネルからのウィジェットの追加/削除、ドラッグ&ドロップ、オーバーレイコントロール付きの編集モード。
  • 各ウィジェットタイプ (タイトル、テキスト、チャート、カスタム) が一度登録され、config によって駆動されるプラグインベースのウィジェット。

使用しない場面

  • 単一の固定されたチャートやパネルには、@gravity-ui/charts または @gravity-ui/chartkit を直接使用してください。グリッド/プラグインの仕組みは、1つのウィジェットにはオーバーヘッドとなります。
  • ウィジェットダッシュボードではない汎用的なレスポンシブグリッドには、react-grid-layout を直接使用してください。
  • ChartKit バックエンドのチャートウィジェットを DashKit ダッシュボード内に埋め込む場合、DashKit がシェルとなり、実際のチャートのレンダリングには引き続き @gravity-ui/chartkit を使用します。

よくある落とし穴

  • コンポーネント <Dashboard> の誤解 - エクスポートは <DashKit> です (ドラッグ&ドロップシェルは <DashKit> + <ActionPanel> をラップする <DashKitDnDWrapper> です)。
  • ヘルパーを使用せずに config を変更する - アイテムの追加/変更/削除には、静的な DashKit.setItem({...}) / DashKit.removeItem({...}) ヘルパーを使用してください。これにより、レイアウトと ID が一貫性を保ちます。
  • DashKit.setSettings / DashKit.registerPlugins を忘れる - コンポーネントはレンダリング前に設定 (言語、グリッド設定、プラグイン登録) する必要があります。そうしないと、ウィジェットは何も表示されません。
  • 2つのパラメータプロップの混同 - defaultGlobalParams (ダッシュボードレベルのデフォルト) と globalParams (URL で上書き可能なグローバルパラメータ)。どちらも ChartKit が消費するパラメータ生成キューに流れ込みます。
  • 実験的な change ハンドラーで event.preventDefault() を使用した際に、手動で onChange を呼び出す - event.preventDefault() を使用すると、DashKit は内部で視覚的な状態を維持します。config.layout を props から再設定すると、そのベースラインがリセットされます。

AI エージェント向けドキュメント

インストールされているバージョンのエージェント読み取り可能なドキュメントは、node_modules/@gravity-ui/dashkit/build/docs/INDEX.md にあります。

ライブラリについて
スターでライブラリを応援
バージョン
10.5.2
最終更新日
06.10.2026
リポジトリ
github.com/gravity-ui/dashkit
ライセンス
MIT License
メンテナー
コントリビューター