@gravity-ui/dashkit 10.2.0 → 10.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +127 -20
- package/build/cjs/components/DashKit/DashKit.d.ts +11 -1
- package/build/cjs/components/DashKit/DashKit.js +55 -7
- package/build/cjs/components/DashKit/DashKit.js.map +1 -1
- package/build/cjs/components/DashKit/__tests__/controlled-layout.test.d.ts +4 -0
- package/build/cjs/components/DashKit/__tests__/controlled-layout.test.js +196 -0
- package/build/cjs/components/DashKit/__tests__/controlled-layout.test.js.map +1 -0
- package/build/cjs/components/DashKit/__tests__/events.test.d.ts +1 -0
- package/build/cjs/components/DashKit/__tests__/events.test.js +227 -0
- package/build/cjs/components/DashKit/__tests__/events.test.js.map +1 -0
- package/build/cjs/components/DashKitView/DashKitView.d.ts +1 -1
- package/build/cjs/components/DashKitView/DashKitView.js +1 -3
- package/build/cjs/components/DashKitView/DashKitView.js.map +1 -1
- package/build/cjs/components/GridLayout/GroupLayout.js +2 -2
- package/build/cjs/components/GridLayout/GroupLayout.js.map +1 -1
- package/build/cjs/components/GridLayout/ReactGridLayout.d.ts +1 -0
- package/build/cjs/components/GridLayout/ReactGridLayout.js +37 -0
- package/build/cjs/components/GridLayout/ReactGridLayout.js.map +1 -1
- package/build/cjs/components/OverlayControls/OverlayControls.js +1 -1
- package/build/cjs/components/OverlayControls/OverlayControls.js.map +1 -1
- package/build/cjs/context/DashKitContext.d.ts +1 -0
- package/build/cjs/context/DashKitContext.js.map +1 -1
- package/build/cjs/context/DashkitOverlayControlsContext.d.ts +1 -1
- package/build/cjs/context/DashkitOverlayControlsContext.js +2 -2
- package/build/cjs/context/DashkitOverlayControlsContext.js.map +1 -1
- package/build/cjs/hocs/withContext.d.ts +2 -2
- package/build/cjs/hocs/withContext.js +61 -31
- package/build/cjs/hocs/withContext.js.map +1 -1
- package/build/cjs/package.json +1 -1
- package/build/cjs/plugins/Text/Text.js +1 -1
- package/build/cjs/plugins/Text/Text.js.map +1 -1
- package/build/cjs/shared/types/config.d.ts +2 -0
- package/build/cjs/shared/types/config.js +9 -0
- package/build/cjs/shared/types/config.js.map +1 -1
- package/build/cjs/typings/events.d.ts +34 -0
- package/build/cjs/typings/events.js +3 -0
- package/build/cjs/typings/events.js.map +1 -0
- package/build/cjs/typings/index.d.ts +1 -0
- package/build/cjs/typings/index.js +1 -0
- package/build/cjs/typings/index.js.map +1 -1
- package/build/cjs/utils/__tests__/get-layout-patches.test.d.ts +1 -0
- package/build/cjs/utils/__tests__/get-layout-patches.test.js +51 -0
- package/build/cjs/utils/__tests__/get-layout-patches.test.js.map +1 -0
- package/build/cjs/utils/enrichLayoutWithDefaults.d.ts +5 -0
- package/build/cjs/utils/enrichLayoutWithDefaults.js +29 -0
- package/build/cjs/utils/enrichLayoutWithDefaults.js.map +1 -0
- package/build/cjs/utils/events.d.ts +10 -0
- package/build/cjs/utils/events.js +34 -0
- package/build/cjs/utils/events.js.map +1 -0
- package/build/cjs/utils/get-layout-patches.d.ts +3 -0
- package/build/cjs/utils/get-layout-patches.js +23 -0
- package/build/cjs/utils/get-layout-patches.js.map +1 -0
- package/build/cjs/utils/index.d.ts +3 -0
- package/build/cjs/utils/index.js +3 -0
- package/build/cjs/utils/index.js.map +1 -1
- package/build/cjs/utils/update-manager.js +2 -2
- package/build/cjs/utils/update-manager.js.map +1 -1
- package/build/docs/INDEX.md +534 -0
- package/build/esm/components/DashKit/DashKit.d.ts +11 -1
- package/build/esm/components/DashKit/DashKit.js +54 -6
- package/build/esm/components/DashKit/DashKit.js.map +1 -1
- package/build/esm/components/DashKit/__tests__/controlled-layout.test.d.ts +4 -0
- package/build/esm/components/DashKit/__tests__/controlled-layout.test.js +193 -0
- package/build/esm/components/DashKit/__tests__/controlled-layout.test.js.map +1 -0
- package/build/esm/components/DashKit/__tests__/events.test.d.ts +1 -0
- package/build/esm/components/DashKit/__tests__/events.test.js +225 -0
- package/build/esm/components/DashKit/__tests__/events.test.js.map +1 -0
- package/build/esm/components/DashKitView/DashKitView.d.ts +1 -1
- package/build/esm/components/DashKitView/DashKitView.js +1 -3
- package/build/esm/components/DashKitView/DashKitView.js.map +1 -1
- package/build/esm/components/GridLayout/GroupLayout.js +2 -2
- package/build/esm/components/GridLayout/GroupLayout.js.map +1 -1
- package/build/esm/components/GridLayout/ReactGridLayout.d.ts +1 -0
- package/build/esm/components/GridLayout/ReactGridLayout.js +37 -0
- package/build/esm/components/GridLayout/ReactGridLayout.js.map +1 -1
- package/build/esm/components/OverlayControls/OverlayControls.js +2 -2
- package/build/esm/components/OverlayControls/OverlayControls.js.map +1 -1
- package/build/esm/context/DashKitContext.d.ts +1 -0
- package/build/esm/context/DashKitContext.js.map +1 -1
- package/build/esm/context/DashkitOverlayControlsContext.d.ts +1 -1
- package/build/esm/context/DashkitOverlayControlsContext.js +1 -1
- package/build/esm/context/DashkitOverlayControlsContext.js.map +1 -1
- package/build/esm/hocs/withContext.d.ts +2 -2
- package/build/esm/hocs/withContext.js +64 -34
- package/build/esm/hocs/withContext.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/plugins/Text/Text.js +1 -1
- package/build/esm/plugins/Text/Text.js.map +1 -1
- package/build/esm/shared/types/config.d.ts +2 -0
- package/build/esm/shared/types/config.js +8 -1
- package/build/esm/shared/types/config.js.map +1 -1
- package/build/esm/typings/events.d.ts +34 -0
- package/build/esm/typings/events.js +2 -0
- package/build/esm/typings/events.js.map +1 -0
- package/build/esm/typings/index.d.ts +1 -0
- package/build/esm/typings/index.js +1 -0
- package/build/esm/typings/index.js.map +1 -1
- package/build/esm/utils/__tests__/get-layout-patches.test.d.ts +1 -0
- package/build/esm/utils/__tests__/get-layout-patches.test.js +49 -0
- package/build/esm/utils/__tests__/get-layout-patches.test.js.map +1 -0
- package/build/esm/utils/enrichLayoutWithDefaults.d.ts +5 -0
- package/build/esm/utils/enrichLayoutWithDefaults.js +25 -0
- package/build/esm/utils/enrichLayoutWithDefaults.js.map +1 -0
- package/build/esm/utils/events.d.ts +10 -0
- package/build/esm/utils/events.js +30 -0
- package/build/esm/utils/events.js.map +1 -0
- package/build/esm/utils/get-layout-patches.d.ts +3 -0
- package/build/esm/utils/get-layout-patches.js +19 -0
- package/build/esm/utils/get-layout-patches.js.map +1 -0
- package/build/esm/utils/index.d.ts +3 -0
- package/build/esm/utils/index.js +3 -0
- package/build/esm/utils/index.js.map +1 -1
- package/build/esm/utils/update-manager.js +3 -3
- package/build/esm/utils/update-manager.js.map +1 -1
- package/package.json +6 -1
- package/build/cjs/hooks/useCalcLayout.d.ts +0 -3
- package/build/cjs/hooks/useCalcLayout.js +0 -40
- package/build/cjs/hooks/useCalcLayout.js.map +0 -1
- package/build/esm/hooks/useCalcLayout.d.ts +0 -3
- package/build/esm/hooks/useCalcLayout.js +0 -35
- package/build/esm/hooks/useCalcLayout.js.map +0 -1
|
@@ -0,0 +1,534 @@
|
|
|
1
|
+
# @gravity-ui/dashkit documentation
|
|
2
|
+
|
|
3
|
+
Documentation for the **installed** version of `@gravity-ui/dashkit`.
|
|
4
|
+
Your training data may be outdated — these files are the source of truth.
|
|
5
|
+
|
|
6
|
+
Paths are relative to this file (`node_modules/@gravity-ui/dashkit/build/docs/`).
|
|
7
|
+
|
|
8
|
+
## For AI agents
|
|
9
|
+
|
|
10
|
+
A dashboard grid composer that arranges resizable, draggable widgets in a responsive grid via a plugin system — reach for it when you build a user-editable dashboard (add/move/resize/delete widgets) instead of placing individual charts or panels by hand.
|
|
11
|
+
|
|
12
|
+
### When to use
|
|
13
|
+
|
|
14
|
+
- Rendering a configurable dashboard where widgets are positioned, resized, and rearranged on a grid (built on `react-grid-layout`).
|
|
15
|
+
- User-editable layouts: adding/removing widgets from an action panel, drag-and-drop, edit mode with overlay controls.
|
|
16
|
+
- Plugin-based widgets where each widget type (title, text, chart, custom) is registered once and driven by a `config`.
|
|
17
|
+
|
|
18
|
+
### When not to use
|
|
19
|
+
|
|
20
|
+
- For a single, fixed chart or panel, use [`@gravity-ui/charts`](https://gravity-ui.com/charts) or [`@gravity-ui/chartkit`](https://github.com/gravity-ui/chartkit) directly — the grid/plugin machinery is overhead for one widget.
|
|
21
|
+
- For a general-purpose responsive grid that is not a widget dashboard, use `react-grid-layout` directly.
|
|
22
|
+
- For embedding ChartKit-backed chart widgets inside a DashKit dashboard, DashKit is the shell; it still relies on [`@gravity-ui/chartkit`](https://github.com/gravity-ui/chartkit) to render the actual charts.
|
|
23
|
+
|
|
24
|
+
### Common pitfalls
|
|
25
|
+
|
|
26
|
+
- **Hallucinated component `<Dashboard>`** — the export is `<DashKit>` (the drag-and-drop shell is `<DashKitDnDWrapper>` wrapping `<DashKit>` + `<ActionPanel>`).
|
|
27
|
+
- **Mutating `config` instead of using helpers** — use the static `DashKit.setItem({...})` / `DashKit.removeItem({...})` helpers to add/change/remove items so layout and ids stay consistent.
|
|
28
|
+
- **Forgetting `DashKit.setSettings` / `DashKit.registerPlugins`** — the component must be configured (language, grid settings, plugin registration) before it is rendered, or widgets show nothing.
|
|
29
|
+
- **Confusing the two param props** — `defaultGlobalParams` (dashboard-level defaults) vs `globalParams` (URL-overridable globals); both flow into the params generation queue consumed by ChartKit.
|
|
30
|
+
- **Calling `onChange` manually with the `change` event** — when you `event.preventDefault()` in the experimental `change` handler, DashKit keeps the visual state internally; re-setting `config.layout` from props resets that baseline.
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm i @gravity-ui/dashkit @gravity-ui/uikit
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
### DashKit configuration
|
|
41
|
+
|
|
42
|
+
Before using `DashKit` as a react component, it must be configured.
|
|
43
|
+
|
|
44
|
+
- set language
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
import {configure, Lang} from '@gravity-ui/uikit';
|
|
48
|
+
|
|
49
|
+
configure({lang: Lang.En});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
- DashKit.setSettings
|
|
53
|
+
|
|
54
|
+
Used for global DashKit settings (such as margins between widgets, default widget sizes and widget overlay menu)
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
import {DashKit} from '@gravity-ui/dashkit';
|
|
58
|
+
|
|
59
|
+
DashKit.setSettings({
|
|
60
|
+
gridLayout: {margin: [8, 8]},
|
|
61
|
+
isMobile: true,
|
|
62
|
+
// menu: [] as Array<MenuItem>,
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
- DashKit.registerPlugins
|
|
67
|
+
|
|
68
|
+
Registering and configuring plugins
|
|
69
|
+
|
|
70
|
+
```js
|
|
71
|
+
import {DashKit} from '@gravity-ui/dashkit';
|
|
72
|
+
import {pluginTitle, pluginText} from '@gravity-ui/dashkit';
|
|
73
|
+
|
|
74
|
+
DashKit.registerPlugins(
|
|
75
|
+
pluginTitle,
|
|
76
|
+
pluginText.setSettings({
|
|
77
|
+
apiHandler({text}) {
|
|
78
|
+
return api.getMarkdown(text);
|
|
79
|
+
},
|
|
80
|
+
}),
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
DashKit.registerPlugins({
|
|
84
|
+
type: 'custom',
|
|
85
|
+
defaultLayout: {
|
|
86
|
+
w: 10,
|
|
87
|
+
h: 8,
|
|
88
|
+
},
|
|
89
|
+
renderer: function CustomPlugin() {
|
|
90
|
+
return <div>Custom widget with custom controls</div>;
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Config
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
export interface Config {
|
|
99
|
+
salt: string; // to form a unique id
|
|
100
|
+
counter: number; // to form a unique id, only increases
|
|
101
|
+
items: ConfigItem[]; // initial widget states
|
|
102
|
+
layout: ConfigLayout[]; // widget position on the grid https://github.com/react-grid-layout
|
|
103
|
+
aliases: ConfigAliases; // aliases for parameters see #Params
|
|
104
|
+
connections: ConfigConnection[]; // links between widgets see #Params
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Config example:
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
import {DashKitProps} from '@gravity-ui/dashkit';
|
|
112
|
+
|
|
113
|
+
const config: DashKitProps['config'] = {
|
|
114
|
+
salt: '0.46703554571365613',
|
|
115
|
+
counter: 4,
|
|
116
|
+
items: [
|
|
117
|
+
{
|
|
118
|
+
id: 'tT',
|
|
119
|
+
data: {
|
|
120
|
+
size: 'm',
|
|
121
|
+
text: 'Caption',
|
|
122
|
+
showInTOC: true,
|
|
123
|
+
},
|
|
124
|
+
type: 'title',
|
|
125
|
+
namespace: 'default',
|
|
126
|
+
orderId: 1,
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
id: 'Ea',
|
|
130
|
+
data: {
|
|
131
|
+
text: 'mode _editActive',
|
|
132
|
+
_editActive: true,
|
|
133
|
+
},
|
|
134
|
+
type: 'text',
|
|
135
|
+
namespace: 'default',
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
id: 'zR',
|
|
139
|
+
data: {
|
|
140
|
+
text: '### Text',
|
|
141
|
+
},
|
|
142
|
+
type: 'text',
|
|
143
|
+
namespace: 'default',
|
|
144
|
+
orderId: 0,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
id: 'Dk',
|
|
148
|
+
data: {
|
|
149
|
+
foo: 'bar',
|
|
150
|
+
},
|
|
151
|
+
type: 'custom',
|
|
152
|
+
namespace: 'default',
|
|
153
|
+
orderId: 5,
|
|
154
|
+
},
|
|
155
|
+
],
|
|
156
|
+
layout: [
|
|
157
|
+
{
|
|
158
|
+
h: 2,
|
|
159
|
+
i: 'tT',
|
|
160
|
+
w: 36,
|
|
161
|
+
x: 0,
|
|
162
|
+
y: 0,
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
h: 6,
|
|
166
|
+
i: 'Ea',
|
|
167
|
+
w: 12,
|
|
168
|
+
x: 0,
|
|
169
|
+
y: 2,
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
h: 6,
|
|
173
|
+
i: 'zR',
|
|
174
|
+
w: 12,
|
|
175
|
+
x: 12,
|
|
176
|
+
y: 2,
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
h: 4,
|
|
180
|
+
i: 'Dk',
|
|
181
|
+
w: 8,
|
|
182
|
+
x: 0,
|
|
183
|
+
y: 8,
|
|
184
|
+
},
|
|
185
|
+
],
|
|
186
|
+
aliases: {},
|
|
187
|
+
connections: [],
|
|
188
|
+
};
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Add a new item to the config:
|
|
192
|
+
|
|
193
|
+
```ts
|
|
194
|
+
const newLayout = updateLayout: [
|
|
195
|
+
{
|
|
196
|
+
h: 6,
|
|
197
|
+
i: 'Ea',
|
|
198
|
+
w: 12,
|
|
199
|
+
x: 0,
|
|
200
|
+
y: 6,
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
h: 4,
|
|
204
|
+
i: 'Dk',
|
|
205
|
+
w: 8,
|
|
206
|
+
x: 0,
|
|
207
|
+
y: 12,
|
|
208
|
+
},
|
|
209
|
+
];
|
|
210
|
+
|
|
211
|
+
const newConfig = DashKit.setItem({
|
|
212
|
+
item: {
|
|
213
|
+
data: {
|
|
214
|
+
text: `Some text`,
|
|
215
|
+
},
|
|
216
|
+
namespace: 'default',
|
|
217
|
+
type: 'text',
|
|
218
|
+
// Optional. If new item needed to be inserted in current layout with predefined dimensions
|
|
219
|
+
layout: { // Current item inseterted before 'Ea'
|
|
220
|
+
h: 6,
|
|
221
|
+
w: 12,
|
|
222
|
+
x: 0,
|
|
223
|
+
y: 2,
|
|
224
|
+
},,
|
|
225
|
+
},
|
|
226
|
+
config: config,
|
|
227
|
+
options: {
|
|
228
|
+
// Optional. New layout values for existing items when new element is dropped from ActionPanel
|
|
229
|
+
updateLayout: newLayout,
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Change an existing item in the config:
|
|
235
|
+
|
|
236
|
+
```ts
|
|
237
|
+
const newConfig = DashKit.setItem({
|
|
238
|
+
item: {
|
|
239
|
+
id: 'tT', // item.id
|
|
240
|
+
data: {
|
|
241
|
+
size: 'm',
|
|
242
|
+
text: `New caption`,
|
|
243
|
+
},
|
|
244
|
+
namespace: 'default',
|
|
245
|
+
type: 'title',
|
|
246
|
+
},
|
|
247
|
+
config: config,
|
|
248
|
+
});
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Delete an item from the config:
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
import {DashKitProps} from '@gravity-ui/dashkit';
|
|
255
|
+
|
|
256
|
+
const oldItemsStateAndParams: DashKitProps['itemsStateAndParams'] = {};
|
|
257
|
+
|
|
258
|
+
const {config: newConfig, itemsStateAndParams} = DashKit.removeItem({
|
|
259
|
+
id: 'tT', // item.id
|
|
260
|
+
config: config,
|
|
261
|
+
itemsStateAndParams: this.state.itemsStateAndParams,
|
|
262
|
+
});
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Params
|
|
266
|
+
|
|
267
|
+
```ts
|
|
268
|
+
type Params = Record<string, string | string[]>;
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
`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.
|
|
272
|
+
|
|
273
|
+
Generation order:
|
|
274
|
+
|
|
275
|
+
1. `defaultGlobalParams`
|
|
276
|
+
2. Default widget parameters `item.default`
|
|
277
|
+
3. `globalParams`
|
|
278
|
+
4. Parameters from [itemsStateAndParams](#itemsStateAndParams) according to the queue.
|
|
279
|
+
|
|
280
|
+
### itemsStateAndParams
|
|
281
|
+
|
|
282
|
+
Object that stores widget parameters and states as well as a parameter change queue.
|
|
283
|
+
It has a `__meta__` field for storing queue and meta information.
|
|
284
|
+
|
|
285
|
+
```ts
|
|
286
|
+
interface StateAndParamsMeta = {
|
|
287
|
+
__meta__: {
|
|
288
|
+
queue: {id: string}[]; // queue
|
|
289
|
+
version: number; // current version itemsStateAndParams
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
And also widget states and parameters:
|
|
295
|
+
|
|
296
|
+
```ts
|
|
297
|
+
interface ItemsStateAndParamsBase {
|
|
298
|
+
[itemId: string]: {
|
|
299
|
+
state?: Record<string, any>;
|
|
300
|
+
params?: Params;
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
```ts
|
|
306
|
+
type ItemsStateAndParams = StateAndParamsMeta & ItemsStateAndParamsBase;
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Experimental DashKit events
|
|
310
|
+
|
|
311
|
+
> Experimental: this API can change in minor releases.
|
|
312
|
+
|
|
313
|
+
`DashKit` exposes an experimental instance event API. Use a component ref and subscribe with `dashkitRef.current?.on(eventName, handler)`. The method returns an unsubscribe callback.
|
|
314
|
+
|
|
315
|
+
The first supported event is `change`. It is emitted when the layout changes, before `onChange` is called. The handler can read the full next and previous layouts, read layout patches, or call `preventDefault()` to stop the default `onChange` call.
|
|
316
|
+
|
|
317
|
+
```tsx
|
|
318
|
+
import React from 'react';
|
|
319
|
+
import {DashKit} from '@gravity-ui/dashkit';
|
|
320
|
+
import type {DashKitChangeEvent} from '@gravity-ui/dashkit';
|
|
321
|
+
|
|
322
|
+
function Dashboard() {
|
|
323
|
+
const dashkitRef = React.useRef<DashKit>(null);
|
|
324
|
+
|
|
325
|
+
React.useEffect(() => {
|
|
326
|
+
const unsubscribe = dashkitRef.current?.on('change', (event: DashKitChangeEvent) => {
|
|
327
|
+
console.log(event.patches);
|
|
328
|
+
|
|
329
|
+
if (event.patches.length > 0) {
|
|
330
|
+
event.preventDefault();
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
return () => unsubscribe?.();
|
|
335
|
+
}, []);
|
|
336
|
+
|
|
337
|
+
return <DashKit ref={dashkitRef} config={config} editMode={true} onChange={onChange} />;
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
```ts
|
|
342
|
+
type DashKitLayoutPatch = Pick<ConfigLayout, 'i'> &
|
|
343
|
+
Partial<Pick<ConfigLayout, 'x' | 'y' | 'w' | 'h' | 'parent'>>;
|
|
344
|
+
|
|
345
|
+
type DashKitChangeEvent = {
|
|
346
|
+
patches: DashKitLayoutPatch[];
|
|
347
|
+
layout: ConfigLayout[];
|
|
348
|
+
previousLayout: ConfigLayout[];
|
|
349
|
+
preventDefault: () => void;
|
|
350
|
+
readonly defaultPrevented: boolean;
|
|
351
|
+
};
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
#### Event-driven layout updates
|
|
355
|
+
|
|
356
|
+
If you use `preventDefault()` in the `change` event handler, you can now handle layout updates without re-initializing the config prop. DashKit maintains an internal baseline and computes patches incrementally:
|
|
357
|
+
|
|
358
|
+
```tsx
|
|
359
|
+
function Dashboard() {
|
|
360
|
+
const [config, setConfig] = useState(initialConfig);
|
|
361
|
+
const dashkitRef = useRef<DashKit>(null);
|
|
362
|
+
|
|
363
|
+
useEffect(() => {
|
|
364
|
+
const unsubscribe = dashkitRef.current?.on('change', (event) => {
|
|
365
|
+
event.preventDefault(); // Don't call onChange
|
|
366
|
+
|
|
367
|
+
// Send only the incremental patches to your backend
|
|
368
|
+
sendPatches(event.patches);
|
|
369
|
+
|
|
370
|
+
// No need to call setConfig({ ...config, layout: event.layout })
|
|
371
|
+
// DashKit maintains the visual state internally
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
return unsubscribe;
|
|
375
|
+
}, []);
|
|
376
|
+
|
|
377
|
+
return <DashKit ref={dashkitRef} config={config} editMode onChange={() => {}} />;
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
**Important:** If you later update `config.layout` from props (e.g., from server sync), DashKit will reset its internal baseline to match the new prop. This ensures compatibility with both event-driven and controlled workflows.
|
|
382
|
+
|
|
383
|
+
### Menu
|
|
384
|
+
|
|
385
|
+
You can specify custom DashKit widget overlay menu in edit mode
|
|
386
|
+
|
|
387
|
+
```ts
|
|
388
|
+
type MenuItem = {
|
|
389
|
+
id: string; // uniq id
|
|
390
|
+
title?: string; // string title
|
|
391
|
+
icon?: ReactNode; // node of icon
|
|
392
|
+
iconSize?: number | string; // icon size in px as number or as string with units
|
|
393
|
+
handler?: (item: ConfigItem) => void; // custom item action handler
|
|
394
|
+
visible?: (item: ConfigItem) => boolean; // optional visibility handler for filtering menu items
|
|
395
|
+
className?: string; // custom class property
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
// use array of menu items in settings
|
|
399
|
+
<Dashkit overlayMenuItems={[] as Array<MenuItem> | null} />
|
|
400
|
+
|
|
401
|
+
[deprecated]
|
|
402
|
+
// overlayMenuItems property has greater priority over setSettings menu
|
|
403
|
+
DashKit.setSettings({menu: [] as Array<MenuItem>});
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### Draggable items from ActionPanel
|
|
407
|
+
|
|
408
|
+
#### DashKitDnDWrapper
|
|
409
|
+
|
|
410
|
+
```ts
|
|
411
|
+
type DraggedOverItem = {
|
|
412
|
+
h: number;
|
|
413
|
+
w: number;
|
|
414
|
+
type: string;
|
|
415
|
+
parent: string;
|
|
416
|
+
i?: number;
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
interface DashKitDnDWrapperProps {
|
|
420
|
+
dragImageSrc?: string;
|
|
421
|
+
onDragStart?: (dragProps: ItemDragProps) => void;
|
|
422
|
+
onDragEnd?: () => void;
|
|
423
|
+
onDropDragOver?: (
|
|
424
|
+
draggedItem: DraggedOverItem,
|
|
425
|
+
sharedItem: DraggedOverItem | null,
|
|
426
|
+
) => void | boolean;
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
- **dragImageSrc**: Drag image preview, by default used transparent 1px png base64
|
|
431
|
+
- **onDragStart**: Callback called when element is dragged from ActionPanel
|
|
432
|
+
- **onDragEnd**: Callback called when element dropped or drag canceled
|
|
433
|
+
|
|
434
|
+
```ts
|
|
435
|
+
type ItemDragProps = {
|
|
436
|
+
type: string; // Plugin type
|
|
437
|
+
layout?: {
|
|
438
|
+
// Optional. Layout item size for preview and init
|
|
439
|
+
w?: number;
|
|
440
|
+
h?: number;
|
|
441
|
+
};
|
|
442
|
+
extra?: any; // Custom user context
|
|
443
|
+
};
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
```ts
|
|
447
|
+
type ItemDropProps = {
|
|
448
|
+
commit: () => void; // Callback should be called after all config operations are made
|
|
449
|
+
dragProps: ItemDragProps; // Item drag props
|
|
450
|
+
itemLayout: ConfigLayout; // Calculated item layout dimensions
|
|
451
|
+
newLayout: ConfigLayout[]; // New layout after element is dropped
|
|
452
|
+
};
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
#### Example:
|
|
456
|
+
|
|
457
|
+
```jsx
|
|
458
|
+
const overlayMenuItems = [
|
|
459
|
+
{
|
|
460
|
+
id: 'chart',
|
|
461
|
+
icon: <Icon data={ChartColumn} />,
|
|
462
|
+
title: 'Chart',
|
|
463
|
+
qa: 'chart',
|
|
464
|
+
dragProps: { // ItemDragProps
|
|
465
|
+
type: 'custom', // Registered plugin type
|
|
466
|
+
},
|
|
467
|
+
}
|
|
468
|
+
]
|
|
469
|
+
|
|
470
|
+
const onDrop = (dropProps: ItemDropProps) => {
|
|
471
|
+
// ... add element to your config
|
|
472
|
+
dropProps.commit();
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
<DashKitDnDWrapper>
|
|
476
|
+
<DashKit editMode={true} config={config} onChange={onChange} onDrop={onDrop} />
|
|
477
|
+
<ActionPanel items={overlayMenuItems} />
|
|
478
|
+
</DashKitDnDWrapper>
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### CSS API
|
|
482
|
+
|
|
483
|
+
| Name | Description |
|
|
484
|
+
| :--------------------------------------------- | :-------------------- |
|
|
485
|
+
| Action panel variables | |
|
|
486
|
+
| `--dashkit-action-panel-color` | Background color |
|
|
487
|
+
| `--dashkit-action-panel-border-color` | Border color |
|
|
488
|
+
| `--dashkit-action-panel-border-radius` | Border radius |
|
|
489
|
+
| Action panel item variables | |
|
|
490
|
+
| `--dashkit-action-panel-item-color` | Backgroud color |
|
|
491
|
+
| `--dashkit-action-panel-item-text-color` | Text color |
|
|
492
|
+
| `--dashkit-action-panel-item-color-hover` | Hover backgroud color |
|
|
493
|
+
| `--dashkit-action-panel-item-text-color-hover` | Hover text color |
|
|
494
|
+
| Overlay variables | |
|
|
495
|
+
| `--dashkit-overlay-border-color` | Border color |
|
|
496
|
+
| `--dashkit-overlay-color` | Background color |
|
|
497
|
+
| `--dashkit-overlay-opacity` | Opacity |
|
|
498
|
+
| Grid item variables | |
|
|
499
|
+
| `--dashkit-grid-item-edit-opacity` | Opacity |
|
|
500
|
+
| `--dashkit-grid-item-border-radius` | Border radius |
|
|
501
|
+
| Placeholder variables | |
|
|
502
|
+
| `--dashkit-placeholder-color` | Background color |
|
|
503
|
+
| `--dashkit-placeholder-opacity` | Opacity |
|
|
504
|
+
|
|
505
|
+
#### Usage example
|
|
506
|
+
|
|
507
|
+
```css
|
|
508
|
+
.custom-theme-wrapper {
|
|
509
|
+
--dashkit-grid-item-edit-opacit: 1;
|
|
510
|
+
--dashkit-overlay-color: var(--g-color-base-float);
|
|
511
|
+
--dashkit-overlay-border-color: var(--g-color-base-float);
|
|
512
|
+
--dashkit-overlay-opacity: 0.5;
|
|
513
|
+
|
|
514
|
+
--dashkit-action-panel-border-color: var(--g-color-line-info);
|
|
515
|
+
--dashkit-action-panel-color: var(--g-color-base-float-accent);
|
|
516
|
+
--dashkit-action-panel-border-radius: var(--g-border-radius-xxl);
|
|
517
|
+
}
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
```tsx
|
|
521
|
+
// ....
|
|
522
|
+
|
|
523
|
+
const CustomThemeWrapper = (props: {
|
|
524
|
+
dashkitProps: DashkitProps;
|
|
525
|
+
actionPanelProps: ActionPanelProps;
|
|
526
|
+
}) => {
|
|
527
|
+
return (
|
|
528
|
+
<div className="custom-theme-wrapper">
|
|
529
|
+
<Dashkit {...props.dashkitProps} />
|
|
530
|
+
<ActionPanel {...props.actionPanelProps} />
|
|
531
|
+
</div>
|
|
532
|
+
);
|
|
533
|
+
};
|
|
534
|
+
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { Config, ConfigItem, ConfigLayout, GlobalParams, ItemDropProps, ItemsStateAndParams } from "../../shared/index.js";
|
|
3
|
-
import type { AddNewItemOptions, ContextProps, DashKitGroup, ItemManipulationCallback, MenuItem, Plugin, SetConfigItem, Settings, SettingsProps } from "../../typings/index.js";
|
|
3
|
+
import type { AddNewItemOptions, ContextProps, DashKitEventHandler, DashKitEventMap, DashKitEventName, DashKitGroup, ItemManipulationCallback, MenuItem, Plugin, SetConfigItem, Settings, SettingsProps } from "../../typings/index.js";
|
|
4
4
|
import GridLayout from "../GridLayout/GridLayout.js";
|
|
5
5
|
import type { OverlayControlItem, PreparedCopyItemOptions } from "../OverlayControls/OverlayControls.js";
|
|
6
6
|
interface DashKitGeneralProps {
|
|
@@ -72,11 +72,21 @@ export declare class DashKit extends React.PureComponent<DashKitInnerProps> {
|
|
|
72
72
|
groups?: DashKitGroup[];
|
|
73
73
|
}): ConfigLayout[];
|
|
74
74
|
metaRef: React.RefObject<GridLayout | null>;
|
|
75
|
+
private _handlers;
|
|
75
76
|
render(): React.JSX.Element;
|
|
76
77
|
getItemsMeta(): Promise<any>[];
|
|
77
78
|
reloadItems(options?: {
|
|
78
79
|
targetIds?: string[];
|
|
79
80
|
force?: boolean;
|
|
80
81
|
}): void;
|
|
82
|
+
/**
|
|
83
|
+
* @experimental This API can change in minor releases.
|
|
84
|
+
* @param eventName Event name.
|
|
85
|
+
* @param handler Event handler.
|
|
86
|
+
* @returns Unsubscribe callback.
|
|
87
|
+
*/
|
|
88
|
+
on<T extends DashKitEventName>(eventName: T, handler: DashKitEventHandler<T>): () => void;
|
|
89
|
+
[_emitSymbol]: <T extends DashKitEventName>(eventName: T, event: DashKitEventMap[T]) => void;
|
|
90
|
+
private _off;
|
|
81
91
|
}
|
|
82
92
|
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
var _a;
|
|
1
2
|
import React from 'react';
|
|
2
3
|
import noop from "lodash/noop.js";
|
|
3
4
|
import pick from "lodash/pick.js";
|
|
@@ -7,6 +8,12 @@ import { RegisterManager, UpdateManager, reflowLayout } from "../../utils/index.
|
|
|
7
8
|
import { DashKitDnDWrapper } from "../DashKitDnDWrapper/DashKitDnDWrapper.js";
|
|
8
9
|
import DashKitView from "../DashKitView/DashKitView.js";
|
|
9
10
|
const registerManager = new RegisterManager();
|
|
11
|
+
/**
|
|
12
|
+
* @internal Not part of the public API. Do not use in production code.
|
|
13
|
+
* Module-scoped symbol — not accessible to external consumers holding a ref,
|
|
14
|
+
* preventing synthetic event injection via instance._emit.
|
|
15
|
+
*/
|
|
16
|
+
export const _emitSymbol = Symbol('DashKit._emit');
|
|
10
17
|
const getReflowProps = (props) => Object.assign({ compactType: 'vertical', cols: 36 }, pick(props, 'cols', 'maxRows', 'compactType'));
|
|
11
18
|
const getReflowGroupsConfig = (groups = []) => {
|
|
12
19
|
const defaultGridProps = getReflowProps(registerManager.gridLayout);
|
|
@@ -25,6 +32,22 @@ export class DashKit extends React.PureComponent {
|
|
|
25
32
|
constructor() {
|
|
26
33
|
super(...arguments);
|
|
27
34
|
this.metaRef = React.createRef();
|
|
35
|
+
this._handlers = new Map();
|
|
36
|
+
this[_a] = (eventName, event) => {
|
|
37
|
+
const handlers = this._handlers.get(eventName);
|
|
38
|
+
if (!handlers) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
for (const handler of handlers) {
|
|
42
|
+
try {
|
|
43
|
+
handler(event);
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
// eslint-disable-next-line no-console
|
|
47
|
+
console.error('DashKit: event handler error', e);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
28
51
|
}
|
|
29
52
|
static registerPlugins(...plugins) {
|
|
30
53
|
plugins.forEach((plugin) => {
|
|
@@ -50,7 +73,8 @@ export class DashKit extends React.PureComponent {
|
|
|
50
73
|
}
|
|
51
74
|
else {
|
|
52
75
|
const item = setItem;
|
|
53
|
-
const
|
|
76
|
+
const registerManagerItem = registerManager.getItem(item.type);
|
|
77
|
+
const layout = Object.assign({}, registerManagerItem.defaultLayout);
|
|
54
78
|
const reflowLayoutOptions = getReflowGroupsConfig(groups);
|
|
55
79
|
const copyItem = Object.assign({}, item);
|
|
56
80
|
if (copyItem.layout) {
|
|
@@ -77,21 +101,45 @@ export class DashKit extends React.PureComponent {
|
|
|
77
101
|
});
|
|
78
102
|
}
|
|
79
103
|
render() {
|
|
80
|
-
const content = (React.createElement(DashKitView, Object.assign({ registerManager: registerManager, ref: this.metaRef }, this.props)));
|
|
104
|
+
const content = (React.createElement(DashKitView, Object.assign({ registerManager: registerManager, ref: this.metaRef }, this.props, { emitDashKitEvent: this[_emitSymbol] })));
|
|
81
105
|
if (!this.context && this.props.groups) {
|
|
82
106
|
return React.createElement(DashKitDnDWrapper, null, content);
|
|
83
107
|
}
|
|
84
108
|
return content;
|
|
85
109
|
}
|
|
86
110
|
getItemsMeta() {
|
|
87
|
-
var
|
|
88
|
-
return (
|
|
111
|
+
var _b, _c;
|
|
112
|
+
return (_c = (_b = this.metaRef.current) === null || _b === void 0 ? void 0 : _b.getItemsMeta()) !== null && _c !== void 0 ? _c : [];
|
|
89
113
|
}
|
|
90
114
|
reloadItems(options) {
|
|
91
|
-
var
|
|
92
|
-
(
|
|
115
|
+
var _b;
|
|
116
|
+
(_b = this.metaRef.current) === null || _b === void 0 ? void 0 : _b.reloadItems(options);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* @experimental This API can change in minor releases.
|
|
120
|
+
* @param eventName Event name.
|
|
121
|
+
* @param handler Event handler.
|
|
122
|
+
* @returns Unsubscribe callback.
|
|
123
|
+
*/
|
|
124
|
+
on(eventName, handler) {
|
|
125
|
+
var _b;
|
|
126
|
+
if (!this._handlers.has(eventName)) {
|
|
127
|
+
this._handlers.set(eventName, new Set());
|
|
128
|
+
}
|
|
129
|
+
(_b = this._handlers.get(eventName)) === null || _b === void 0 ? void 0 : _b.add(handler);
|
|
130
|
+
return () => this._off(eventName, handler);
|
|
131
|
+
}
|
|
132
|
+
_off(eventName, handler) {
|
|
133
|
+
const handlers = this._handlers.get(eventName);
|
|
134
|
+
if (handlers) {
|
|
135
|
+
handlers.delete(handler);
|
|
136
|
+
if (handlers.size === 0) {
|
|
137
|
+
this._handlers.delete(eventName);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
93
140
|
}
|
|
94
141
|
}
|
|
142
|
+
_a = _emitSymbol;
|
|
95
143
|
DashKit.defaultProps = {
|
|
96
144
|
onItemEdit: noop,
|
|
97
145
|
onChange: noop,
|