{"id":24755192,"url":"https://github.com/gravity-ui/dashkit","last_synced_at":"2025-12-25T15:46:35.824Z","repository":{"id":51449221,"uuid":"491888380","full_name":"gravity-ui/dashkit","owner":"gravity-ui","description":null,"archived":false,"fork":false,"pushed_at":"2024-04-18T10:23:57.000Z","size":1408,"stargazers_count":10,"open_issues_count":5,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-04-18T14:24:48.916Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gravity-ui.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null}},"created_at":"2022-05-13T12:26:37.000Z","updated_at":"2024-07-19T10:00:25.275Z","dependencies_parsed_at":"2023-11-12T19:24:47.563Z","dependency_job_id":"dc5e3f6e-2a94-40ff-93c5-1a7c00ed4860","html_url":"https://github.com/gravity-ui/dashkit","commit_stats":{"total_commits":45,"total_committers":9,"mean_commits":5.0,"dds":0.7111111111111111,"last_synced_commit":"738ce14a7883a88d3096ed4c9bd21bcc16f3fd20"},"previous_names":["yandex-cloud/dashkit"],"tags_count":93,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gravity-ui%2Fdashkit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gravity-ui%2Fdashkit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gravity-ui%2Fdashkit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gravity-ui%2Fdashkit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gravity-ui","download_url":"https://codeload.github.com/gravity-ui/dashkit/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":236017975,"owners_count":19082013,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-28T12:36:57.335Z","updated_at":"2025-12-25T15:46:35.778Z","avatar_url":"https://github.com/gravity-ui.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @gravity-ui/dashkit \u0026middot; [![npm package](https://img.shields.io/npm/v/@gravity-ui/dashkit)](https://www.npmjs.com/package/@gravity-ui/dashkit) [![CI](https://img.shields.io/github/actions/workflow/status/gravity-ui/dashkit/.github/workflows/ci.yaml?branch=main\u0026label=CI\u0026logo=github)](https://github.com/gravity-ui/dashkit/actions/workflows/ci.yaml?query=branch:main) [![storybook](https://img.shields.io/badge/Storybook-deployed-ff4685)](https://preview.gravity-ui.com/dashkit/)\n\n# DashKit\n\nA dashboard grid rendering library.\n\n## Installation\n\n```bash\nnpm i @gravity-ui/dashkit @gravity-ui/uikit\n```\n\n## Description\n\nThe library is used to line up widgets in a grid, resize them, add new ones, and delete them.\nThe widget is a react component. For example, text, graphics, and images.\n\nNew widgets are added via a plugin system.\n\n### Plugins\n\nPlugins are required to create custom widgets.\n\n### Props\n\n```ts\ntype ItemManipulationCallback = (eventData: {\n    layout: Layouts;\n    oldItem: Layout;\n    newItem: Layout;\n    placeholder: Layout;\n    e: MouseEvent;\n    element: HTMLElement;\n}) =\u003e void;\n\ninterface DashKitProps {\n  config: Config;\n  editMode: boolean;\n  onItemEdit: ({id}: {id: string}) =\u003e void;\n  onChange: (data: {config: Config; itemsStateAndParams: ItemsStateAndParams}) =\u003e void;\n  onDrop: (dropProps: ItemDropProps) =\u003e void;\n  onItemMountChange: (item: ConfigItem, state: {isAsync: boolead; isMounted: boolean}) =\u003e void;\n  onItemRender: (item: ConfigItem) =\u003e void;\n\n  onDragStart?: ItemManipulationCallback;\n  onDrag?: ItemManipulationCallback;\n  onDragStop?: ItemManipulationCallback;\n  onResizeStart?: ItemManipulationCallback;\n  onResize?: ItemManipulationCallback;\n  onResizeStop?: ItemManipulationCallback;\n\n  defaultGlobalParams: GlobalParams;\n  globalParams: GlobalParams;\n  itemsStateAndParams: ItemsStateAndParams;\n  settings: SettingsProps;\n  context: ContextProps;\n  overlayControls?: Record\u003cstring, OverlayControlItem[]\u003e | null;\n  overlayMenuItems?: MenuItems[] | null;\n  noOverlay?: boolean;\n\n  focusable?: boolean;\n  onItemFocus: (item: ConfigItem) =\u003e void;\n  onItemBlur: (item: ConfigItem) =\u003e void;\n\n  draggableHandleClassName?: string;\n  getPreparedCopyItemOptions?: (options: PreparedCopyItemOptions) =\u003e PreparedCopyItemOptions;\n  onCopyFulfill?: (error: null | Error, data?: PreparedCopyItemOptions) =\u003e void;\n}\n```\n\n- **config**: [сonfig](#Config).\n- **editMode**: Whether edit mode is enabled.\n- **onItemEdit**: Called when you click to edit a widget.\n- **onChange**: Called when config or [itemsStateAndParams](#itemsStateAndParams) are changed.\n- **onDrop**: Called when item dropped from ActionPanel using (#DashKitDnDWrapper)\n- **onItemMountChange**: Called when item mount state changed\n- **onItemRender**: Called when item render complete\n- **defaultGlobalParams**, **globalParams**: [Parameters](#Params) that affect all widgets. In DataLens, `defaultGlobalParams` are global parameters set in the dashboard settings. `globalParams` are globals parameters that can be set in the url.\n- **itemsStateAndParams**: [itemsStateAndParams](#itemsStateAndParams).\n- **settings**: DashKit settings.\n- **context**: Object that will be propped up on all widgets.\n- **overlayControls**: Object that overrides widget controls at the time of editing. If not transmitted, basic controls will be displayed. If `null` passed only close button or custom menu will be displayed.\n- **overlayMenuItems**: Custom dropdown menu items\n- **noOverlay**: If `true`, overlay and controls are not displayed while editing.\n- **focusable**: If `true`, grid items will be focusable.\n- **onItemFocus**: Called when `focusable` is true and item is focused.\n- **onItemBlur**: Called when `focusable` is true and item is focused out.\n- **draggableHandleClassName** : СSS class name of the element that makes the widget draggable.\n- **onDragStart**: ReactGridLayout called when item drag started\n- **onDrag**: ReactGridLayout called while item drag\n- **onDragStop**: ReactGridLayout called when item drag stopped\n- **onResizeStart**: ReactGridLayout called when item resize started\n- **onResize**: ReactGridLayout called while item resizing\n- **onResizeStop**: ReactGridLayout called when item resize stoped\n- **getPreparedCopyItemOptions**: Called for converting copied item to serializable object before saving it to localstorage. It should be used instead of deprecated `context.getPreparedCopyItemOptions` prop\n- **onCopyFulfill**: Called when item copy finished with `error=null` and defined `data` on successful operation done and with `error: Error` without `data` otherwise\n\n## Usage\n\n### DashKit configuration\n\nBefore using `DashKit` as a react component, it must be configured.\n\n- set language\n\n  ```js\n  import {configure, Lang} from '@gravity-ui/uikit';\n\n  configure({lang: Lang.En});\n  ```\n\n- DashKit.setSettings\n\n  Used for global DashKit settings (such as margins between widgets, default widget sizes and widget overlay menu)\n\n  ```js\n  import {DashKit} from '@gravity-ui/dashkit';\n\n  DashKit.setSettings({\n    gridLayout: {margin: [8, 8]},\n    isMobile: true,\n    // menu: [] as Array\u003cMenuItem\u003e,\n  });\n  ```\n\n- DashKit.registerPlugins\n\n  Registering and configuring plugins\n\n  ```js\n  import {DashKit} from '@gravity-ui/dashkit';\n  import {pluginTitle, pluginText} from '@gravity-ui/dashkit';\n\n  DashKit.registerPlugins(\n    pluginTitle,\n    pluginText.setSettings({\n      apiHandler({text}) {\n        return api.getMarkdown(text);\n      },\n    }),\n  );\n\n  DashKit.registerPlugins({\n    type: 'custom',\n    defaultLayout: {\n      w: 10,\n      h: 8,\n    },\n    renderer: function CustomPlugin() {\n      return \u003cdiv\u003eCustom widget with custom controls\u003c/div\u003e;\n    },\n  });\n  ```\n\n### Config\n\n```ts\nexport interface Config {\n  salt: string; // to form a unique id\n  counter: number; // to form a unique id, only increases\n  items: ConfigItem[]; //  initial widget states\n  layout: ConfigLayout[]; // widget position on the grid https://github.com/react-grid-layout\n  aliases: ConfigAliases; // aliases for parameters see #Params\n  connections: ConfigConnection[]; // links between widgets see #Params\n}\n```\n\nConfig example:\n\n```ts\nimport {DashKitProps} from '@gravity-ui/dashkit';\n\nconst config: DashKitProps['config'] = {\n  salt: '0.46703554571365613',\n  counter: 4,\n  items: [\n    {\n      id: 'tT',\n      data: {\n        size: 'm',\n        text: 'Caption',\n        showInTOC: true,\n      },\n      type: 'title',\n      namespace: 'default',\n      orderId: 1,\n    },\n    {\n      id: 'Ea',\n      data: {\n        text: 'mode _editActive',\n        _editActive: true,\n      },\n      type: 'text',\n      namespace: 'default',\n    },\n    {\n      id: 'zR',\n      data: {\n        text: '### Text',\n      },\n      type: 'text',\n      namespace: 'default',\n      orderId: 0,\n    },\n    {\n      id: 'Dk',\n      data: {\n        foo: 'bar',\n      },\n      type: 'custom',\n      namespace: 'default',\n      orderId: 5,\n    },\n  ],\n  layout: [\n    {\n      h: 2,\n      i: 'tT',\n      w: 36,\n      x: 0,\n      y: 0,\n    },\n    {\n      h: 6,\n      i: 'Ea',\n      w: 12,\n      x: 0,\n      y: 2,\n    },\n    {\n      h: 6,\n      i: 'zR',\n      w: 12,\n      x: 12,\n      y: 2,\n    },\n    {\n      h: 4,\n      i: 'Dk',\n      w: 8,\n      x: 0,\n      y: 8,\n    },\n  ],\n  aliases: {},\n  connections: [],\n};\n```\n\nAdd a new item to the config:\n\n```ts\nconst newLayout = updateLayout: [\n  {\n    h: 6,\n    i: 'Ea',\n    w: 12,\n    x: 0,\n    y: 6,\n  },\n  {\n    h: 4,\n    i: 'Dk',\n    w: 8,\n    x: 0,\n    y: 12,\n  },\n];\n\nconst newConfig = DashKit.setItem({\n  item: {\n    data: {\n      text: `Some text`,\n    },\n    namespace: 'default',\n    type: 'text',\n    // Optional. If new item needed to be inserted in current layout with predefined dimensions\n    layout: { // Current item inseterted before 'Ea'\n      h: 6,\n      w: 12,\n      x: 0,\n      y: 2,\n    },,\n  },\n  config: config,\n  options: {\n    // Optional. New layout values for existing items when new element is dropped from ActionPanel\n    updateLayout: newLayout,\n  },\n});\n```\n\nChange an existing item in the config:\n\n```ts\nconst newConfig = DashKit.setItem({\n  item: {\n    id: 'tT', // item.id\n    data: {\n      size: 'm',\n      text: `New caption`,\n    },\n    namespace: 'default',\n    type: 'title',\n  },\n  config: config,\n});\n```\n\nDelete an item from the config:\n\n```ts\nimport {DashKitProps} from '@gravity-ui/dashkit';\n\nconst oldItemsStateAndParams: DashKitProps['itemsStateAndParams'] = {};\n\nconst {config: newConfig, itemsStateAndParams} = DashKit.removeItem({\n  id: 'tT', // item.id\n  config: config,\n  itemsStateAndParams: this.state.itemsStateAndParams,\n});\n```\n\n### Params\n\n```ts\ntype Params = Record\u003cstring, string | string[]\u003e;\n```\n\n`DashKit` generates parameters according to the default parameters for widgets, links, and aliases. These parameters are required for the [ChartKit](https://github.com/gravity-ui/chartkit) library.\n\nGeneration order:\n\n1. `defaultGlobalParams`\n2. Default widget parameters `item.default`\n3. `globalParams`\n4. Parameters from [itemsStateAndParams](#itemsStateAndParams) according to the queue.\n\n### itemsStateAndParams\n\nObject that stores widget parameters and states as well as a parameter change queue.\nIt has a `__meta__` field for storing queue and meta information.\n\n```ts\ninterface StateAndParamsMeta = {\n    __meta__: {\n        queue: {id: string}[]; // queue\n        version: number; // current version itemsStateAndParams\n    };\n}\n```\n\nAnd also widget states and parameters:\n\n```ts\ninterface ItemsStateAndParamsBase {\n  [itemId: string]: {\n    state?: Record\u003cstring, any\u003e;\n    params?: Params;\n  };\n}\n```\n\n```ts\ntype ItemsStateAndParams = StateAndParamsMeta \u0026 ItemsStateAndParamsBase;\n```\n\n### Menu\n\nYou can specify custom DashKit widget overlay menu in edit mode\n\n```ts\ntype MenuItem = {\n  id: string; // uniq id\n  title?: string; // string title\n  icon?: ReactNode; // node of icon\n  iconSize?: number | string; // icon size in px as number or as string with units\n  handler?: (item: ConfigItem) =\u003e void; // custom item action handler\n  visible?: (item: ConfigItem) =\u003e boolean; // optional visibility handler for filtering menu items\n  className?: string; // custom class property\n};\n\n// use array of menu items in settings\n\u003cDashkit overlayMenuItems={[] as Array\u003cMenuItem\u003e | null} /\u003e\n\n[deprecated]\n// overlayMenuItems property has greater priority over setSettings menu\nDashKit.setSettings({menu: [] as Array\u003cMenuItem\u003e});\n```\n\n### Draggable items from ActionPanel\n\n#### DashKitDnDWrapper\n\n```ts\ntype DraggedOverItem = {\n  h: number;\n  w: number;\n  type: string;\n  parent: string;\n  i?: number;\n};\n\ninterface DashKitDnDWrapperProps {\n  dragImageSrc?: string;\n  onDragStart?: (dragProps: ItemDragProps) =\u003e void;\n  onDragEnd?: () =\u003e void;\n  onDropDragOver?: (draggedItem: DraggedOverItem, sharedItem: DraggedOverItem | null) =\u003e void | boolean;\n}\n```\n\n- **dragImageSrc**: Drag image preview, by default used transparent 1px png base64\n- **onDragStart**: Callback called when element is dragged from ActionPanel\n- **onDragEnd**: Callback called when element dropped or drag canceled\n\n```ts\ntype ItemDragProps = {\n    type: string; // Plugin type\n    layout?: { // Optional. Layout item size for preview and init\n        w?: number;\n        h?: number;\n    };\n    extra?: any; // Custom user context\n};\n```\n\n```ts\ntype ItemDropProps = {\n    commit: () =\u003e void; // Callback should be called after all config operations are made\n    dragProps: ItemDragProps; // Item drag props\n    itemLayout: ConfigLayout; // Calculated item layout dimensions\n    newLayout: ConfigLayout[]; // New layout after element is dropped\n};\n```\n\n\n#### Example:\n\n```jsx\nconst overlayMenuItems = [\n  {\n    id: 'chart',\n    icon: \u003cIcon data={ChartColumn} /\u003e,\n    title: 'Chart',\n    qa: 'chart',\n    dragProps: { // ItemDragProps\n        type: 'custom', // Registered plugin type\n    },\n  }\n]\n\nconst onDrop = (dropProps: ItemDropProps) =\u003e {\n  // ... add element to your config\n  dropProps.commit();\n}\n\n\u003cDashKitDnDWrapper\u003e\n  \u003cDashKit editMode={true} config={config} onChange={onChange} onDrop={onDrop} /\u003e\n  \u003cActionPanel items={overlayMenuItems} /\u003e\n\u003c/DashKitDnDWrapper\u003e\n```\n\n### CSS API\n\n| Name                                           | Description           |\n| :--------------------------------------------- | :-------------------- |\n| Action panel variables                         |                       |\n| `--dashkit-action-panel-color`                 | Background color      |\n| `--dashkit-action-panel-border-color`          | Border color          |\n| `--dashkit-action-panel-border-radius`         | Border radius         |\n| Action panel item variables                    |                       |\n| `--dashkit-action-panel-item-color`            | Backgroud color       |\n| `--dashkit-action-panel-item-text-color`       | Text color            |\n| `--dashkit-action-panel-item-color-hover`      | Hover backgroud color |\n| `--dashkit-action-panel-item-text-color-hover` | Hover text color      |\n| Overlay variables                              |                       |\n| `--dashkit-overlay-border-color`               | Border color          |\n| `--dashkit-overlay-color`                      | Background color      |\n| `--dashkit-overlay-opacity`                    | Opacity               |\n| Grid item variables                            |                       |\n| `--dashkit-grid-item-edit-opacity`             | Opacity               |\n| `--dashkit-grid-item-border-radius`            | Border radius         |\n| Placeholder variables                          |                       |\n| `--dashkit-placeholder-color`                  | Background color      |\n| `--dashkit-placeholder-opacity`                | Opacity               |\n\n#### Usage example\n\n```css\n.custom-theme-wrapper {\n  --dashkit-grid-item-edit-opacit: 1;\n  --dashkit-overlay-color: var(--g-color-base-float);\n  --dashkit-overlay-border-color: var(--g-color-base-float);\n  --dashkit-overlay-opacity: 0.5;\n\n  --dashkit-action-panel-border-color: var(--g-color-line-info);\n  --dashkit-action-panel-color: var(--g-color-base-float-accent);\n  --dashkit-action-panel-border-radius: var(--g-border-radius-xxl);\n}\n```\n\n```tsx\n// ....\n\nconst CustomThemeWrapper = (props: {\n  dashkitProps: DashkitProps;\n  actionPanelProps: ActionPanelProps;\n}) =\u003e {\n  return (\n    \u003cdiv className=\"custom-theme-wrapper\"\u003e\n      \u003cDashkit {...props.dashkitProps} /\u003e\n      \u003cActionPanel {...props.actionPanelProps} /\u003e\n    \u003c/div\u003e\n  );\n};\n```\n\n## Development\n\n### Build \u0026 watch\n\n- Build dependencies `npm ci`\n- Build a project `npm run build`\n- Build storybook `npm run start`\n\nBy default, storybook runs on `http://localhost:7120/`.\nNew changes from a project aren't always picked up when storybook is running, so it's better to rebuild a project manually and restart storybook.\n\n\n### Example of an nginx config for development on a dev machine\n\n```bash\nserver {\n    server_name dashkit.username.ru;\n\n    include common/ssl;\n\n    access_log /home/username/logs/common.access.log;\n    error_log /home/username/logs/common.error.log;\n\n    root /home/username/projects/dashkit;\n\n    location / {\n        try_files $uri @node;\n    }\n\n    location @node {\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_pass http://127.0.0.1:7120;\n        proxy_redirect off;\n    }\n}\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgravity-ui%2Fdashkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgravity-ui%2Fdashkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgravity-ui%2Fdashkit/lists"}