@gravity-ui/dashkit 10.4.4 → 10.5.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.
Files changed (31) hide show
  1. package/README.md +3 -1
  2. package/build/cjs/components/ActionPanel/ActionPanel.css +53 -24
  3. package/build/cjs/components/ActionPanel/ActionPanel.js +27 -1
  4. package/build/cjs/components/ActionPanel/ActionPanel.js.map +1 -1
  5. package/build/cjs/components/DashKitDnDWrapper/DashKitDnDWrapper.js +4 -2
  6. package/build/cjs/components/DashKitDnDWrapper/DashKitDnDWrapper.js.map +1 -1
  7. package/build/cjs/components/GridItem/GridItem.css +4 -2
  8. package/build/cjs/context/DashKitDnDContext.d.ts +1 -1
  9. package/build/cjs/context/DashKitDnDContext.js.map +1 -1
  10. package/build/cjs/hooks/__tests__/useDnDItemProps.test.d.ts +2 -0
  11. package/build/cjs/hooks/__tests__/useDnDItemProps.test.js +45 -0
  12. package/build/cjs/hooks/__tests__/useDnDItemProps.test.js.map +1 -0
  13. package/build/cjs/hooks/useDnDItemProps.js +1 -1
  14. package/build/cjs/hooks/useDnDItemProps.js.map +1 -1
  15. package/build/cjs/package.json +1 -1
  16. package/build/docs/INDEX.md +3 -1
  17. package/build/esm/components/ActionPanel/ActionPanel.css +53 -24
  18. package/build/esm/components/ActionPanel/ActionPanel.js +27 -1
  19. package/build/esm/components/ActionPanel/ActionPanel.js.map +1 -1
  20. package/build/esm/components/DashKitDnDWrapper/DashKitDnDWrapper.js +4 -2
  21. package/build/esm/components/DashKitDnDWrapper/DashKitDnDWrapper.js.map +1 -1
  22. package/build/esm/components/GridItem/GridItem.css +4 -2
  23. package/build/esm/context/DashKitDnDContext.d.ts +1 -1
  24. package/build/esm/context/DashKitDnDContext.js.map +1 -1
  25. package/build/esm/hooks/__tests__/useDnDItemProps.test.d.ts +2 -0
  26. package/build/esm/hooks/__tests__/useDnDItemProps.test.js +42 -0
  27. package/build/esm/hooks/__tests__/useDnDItemProps.test.js.map +1 -0
  28. package/build/esm/hooks/useDnDItemProps.js +1 -1
  29. package/build/esm/hooks/useDnDItemProps.js.map +1 -1
  30. package/build/esm/package.json +1 -1
  31. package/package.json +1 -1
package/README.md CHANGED
@@ -487,7 +487,7 @@ interface DashKitDnDWrapperProps {
487
487
  }
488
488
  ```
489
489
 
490
- - **dragImageSrc**: Drag image preview, by default used transparent 1px png base64
490
+ - **dragImageSrc**: Optional custom drag image. By default, the dragged ActionPanel item is shown as the preview.
491
491
  - **onDragStart**: Callback called when element is dragged from ActionPanel
492
492
  - **onDragEnd**: Callback called when element dropped or drag canceled
493
493
 
@@ -550,7 +550,9 @@ const onDrop = (dropProps: ItemDropProps) => {
550
550
  | `--dashkit-action-panel-item-color` | Backgroud color |
551
551
  | `--dashkit-action-panel-item-text-color` | Text color |
552
552
  | `--dashkit-action-panel-item-color-hover` | Hover backgroud color |
553
+ | `--dashkit-action-panel-item-color-dragging` | Drag background color |
553
554
  | `--dashkit-action-panel-item-text-color-hover` | Hover text color |
555
+ | `--dashkit-action-panel-item-text-color-dragging` | Drag text color |
554
556
  | Overlay variables | |
555
557
  | `--dashkit-overlay-border-color` | Border color |
556
558
  | `--dashkit-overlay-color` | Background color |
@@ -1,20 +1,25 @@
1
1
  .dashkit-action-panel {
2
- --_--dashkit-action-panel-color: var(--dashkit-action-panel-color, var(--g-color-base-float));
3
- --_--dashkit-action-panel-border-color: var(
4
- --dashkit-action-panel-border-color,
5
- var(--g-color-base-brand)
2
+ --_--dashkit-action-panel-color: var(
3
+ --dashkit-action-panel-color,
4
+ var(--g-color-base-float-heavy)
6
5
  );
6
+ --_--dashkit-action-panel-border-color: var(--dashkit-action-panel-border-color, transparent);
7
7
  --_--dashkit-action-panel-border-radius: var(
8
8
  --dashkit-action-panel-border-radius,
9
- var(--g-border-radius-xl)
9
+ var(--g-border-radius-2xl, 16px)
10
10
  );
11
11
  background-color: var(--_--dashkit-action-panel-color);
12
+ backdrop-filter: blur(18px);
12
13
  position: fixed;
13
14
  bottom: 20px;
14
15
  display: flex;
16
+ width: max-content;
17
+ max-width: calc(100vw - 40px);
18
+ overflow-x: auto;
15
19
  border-radius: var(--_--dashkit-action-panel-border-radius);
16
- border: 2px solid var(--_--dashkit-action-panel-border-color);
17
- padding: 8px;
20
+ outline: 2px solid var(--_--dashkit-action-panel-border-color);
21
+ outline-offset: -2px;
22
+ padding: 6px;
18
23
  gap: 0;
19
24
  left: 50%;
20
25
  transform: translateX(-50%) translateY(0);
@@ -40,46 +45,70 @@
40
45
  --_--dashkit-action-panel-item-color: var(--dashkit-action-panel-item-color, transparent);
41
46
  --_--dashkit-action-panel-item-text-color: var(
42
47
  --dashkit-action-panel-item-text-color,
43
- var(--g-color-text-primary)
48
+ var(--g-color-text-light-primary)
44
49
  );
45
50
  --_--dashkit-action-panel-item-color-hover: var(
46
51
  --dashkit-action-panel-item-color-hover,
47
- var(--g-color-base-simple-hover)
52
+ var(--g-color-base-light-simple-hover)
53
+ );
54
+ --_--dashkit-action-panel-item-color-dragging: var(
55
+ --dashkit-action-panel-item-color-dragging,
56
+ var(--g-color-base-float-heavy)
48
57
  );
49
58
  --_--dashkit-action-panel-item-text-color-hover: var(
50
59
  --dashkit-action-panel-item-text-color-hover,
51
- var(--g-color-text-primary)
60
+ var(--g-color-text-light-primary)
52
61
  );
53
- height: 68px;
54
- width: 98px;
62
+ min-height: 40px;
63
+ max-width: 200px;
64
+ flex: 0 0 auto;
55
65
  display: flex;
56
- flex-direction: column;
66
+ gap: 4px;
57
67
  justify-content: center;
58
68
  align-items: center;
59
- transition: 300ms color ease-in-out, 300ms background-color ease-in-out;
60
- border-radius: 6px;
61
- padding: 0 12px;
69
+ border-radius: var(--g-border-radius-xl);
70
+ padding: 0 16px;
62
71
  box-sizing: border-box;
63
72
  white-space: nowrap;
64
- overflow: hidden;
65
73
  background-color: var(--_--dashkit-action-panel-item-color);
66
74
  color: var(--_--dashkit-action-panel-item-text-color);
67
- will-change: color, backgroung-color;
68
- }
69
- .dashkit-action-panel__item:hover {
70
75
  cursor: pointer;
76
+ }
77
+ .dashkit-action-panel__item:hover, .dashkit-action-panel__item:focus-visible {
71
78
  background-color: var(--_--dashkit-action-panel-item-color-hover);
72
79
  color: var(--_--dashkit-action-panel-item-text-color-hover);
73
80
  }
81
+ .dashkit-action-panel__item_draggable {
82
+ transform: translate(0, 0);
83
+ cursor: grab;
84
+ }
85
+ .dashkit-action-panel__item_draggable:hover, .dashkit-action-panel__item_draggable:active {
86
+ transform: translateY(-2px);
87
+ box-shadow: 0 3px 5px rgba(0, 0, 0, 0.15);
88
+ }
89
+ .dashkit-action-panel__item_draggable:active {
90
+ cursor: grabbing;
91
+ }
92
+ .dashkit-action-panel__item_dragging, .dashkit-action-panel__item_dragging:hover {
93
+ transform: translate(0, 0);
94
+ background-color: var(--_--dashkit-action-panel-item-color-dragging);
95
+ color: var(--dashkit-action-panel-item-text-color-dragging, var(--g-color-text-light-primary));
96
+ }
97
+ .dashkit-action-panel__item_dragging-source-disabled, .dashkit-action-panel__item_dragging-source-disabled:hover {
98
+ opacity: 0.5;
99
+ box-shadow: none;
100
+ }
74
101
  .dashkit-action-panel__icon {
75
- margin-bottom: 4px;
102
+ display: flex;
103
+ flex: 0 0 auto;
104
+ align-items: center;
105
+ justify-content: center;
76
106
  }
77
107
  .dashkit-action-panel__title {
78
- font-size: 13px;
108
+ min-width: 0;
109
+ font-size: 12px;
79
110
  font-weight: 400;
80
111
  line-height: 16px;
81
- max-width: 100%;
82
- white-space: nowrap;
83
112
  overflow: hidden;
84
113
  text-overflow: ellipsis;
85
114
  }
@@ -10,7 +10,33 @@ require("./ActionPanel.css");
10
10
  const b = (0, cn_1.cn)('dashkit-action-panel');
11
11
  const ActionPanelItemContainer = ({ item }) => {
12
12
  const dndProps = (0, useDnDItemProps_1.useDnDItemProps)(item);
13
- return (react_1.default.createElement("div", Object.assign({ role: "button", className: b('item', { draggable: Boolean(dndProps) }, item.className), onClick: item.onClick, "data-qa": item.qa }, dndProps),
13
+ const draggingClassName = `${b('item')}_dragging`;
14
+ const disabledSourceClassName = `${b('item')}_dragging-source-disabled`;
15
+ const disableSourceTimer = react_1.default.useRef(null);
16
+ react_1.default.useEffect(() => () => {
17
+ if (disableSourceTimer.current !== null) {
18
+ clearTimeout(disableSourceTimer.current);
19
+ }
20
+ }, []);
21
+ const onDragStart = (event) => {
22
+ const source = event.currentTarget;
23
+ source.classList.add(draggingClassName);
24
+ dndProps === null || dndProps === void 0 ? void 0 : dndProps.onDragStart(event);
25
+ // The native drag image captures the solid item before the panel source is disabled.
26
+ disableSourceTimer.current = setTimeout(() => {
27
+ source.classList.add(disabledSourceClassName);
28
+ disableSourceTimer.current = null;
29
+ }, 0);
30
+ };
31
+ const onDragEnd = (event) => {
32
+ if (disableSourceTimer.current !== null) {
33
+ clearTimeout(disableSourceTimer.current);
34
+ disableSourceTimer.current = null;
35
+ }
36
+ event.currentTarget.classList.remove(draggingClassName, disabledSourceClassName);
37
+ dndProps === null || dndProps === void 0 ? void 0 : dndProps.onDragEnd(event);
38
+ };
39
+ return (react_1.default.createElement("div", Object.assign({ role: "button", className: b('item', { draggable: Boolean(dndProps) }, item.className), onClick: item.onClick, "data-qa": item.qa }, dndProps, { onDragStart: dndProps ? onDragStart : undefined, onDragEnd: dndProps ? onDragEnd : undefined }),
14
40
  react_1.default.createElement("div", { className: b('icon') }, item.icon),
15
41
  react_1.default.createElement("div", { className: b('title'), title: item.title }, item.title)));
16
42
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ActionPanel.js","sourceRoot":"../../../../src","sources":["components/ActionPanel/ActionPanel.tsx"],"names":[],"mappings":";;;;AAAA,0DAA0B;AAE1B,mEAAqD;AAErD,oEAA4D;AAC5D,0CAAkC;AAIlC,6BAA4B;AAE5B,MAAM,CAAC,GAAG,IAAA,OAAE,EAAC,sBAAsB,CAAC,CAAC;AAE9B,MAAM,wBAAwB,GAAG,CAAC,EAAC,IAAI,EAA0B,EAAE,EAAE;IACxE,MAAM,QAAQ,GAAG,IAAA,iCAAe,EAAC,IAAI,CAAC,CAAC;IAEvC,OAAO,CACH,qDACI,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,EAAC,SAAS,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAC,EAAE,IAAI,CAAC,SAAS,CAAC,EACpE,OAAO,EAAE,IAAI,CAAC,OAAO,aACZ,IAAI,CAAC,EAAE,IACZ,QAAQ;QAEZ,uCAAK,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,IAAG,IAAI,CAAC,IAAI,CAAO;QAC5C,uCAAK,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,IACxC,IAAI,CAAC,KAAK,CACT,CACJ,CACT,CAAC;AACN,CAAC,CAAC;AAjBW,QAAA,wBAAwB,4BAiBnC;AAEK,MAAM,WAAW,GAAG,CAAC,KAAuB,EAAE,EAAE;;IACnD,MAAM,UAAU,GAAG,MAAA,KAAK,CAAC,OAAO,mCAAI,KAAK,CAAC;IAC1C,MAAM,UAAU,GAAG,MAAA,KAAK,CAAC,eAAe,mCAAI,KAAK,CAAC;IAClD,MAAM,OAAO,GAAG,eAAK,CAAC,MAAM,CAAwB,IAAI,CAAC,CAAC;IAE1D,MAAM,OAAO,GAAG,CACZ,uCAAK,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,IACjD,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAiB,EAAE,EAAE;YAArB,EAAC,MAAM,OAAU,EAAL,IAAI,sBAAhB,UAAiB,CAAD;QAC9B,MAAM,GAAG,GAAG,mBAAmB,IAAI,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,QAAQ,GAAG,8BAAC,gCAAwB,IAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,GAAI,CAAC;QAEpE,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,iCAAK,IAAI,KAAE,GAAG,EAAE,QAAQ,IAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;IAChE,CAAC,CAAC,CACA,CACT,CAAC;IAEF,IAAI,UAAU,EAAE,CAAC;QACb,OAAO,CACH,8BAAC,sCAAa,IACV,EAAE,EAAE,CAAC,UAAU,EACf,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,EACnB,OAAO,EAAE,GAAG,EACZ,aAAa,UAEZ,OAAO,CACI,CACnB,CAAC;IACN,CAAC;SAAM,CAAC;QACJ,OAAO,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;IACvC,CAAC;AACL,CAAC,CAAC;AA/BW,QAAA,WAAW,eA+BtB","sourcesContent":["import React from 'react';\n\nimport {CSSTransition} from 'react-transition-group';\n\nimport {useDnDItemProps} from '../../hooks/useDnDItemProps';\nimport {cn} from '../../utils/cn';\n\nimport {ActionPanelItem, ActionPanelProps} from './types';\n\nimport './ActionPanel.scss';\n\nconst b = cn('dashkit-action-panel');\n\nexport const ActionPanelItemContainer = ({item}: {item: ActionPanelItem}) => {\n const dndProps = useDnDItemProps(item);\n\n return (\n <div\n role=\"button\"\n className={b('item', {draggable: Boolean(dndProps)}, item.className)}\n onClick={item.onClick}\n data-qa={item.qa}\n {...dndProps}\n >\n <div className={b('icon')}>{item.icon}</div>\n <div className={b('title')} title={item.title}>\n {item.title}\n </div>\n </div>\n );\n};\n\nexport const ActionPanel = (props: ActionPanelProps) => {\n const isDisabled = props.disable ?? false;\n const isAnimated = props.toggleAnimation ?? false;\n const nodeRef = React.useRef<HTMLDivElement | null>(null);\n\n const content = (\n <div ref={nodeRef} className={b(null, props.className)}>\n {props.items.map(({wrapTo, ...item}) => {\n const key = `dk-action-panel-${item.id}`;\n const children = <ActionPanelItemContainer key={key} item={item} />;\n\n return wrapTo ? wrapTo({...item, key, children}) : children;\n })}\n </div>\n );\n\n if (isAnimated) {\n return (\n <CSSTransition\n in={!isDisabled}\n nodeRef={nodeRef}\n classNames={b(null)}\n timeout={300}\n unmountOnExit\n >\n {content}\n </CSSTransition>\n );\n } else {\n return isDisabled ? null : content;\n }\n};\n"]}
1
+ {"version":3,"file":"ActionPanel.js","sourceRoot":"../../../../src","sources":["components/ActionPanel/ActionPanel.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\n\nimport {CSSTransition} from 'react-transition-group';\n\nimport {useDnDItemProps} from '../../hooks/useDnDItemProps';\nimport {cn} from '../../utils/cn';\n\nimport {ActionPanelItem, ActionPanelProps} from './types';\n\nimport './ActionPanel.scss';\n\nconst b = cn('dashkit-action-panel');\n\nexport const ActionPanelItemContainer = ({item}: {item: ActionPanelItem}) => {\n const dndProps = useDnDItemProps(item);\n const draggingClassName = `${b('item')}_dragging`;\n const disabledSourceClassName = `${b('item')}_dragging-source-disabled`;\n const disableSourceTimer = React.useRef<ReturnType<typeof setTimeout> | null>(null);\n\n React.useEffect(\n () => () => {\n if (disableSourceTimer.current !== null) {\n clearTimeout(disableSourceTimer.current);\n }\n },\n [],\n );\n\n const onDragStart = (event: React.DragEvent<HTMLDivElement>) => {\n const source = event.currentTarget;\n source.classList.add(draggingClassName);\n dndProps?.onDragStart(event);\n // The native drag image captures the solid item before the panel source is disabled.\n disableSourceTimer.current = setTimeout(() => {\n source.classList.add(disabledSourceClassName);\n disableSourceTimer.current = null;\n }, 0);\n };\n\n const onDragEnd = (event: React.DragEvent<HTMLDivElement>) => {\n if (disableSourceTimer.current !== null) {\n clearTimeout(disableSourceTimer.current);\n disableSourceTimer.current = null;\n }\n event.currentTarget.classList.remove(draggingClassName, disabledSourceClassName);\n dndProps?.onDragEnd(event);\n };\n\n return (\n <div\n role=\"button\"\n className={b('item', {draggable: Boolean(dndProps)}, item.className)}\n onClick={item.onClick}\n data-qa={item.qa}\n {...dndProps}\n onDragStart={dndProps ? onDragStart : undefined}\n onDragEnd={dndProps ? onDragEnd : undefined}\n >\n <div className={b('icon')}>{item.icon}</div>\n <div className={b('title')} title={item.title}>\n {item.title}\n </div>\n </div>\n );\n};\n\nexport const ActionPanel = (props: ActionPanelProps) => {\n const isDisabled = props.disable ?? false;\n const isAnimated = props.toggleAnimation ?? false;\n const nodeRef = React.useRef<HTMLDivElement | null>(null);\n\n const content = (\n <div ref={nodeRef} className={b(null, props.className)}>\n {props.items.map(({wrapTo, ...item}) => {\n const key = `dk-action-panel-${item.id}`;\n const children = <ActionPanelItemContainer key={key} item={item} />;\n\n return wrapTo ? wrapTo({...item, key, children}) : children;\n })}\n </div>\n );\n\n if (isAnimated) {\n return (\n <CSSTransition\n in={!isDisabled}\n nodeRef={nodeRef}\n classNames={b(null)}\n timeout={300}\n unmountOnExit\n >\n {content}\n </CSSTransition>\n );\n } else {\n return isDisabled ? null : content;\n }\n};\n"]}
@@ -4,12 +4,14 @@ exports.DashKitDnDWrapper = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const context_1 = require("../../context/index.js");
7
- const defaultImageSrc = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=';
8
7
  const DashKitDnDWrapper = (props) => {
9
8
  const [dragProps, setDragProps] = react_1.default.useState(null);
10
9
  const dragImagePreview = react_1.default.useMemo(() => {
10
+ if (!props.dragImageSrc) {
11
+ return null;
12
+ }
11
13
  const img = new Image();
12
- img.src = props.dragImageSrc || defaultImageSrc;
14
+ img.src = props.dragImageSrc;
13
15
  return img;
14
16
  }, [props.dragImageSrc]);
15
17
  const onDragStartProp = props.onDragStart;
@@ -1 +1 @@
1
- {"version":3,"file":"DashKitDnDWrapper.js","sourceRoot":"../../../../src","sources":["components/DashKitDnDWrapper/DashKitDnDWrapper.tsx"],"names":[],"mappings":";;;;AAAA,0DAA0B;AAE1B,oDAAgD;AAchD,MAAM,eAAe,GACjB,oHAAoH,CAAC;AAElH,MAAM,iBAAiB,GAAqC,CAAC,KAAK,EAAE,EAAE;IACzE,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,eAAK,CAAC,QAAQ,CAAuB,IAAI,CAAC,CAAC;IAE7E,MAAM,gBAAgB,GAAG,eAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACxC,MAAM,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,GAAG,CAAC,GAAG,GAAG,KAAK,CAAC,YAAY,IAAI,eAAe,CAAC;QAChD,OAAO,GAAG,CAAC;IACf,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;IAEzB,MAAM,eAAe,GAAG,KAAK,CAAC,WAAW,CAAC;IAC1C,MAAM,WAAW,GAAG,eAAK,CAAC,WAAW,CACjC,CAAC,CAA2B,EAAE,aAA4B,EAAE,EAAE;QAC1D,YAAY,CAAC,aAAa,CAAC,CAAC;QAC5B,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAG,aAAa,CAAC,CAAC;IACrC,CAAC,EACD,CAAC,YAAY,EAAE,eAAe,CAAC,CAClC,CAAC;IAEF,MAAM,aAAa,GAAG,KAAK,CAAC,SAAS,CAAC;IACtC,MAAM,SAAS,GAAG,eAAK,CAAC,WAAW,CAC/B,CAAC,CAA2B,EAAE,EAAE;QAC5B,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,aAAa,aAAb,aAAa,uBAAb,aAAa,EAAI,CAAC;IACtB,CAAC,EACD,CAAC,YAAY,EAAE,aAAa,CAAC,CAChC,CAAC;IAEF,MAAM,YAAY,GAAG,eAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACpC,OAAO;YACH,SAAS;YACT,gBAAgB;YAChB,WAAW;YACX,SAAS;YACT,cAAc,EAAE,KAAK,CAAC,cAAc;SACvC,CAAC;IACN,CAAC,EAAE,CAAC,SAAS,EAAE,gBAAgB,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;IAEhF,OAAO,CACH,8BAAC,2BAAiB,CAAC,QAAQ,IAAC,KAAK,EAAE,YAAY,IAC1C,KAAK,CAAC,QAAQ,CACU,CAChC,CAAC;AACN,CAAC,CAAC;AA1CW,QAAA,iBAAiB,qBA0C5B","sourcesContent":["import React from 'react';\n\nimport {DashKitDnDContext} from '../../context';\nimport type {DraggedOverItem, ItemDragProps} from '../../shared';\n\ntype DashKitDnDWrapperProps = {\n dragImageSrc?: string;\n onDropDragOver?: (\n draggedItem: DraggedOverItem,\n sharedItem: DraggedOverItem | null,\n ) => void | boolean;\n onDragStart?: (dragProps: ItemDragProps) => void;\n onDragEnd?: () => void;\n children: React.ReactElement;\n};\n\nconst defaultImageSrc =\n 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=';\n\nexport const DashKitDnDWrapper: React.FC<DashKitDnDWrapperProps> = (props) => {\n const [dragProps, setDragProps] = React.useState<ItemDragProps | null>(null);\n\n const dragImagePreview = React.useMemo(() => {\n const img = new Image();\n img.src = props.dragImageSrc || defaultImageSrc;\n return img;\n }, [props.dragImageSrc]);\n\n const onDragStartProp = props.onDragStart;\n const onDragStart = React.useCallback(\n (_: React.DragEvent<Element>, itemDragProps: ItemDragProps) => {\n setDragProps(itemDragProps);\n onDragStartProp?.(itemDragProps);\n },\n [setDragProps, onDragStartProp],\n );\n\n const onDragEndProp = props.onDragEnd;\n const onDragEnd = React.useCallback(\n (_: React.DragEvent<Element>) => {\n setDragProps(null);\n onDragEndProp?.();\n },\n [setDragProps, onDragEndProp],\n );\n\n const contextValue = React.useMemo(() => {\n return {\n dragProps,\n dragImagePreview,\n onDragStart,\n onDragEnd,\n onDropDragOver: props.onDropDragOver,\n };\n }, [dragProps, dragImagePreview, onDragStart, onDragEnd, props.onDropDragOver]);\n\n return (\n <DashKitDnDContext.Provider value={contextValue}>\n {props.children}\n </DashKitDnDContext.Provider>\n );\n};\n"]}
1
+ {"version":3,"file":"DashKitDnDWrapper.js","sourceRoot":"../../../../src","sources":["components/DashKitDnDWrapper/DashKitDnDWrapper.tsx"],"names":[],"mappings":";;;;AAAA,0DAA0B;AAE1B,oDAAgD;AAczC,MAAM,iBAAiB,GAAqC,CAAC,KAAK,EAAE,EAAE;IACzE,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,eAAK,CAAC,QAAQ,CAAuB,IAAI,CAAC,CAAC;IAE7E,MAAM,gBAAgB,GAAG,eAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACxC,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;YACtB,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,GAAG,CAAC,GAAG,GAAG,KAAK,CAAC,YAAY,CAAC;QAC7B,OAAO,GAAG,CAAC;IACf,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;IAEzB,MAAM,eAAe,GAAG,KAAK,CAAC,WAAW,CAAC;IAC1C,MAAM,WAAW,GAAG,eAAK,CAAC,WAAW,CACjC,CAAC,CAA2B,EAAE,aAA4B,EAAE,EAAE;QAC1D,YAAY,CAAC,aAAa,CAAC,CAAC;QAC5B,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAG,aAAa,CAAC,CAAC;IACrC,CAAC,EACD,CAAC,YAAY,EAAE,eAAe,CAAC,CAClC,CAAC;IAEF,MAAM,aAAa,GAAG,KAAK,CAAC,SAAS,CAAC;IACtC,MAAM,SAAS,GAAG,eAAK,CAAC,WAAW,CAC/B,CAAC,CAA2B,EAAE,EAAE;QAC5B,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,aAAa,aAAb,aAAa,uBAAb,aAAa,EAAI,CAAC;IACtB,CAAC,EACD,CAAC,YAAY,EAAE,aAAa,CAAC,CAChC,CAAC;IAEF,MAAM,YAAY,GAAG,eAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACpC,OAAO;YACH,SAAS;YACT,gBAAgB;YAChB,WAAW;YACX,SAAS;YACT,cAAc,EAAE,KAAK,CAAC,cAAc;SACvC,CAAC;IACN,CAAC,EAAE,CAAC,SAAS,EAAE,gBAAgB,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;IAEhF,OAAO,CACH,8BAAC,2BAAiB,CAAC,QAAQ,IAAC,KAAK,EAAE,YAAY,IAC1C,KAAK,CAAC,QAAQ,CACU,CAChC,CAAC;AACN,CAAC,CAAC;AA9CW,QAAA,iBAAiB,qBA8C5B","sourcesContent":["import React from 'react';\n\nimport {DashKitDnDContext} from '../../context';\nimport type {DraggedOverItem, ItemDragProps} from '../../shared';\n\ntype DashKitDnDWrapperProps = {\n dragImageSrc?: string;\n onDropDragOver?: (\n draggedItem: DraggedOverItem,\n sharedItem: DraggedOverItem | null,\n ) => void | boolean;\n onDragStart?: (dragProps: ItemDragProps) => void;\n onDragEnd?: () => void;\n children: React.ReactElement;\n};\n\nexport const DashKitDnDWrapper: React.FC<DashKitDnDWrapperProps> = (props) => {\n const [dragProps, setDragProps] = React.useState<ItemDragProps | null>(null);\n\n const dragImagePreview = React.useMemo(() => {\n if (!props.dragImageSrc) {\n return null;\n }\n\n const img = new Image();\n img.src = props.dragImageSrc;\n return img;\n }, [props.dragImageSrc]);\n\n const onDragStartProp = props.onDragStart;\n const onDragStart = React.useCallback(\n (_: React.DragEvent<Element>, itemDragProps: ItemDragProps) => {\n setDragProps(itemDragProps);\n onDragStartProp?.(itemDragProps);\n },\n [setDragProps, onDragStartProp],\n );\n\n const onDragEndProp = props.onDragEnd;\n const onDragEnd = React.useCallback(\n (_: React.DragEvent<Element>) => {\n setDragProps(null);\n onDragEndProp?.();\n },\n [setDragProps, onDragEndProp],\n );\n\n const contextValue = React.useMemo(() => {\n return {\n dragProps,\n dragImagePreview,\n onDragStart,\n onDragEnd,\n onDropDragOver: props.onDropDragOver,\n };\n }, [dragProps, dragImagePreview, onDragStart, onDragEnd, props.onDropDragOver]);\n\n return (\n <DashKitDnDContext.Provider value={contextValue}>\n {props.children}\n </DashKitDnDContext.Provider>\n );\n};\n"]}
@@ -45,6 +45,7 @@
45
45
  }
46
46
 
47
47
  .react-grid-item.dropping {
48
+ opacity: 0;
48
49
  user-select: none;
49
50
  pointer-events: none;
50
51
  touch-action: none;
@@ -79,9 +80,10 @@
79
80
  }
80
81
 
81
82
  .react-grid-item.react-grid-placeholder {
82
- --_-dashkit-placeholder-color: var(--dashkit-placeholder-color, #fc0);
83
- --_-dashkit-placeholder-opacity: var(--dashkit-placeholder-opacity, 0.2);
83
+ --_-dashkit-placeholder-color: var(--dashkit-placeholder-color, var(--g-color-base-brand));
84
+ --_-dashkit-placeholder-opacity: var(--dashkit-placeholder-opacity, 0.1);
84
85
  background: var(--_-dashkit-placeholder-color);
86
+ border-radius: var(--dashkit-grid-item-border-radius, 3px);
85
87
  opacity: var(--_-dashkit-placeholder-opacity);
86
88
  transition-duration: 100ms;
87
89
  z-index: 2;
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import type { DraggedOverItem, ItemDragProps } from "../shared/types/index.js";
3
3
  export type DashKitDnDCtxShape = {
4
4
  dragProps: ItemDragProps | null;
5
- dragImagePreview: HTMLImageElement;
5
+ dragImagePreview: HTMLImageElement | null;
6
6
  onDragStart: (e: React.DragEvent<Element>, itemDragProps: ItemDragProps) => void;
7
7
  onDragEnd: (e: React.DragEvent<Element>) => void;
8
8
  onDropDragOver?: (draggedItem: DraggedOverItem, sharedItem: DraggedOverItem | null) => void | boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"DashKitDnDContext.js","sourceRoot":"../../../src","sources":["context/DashKitDnDContext.ts"],"names":[],"mappings":";;;;AAAA,0DAA0B;AAeb,QAAA,iBAAiB,GAAG,eAAK,CAAC,aAAa,CAA4B,SAAS,CAAC,CAAC","sourcesContent":["import React from 'react';\n\nimport type {DraggedOverItem, ItemDragProps} from '../shared/types';\n\nexport type DashKitDnDCtxShape = {\n dragProps: ItemDragProps | null;\n dragImagePreview: HTMLImageElement;\n onDragStart: (e: React.DragEvent<Element>, itemDragProps: ItemDragProps) => void;\n onDragEnd: (e: React.DragEvent<Element>) => void;\n onDropDragOver?: (\n draggedItem: DraggedOverItem,\n sharedItem: DraggedOverItem | null,\n ) => void | boolean;\n};\n\nexport const DashKitDnDContext = React.createContext<DashKitDnDCtxShape | void>(undefined);\n"]}
1
+ {"version":3,"file":"DashKitDnDContext.js","sourceRoot":"../../../src","sources":["context/DashKitDnDContext.ts"],"names":[],"mappings":";;;;AAAA,0DAA0B;AAeb,QAAA,iBAAiB,GAAG,eAAK,CAAC,aAAa,CAA4B,SAAS,CAAC,CAAC","sourcesContent":["import React from 'react';\n\nimport type {DraggedOverItem, ItemDragProps} from '../shared/types';\n\nexport type DashKitDnDCtxShape = {\n dragProps: ItemDragProps | null;\n dragImagePreview: HTMLImageElement | null;\n onDragStart: (e: React.DragEvent<Element>, itemDragProps: ItemDragProps) => void;\n onDragEnd: (e: React.DragEvent<Element>) => void;\n onDropDragOver?: (\n draggedItem: DraggedOverItem,\n sharedItem: DraggedOverItem | null,\n ) => void | boolean;\n};\n\nexport const DashKitDnDContext = React.createContext<DashKitDnDCtxShape | void>(undefined);\n"]}
@@ -0,0 +1,2 @@
1
+ /** @jest-environment jsdom */
2
+ export {};
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ /** @jest-environment jsdom */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const tslib_1 = require("tslib");
5
+ const react_1 = tslib_1.__importDefault(require("react"));
6
+ const react_2 = require("@testing-library/react");
7
+ const ActionPanel_1 = require("../../components/ActionPanel/ActionPanel.js");
8
+ const DashKitDnDWrapper_1 = require("../../components/DashKitDnDWrapper/DashKitDnDWrapper.js");
9
+ const item = { id: 'chart', title: 'Chart', icon: 'icon', dragProps: { type: 'chart' } };
10
+ describe('ActionPanel drag preview', () => {
11
+ it('captures the solid item before disabling the panel source and restores it on drag end', () => {
12
+ jest.useFakeTimers();
13
+ const onDragStart = jest.fn();
14
+ const onDragEnd = jest.fn();
15
+ const setDragImage = jest.fn();
16
+ (0, react_2.render)(react_1.default.createElement(DashKitDnDWrapper_1.DashKitDnDWrapper, { onDragStart: onDragStart, onDragEnd: onDragEnd },
17
+ react_1.default.createElement(ActionPanel_1.ActionPanel, { items: [item] })));
18
+ const source = react_2.screen.getByRole('button', { name: /Chart/ });
19
+ const disabledSourceClassName = 'dashkit-action-panel__item_dragging-source-disabled';
20
+ setDragImage.mockImplementation(() => {
21
+ expect(source.classList.contains('dashkit-action-panel__item_dragging')).toBe(true);
22
+ expect(source.classList.contains(disabledSourceClassName)).toBe(false);
23
+ });
24
+ react_2.fireEvent.dragStart(source, { dataTransfer: { setDragImage } });
25
+ expect(setDragImage).toHaveBeenCalledWith(source, 0, 0);
26
+ expect(onDragStart).toHaveBeenCalledWith(item.dragProps);
27
+ (0, react_2.act)(() => jest.runOnlyPendingTimers());
28
+ expect(source.classList.contains(disabledSourceClassName)).toBe(true);
29
+ react_2.fireEvent.dragEnd(source);
30
+ expect(source.classList.contains('dashkit-action-panel__item_dragging')).toBe(false);
31
+ expect(source.classList.contains(disabledSourceClassName)).toBe(false);
32
+ expect(onDragEnd).toHaveBeenCalledTimes(1);
33
+ jest.useRealTimers();
34
+ });
35
+ it('respects a custom drag image', () => {
36
+ const setDragImage = jest.fn();
37
+ (0, react_2.render)(react_1.default.createElement(DashKitDnDWrapper_1.DashKitDnDWrapper, { dragImageSrc: "data:image/png;base64,AAAA" },
38
+ react_1.default.createElement(ActionPanel_1.ActionPanel, { items: [item] })));
39
+ react_2.fireEvent.dragStart(react_2.screen.getByRole('button', { name: /Chart/ }), {
40
+ dataTransfer: { setDragImage },
41
+ });
42
+ expect(setDragImage.mock.calls[0][0]).toBeInstanceOf(HTMLImageElement);
43
+ });
44
+ });
45
+ //# sourceMappingURL=useDnDItemProps.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDnDItemProps.test.js","sourceRoot":"../../../../src","sources":["hooks/__tests__/useDnDItemProps.test.tsx"],"names":[],"mappings":"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","sourcesContent":["/** @jest-environment jsdom */\n\nimport React from 'react';\n\nimport {act, fireEvent, render, screen} from '@testing-library/react';\n\nimport {ActionPanel} from '../../components/ActionPanel/ActionPanel';\nimport {DashKitDnDWrapper} from '../../components/DashKitDnDWrapper/DashKitDnDWrapper';\n\nconst item = {id: 'chart', title: 'Chart', icon: 'icon', dragProps: {type: 'chart'}};\n\ndescribe('ActionPanel drag preview', () => {\n it('captures the solid item before disabling the panel source and restores it on drag end', () => {\n jest.useFakeTimers();\n const onDragStart = jest.fn();\n const onDragEnd = jest.fn();\n const setDragImage = jest.fn();\n\n render(\n <DashKitDnDWrapper onDragStart={onDragStart} onDragEnd={onDragEnd}>\n <ActionPanel items={[item]} />\n </DashKitDnDWrapper>,\n );\n const source = screen.getByRole('button', {name: /Chart/});\n const disabledSourceClassName = 'dashkit-action-panel__item_dragging-source-disabled';\n\n setDragImage.mockImplementation(() => {\n expect(source.classList.contains('dashkit-action-panel__item_dragging')).toBe(true);\n expect(source.classList.contains(disabledSourceClassName)).toBe(false);\n });\n fireEvent.dragStart(source, {dataTransfer: {setDragImage}});\n expect(setDragImage).toHaveBeenCalledWith(source, 0, 0);\n expect(onDragStart).toHaveBeenCalledWith(item.dragProps);\n act(() => jest.runOnlyPendingTimers());\n expect(source.classList.contains(disabledSourceClassName)).toBe(true);\n\n fireEvent.dragEnd(source);\n expect(source.classList.contains('dashkit-action-panel__item_dragging')).toBe(false);\n expect(source.classList.contains(disabledSourceClassName)).toBe(false);\n expect(onDragEnd).toHaveBeenCalledTimes(1);\n jest.useRealTimers();\n });\n\n it('respects a custom drag image', () => {\n const setDragImage = jest.fn();\n render(\n <DashKitDnDWrapper dragImageSrc=\"data:image/png;base64,AAAA\">\n <ActionPanel items={[item]} />\n </DashKitDnDWrapper>,\n );\n\n fireEvent.dragStart(screen.getByRole('button', {name: /Chart/}), {\n dataTransfer: {setDragImage},\n });\n expect(setDragImage.mock.calls[0][0]).toBeInstanceOf(HTMLImageElement);\n });\n});\n"]}
@@ -9,7 +9,7 @@ const useDnDItemProps = (item) => {
9
9
  const onDragStart = react_1.default.useCallback((e) => {
10
10
  if (dragContext && item.dragProps) {
11
11
  dragContext.onDragStart(e, item.dragProps);
12
- e.dataTransfer.setDragImage(dragContext.dragImagePreview, 0, 0);
12
+ e.dataTransfer.setDragImage(dragContext.dragImagePreview || e.currentTarget, 0, 0);
13
13
  }
14
14
  }, [dragContext, item.dragProps]);
15
15
  const onDragEnd = react_1.default.useCallback((e) => {
@@ -1 +1 @@
1
- {"version":3,"file":"useDnDItemProps.js","sourceRoot":"../../../src","sources":["hooks/useDnDItemProps.ts"],"names":[],"mappings":";;;;AAAA,0DAA0B;AAG1B,iDAA6C;AAStC,MAAM,eAAe,GAAG,CAAC,IAAqB,EAAY,EAAE;IAC/D,MAAM,WAAW,GAAG,eAAK,CAAC,UAAU,CAAC,2BAAiB,CAAC,CAAC;IAExD,MAAM,WAAW,GAAG,eAAK,CAAC,WAAW,CACjC,CAAC,CAAkB,EAAE,EAAE;QACnB,IAAI,WAAW,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAChC,WAAW,CAAC,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;YAC3C,CAAC,CAAC,YAAY,CAAC,YAAY,CAAC,WAAW,CAAC,gBAAgB,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACpE,CAAC;IACL,CAAC,EACD,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,CAChC,CAAC;IAEF,MAAM,SAAS,GAAG,eAAK,CAAC,WAAW,CAC/B,CAAC,CAAC,EAAE,EAAE;QACF,IAAI,WAAW,EAAE,CAAC;YACd,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;IACL,CAAC,EACD,CAAC,WAAW,CAAC,CAChB,CAAC;IAEF,IAAI,WAAW,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QAChC,OAAO;YACH,SAAS,EAAE,IAAI;YACf,YAAY,EAAE,IAAI;YAClB,WAAW;YACX,SAAS;SACZ,CAAC;IACN,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC;AAhCW,QAAA,eAAe,mBAgC1B","sourcesContent":["import React from 'react';\n\nimport {ActionPanelItem} from '../components';\nimport {DashKitDnDContext} from '../context';\n\ntype DndProps = null | {\n draggable: true;\n unselectable: 'on';\n onDragStart: React.DragEventHandler<HTMLDivElement>;\n onDragEnd: React.DragEventHandler<HTMLDivElement>;\n};\n\nexport const useDnDItemProps = (item: ActionPanelItem): DndProps => {\n const dragContext = React.useContext(DashKitDnDContext);\n\n const onDragStart = React.useCallback(\n (e: React.DragEvent) => {\n if (dragContext && item.dragProps) {\n dragContext.onDragStart(e, item.dragProps);\n e.dataTransfer.setDragImage(dragContext.dragImagePreview, 0, 0);\n }\n },\n [dragContext, item.dragProps],\n );\n\n const onDragEnd = React.useCallback<React.DragEventHandler<HTMLDivElement>>(\n (e) => {\n if (dragContext) {\n dragContext.onDragEnd(e);\n }\n },\n [dragContext],\n );\n\n if (dragContext && item.dragProps) {\n return {\n draggable: true,\n unselectable: 'on',\n onDragStart,\n onDragEnd,\n };\n }\n\n return null;\n};\n"]}
1
+ {"version":3,"file":"useDnDItemProps.js","sourceRoot":"../../../src","sources":["hooks/useDnDItemProps.ts"],"names":[],"mappings":";;;;AAAA,0DAA0B;AAG1B,iDAA6C;AAStC,MAAM,eAAe,GAAG,CAAC,IAAqB,EAAY,EAAE;IAC/D,MAAM,WAAW,GAAG,eAAK,CAAC,UAAU,CAAC,2BAAiB,CAAC,CAAC;IAExD,MAAM,WAAW,GAAG,eAAK,CAAC,WAAW,CACjC,CAAC,CAAkB,EAAE,EAAE;QACnB,IAAI,WAAW,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAChC,WAAW,CAAC,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;YAC3C,CAAC,CAAC,YAAY,CAAC,YAAY,CAAC,WAAW,CAAC,gBAAgB,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACvF,CAAC;IACL,CAAC,EACD,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,CAChC,CAAC;IAEF,MAAM,SAAS,GAAG,eAAK,CAAC,WAAW,CAC/B,CAAC,CAAC,EAAE,EAAE;QACF,IAAI,WAAW,EAAE,CAAC;YACd,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;IACL,CAAC,EACD,CAAC,WAAW,CAAC,CAChB,CAAC;IAEF,IAAI,WAAW,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QAChC,OAAO;YACH,SAAS,EAAE,IAAI;YACf,YAAY,EAAE,IAAI;YAClB,WAAW;YACX,SAAS;SACZ,CAAC;IACN,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC;AAhCW,QAAA,eAAe,mBAgC1B","sourcesContent":["import React from 'react';\n\nimport {ActionPanelItem} from '../components';\nimport {DashKitDnDContext} from '../context';\n\ntype DndProps = null | {\n draggable: true;\n unselectable: 'on';\n onDragStart: React.DragEventHandler<HTMLDivElement>;\n onDragEnd: React.DragEventHandler<HTMLDivElement>;\n};\n\nexport const useDnDItemProps = (item: ActionPanelItem): DndProps => {\n const dragContext = React.useContext(DashKitDnDContext);\n\n const onDragStart = React.useCallback(\n (e: React.DragEvent) => {\n if (dragContext && item.dragProps) {\n dragContext.onDragStart(e, item.dragProps);\n e.dataTransfer.setDragImage(dragContext.dragImagePreview || e.currentTarget, 0, 0);\n }\n },\n [dragContext, item.dragProps],\n );\n\n const onDragEnd = React.useCallback<React.DragEventHandler<HTMLDivElement>>(\n (e) => {\n if (dragContext) {\n dragContext.onDragEnd(e);\n }\n },\n [dragContext],\n );\n\n if (dragContext && item.dragProps) {\n return {\n draggable: true,\n unselectable: 'on',\n onDragStart,\n onDragEnd,\n };\n }\n\n return null;\n};\n"]}
@@ -1 +1 @@
1
- {"version":"10.4.4","type":"commonjs","sideEffects":["*.scss","*.css"]}
1
+ {"version":"10.5.0","type":"commonjs","sideEffects":["*.scss","*.css"]}
@@ -427,7 +427,7 @@ interface DashKitDnDWrapperProps {
427
427
  }
428
428
  ```
429
429
 
430
- - **dragImageSrc**: Drag image preview, by default used transparent 1px png base64
430
+ - **dragImageSrc**: Optional custom drag image. By default, the dragged ActionPanel item is shown as the preview.
431
431
  - **onDragStart**: Callback called when element is dragged from ActionPanel
432
432
  - **onDragEnd**: Callback called when element dropped or drag canceled
433
433
 
@@ -490,7 +490,9 @@ const onDrop = (dropProps: ItemDropProps) => {
490
490
  | `--dashkit-action-panel-item-color` | Backgroud color |
491
491
  | `--dashkit-action-panel-item-text-color` | Text color |
492
492
  | `--dashkit-action-panel-item-color-hover` | Hover backgroud color |
493
+ | `--dashkit-action-panel-item-color-dragging` | Drag background color |
493
494
  | `--dashkit-action-panel-item-text-color-hover` | Hover text color |
495
+ | `--dashkit-action-panel-item-text-color-dragging` | Drag text color |
494
496
  | Overlay variables | |
495
497
  | `--dashkit-overlay-border-color` | Border color |
496
498
  | `--dashkit-overlay-color` | Background color |
@@ -1,20 +1,25 @@
1
1
  .dashkit-action-panel {
2
- --_--dashkit-action-panel-color: var(--dashkit-action-panel-color, var(--g-color-base-float));
3
- --_--dashkit-action-panel-border-color: var(
4
- --dashkit-action-panel-border-color,
5
- var(--g-color-base-brand)
2
+ --_--dashkit-action-panel-color: var(
3
+ --dashkit-action-panel-color,
4
+ var(--g-color-base-float-heavy)
6
5
  );
6
+ --_--dashkit-action-panel-border-color: var(--dashkit-action-panel-border-color, transparent);
7
7
  --_--dashkit-action-panel-border-radius: var(
8
8
  --dashkit-action-panel-border-radius,
9
- var(--g-border-radius-xl)
9
+ var(--g-border-radius-2xl, 16px)
10
10
  );
11
11
  background-color: var(--_--dashkit-action-panel-color);
12
+ backdrop-filter: blur(18px);
12
13
  position: fixed;
13
14
  bottom: 20px;
14
15
  display: flex;
16
+ width: max-content;
17
+ max-width: calc(100vw - 40px);
18
+ overflow-x: auto;
15
19
  border-radius: var(--_--dashkit-action-panel-border-radius);
16
- border: 2px solid var(--_--dashkit-action-panel-border-color);
17
- padding: 8px;
20
+ outline: 2px solid var(--_--dashkit-action-panel-border-color);
21
+ outline-offset: -2px;
22
+ padding: 6px;
18
23
  gap: 0;
19
24
  left: 50%;
20
25
  transform: translateX(-50%) translateY(0);
@@ -40,46 +45,70 @@
40
45
  --_--dashkit-action-panel-item-color: var(--dashkit-action-panel-item-color, transparent);
41
46
  --_--dashkit-action-panel-item-text-color: var(
42
47
  --dashkit-action-panel-item-text-color,
43
- var(--g-color-text-primary)
48
+ var(--g-color-text-light-primary)
44
49
  );
45
50
  --_--dashkit-action-panel-item-color-hover: var(
46
51
  --dashkit-action-panel-item-color-hover,
47
- var(--g-color-base-simple-hover)
52
+ var(--g-color-base-light-simple-hover)
53
+ );
54
+ --_--dashkit-action-panel-item-color-dragging: var(
55
+ --dashkit-action-panel-item-color-dragging,
56
+ var(--g-color-base-float-heavy)
48
57
  );
49
58
  --_--dashkit-action-panel-item-text-color-hover: var(
50
59
  --dashkit-action-panel-item-text-color-hover,
51
- var(--g-color-text-primary)
60
+ var(--g-color-text-light-primary)
52
61
  );
53
- height: 68px;
54
- width: 98px;
62
+ min-height: 40px;
63
+ max-width: 200px;
64
+ flex: 0 0 auto;
55
65
  display: flex;
56
- flex-direction: column;
66
+ gap: 4px;
57
67
  justify-content: center;
58
68
  align-items: center;
59
- transition: 300ms color ease-in-out, 300ms background-color ease-in-out;
60
- border-radius: 6px;
61
- padding: 0 12px;
69
+ border-radius: var(--g-border-radius-xl);
70
+ padding: 0 16px;
62
71
  box-sizing: border-box;
63
72
  white-space: nowrap;
64
- overflow: hidden;
65
73
  background-color: var(--_--dashkit-action-panel-item-color);
66
74
  color: var(--_--dashkit-action-panel-item-text-color);
67
- will-change: color, backgroung-color;
68
- }
69
- .dashkit-action-panel__item:hover {
70
75
  cursor: pointer;
76
+ }
77
+ .dashkit-action-panel__item:hover, .dashkit-action-panel__item:focus-visible {
71
78
  background-color: var(--_--dashkit-action-panel-item-color-hover);
72
79
  color: var(--_--dashkit-action-panel-item-text-color-hover);
73
80
  }
81
+ .dashkit-action-panel__item_draggable {
82
+ transform: translate(0, 0);
83
+ cursor: grab;
84
+ }
85
+ .dashkit-action-panel__item_draggable:hover, .dashkit-action-panel__item_draggable:active {
86
+ transform: translateY(-2px);
87
+ box-shadow: 0 3px 5px rgba(0, 0, 0, 0.15);
88
+ }
89
+ .dashkit-action-panel__item_draggable:active {
90
+ cursor: grabbing;
91
+ }
92
+ .dashkit-action-panel__item_dragging, .dashkit-action-panel__item_dragging:hover {
93
+ transform: translate(0, 0);
94
+ background-color: var(--_--dashkit-action-panel-item-color-dragging);
95
+ color: var(--dashkit-action-panel-item-text-color-dragging, var(--g-color-text-light-primary));
96
+ }
97
+ .dashkit-action-panel__item_dragging-source-disabled, .dashkit-action-panel__item_dragging-source-disabled:hover {
98
+ opacity: 0.5;
99
+ box-shadow: none;
100
+ }
74
101
  .dashkit-action-panel__icon {
75
- margin-bottom: 4px;
102
+ display: flex;
103
+ flex: 0 0 auto;
104
+ align-items: center;
105
+ justify-content: center;
76
106
  }
77
107
  .dashkit-action-panel__title {
78
- font-size: 13px;
108
+ min-width: 0;
109
+ font-size: 12px;
79
110
  font-weight: 400;
80
111
  line-height: 16px;
81
- max-width: 100%;
82
- white-space: nowrap;
83
112
  overflow: hidden;
84
113
  text-overflow: ellipsis;
85
114
  }
@@ -7,7 +7,33 @@ import "./ActionPanel.css";
7
7
  const b = cn('dashkit-action-panel');
8
8
  export const ActionPanelItemContainer = ({ item }) => {
9
9
  const dndProps = useDnDItemProps(item);
10
- return (React.createElement("div", Object.assign({ role: "button", className: b('item', { draggable: Boolean(dndProps) }, item.className), onClick: item.onClick, "data-qa": item.qa }, dndProps),
10
+ const draggingClassName = `${b('item')}_dragging`;
11
+ const disabledSourceClassName = `${b('item')}_dragging-source-disabled`;
12
+ const disableSourceTimer = React.useRef(null);
13
+ React.useEffect(() => () => {
14
+ if (disableSourceTimer.current !== null) {
15
+ clearTimeout(disableSourceTimer.current);
16
+ }
17
+ }, []);
18
+ const onDragStart = (event) => {
19
+ const source = event.currentTarget;
20
+ source.classList.add(draggingClassName);
21
+ dndProps === null || dndProps === void 0 ? void 0 : dndProps.onDragStart(event);
22
+ // The native drag image captures the solid item before the panel source is disabled.
23
+ disableSourceTimer.current = setTimeout(() => {
24
+ source.classList.add(disabledSourceClassName);
25
+ disableSourceTimer.current = null;
26
+ }, 0);
27
+ };
28
+ const onDragEnd = (event) => {
29
+ if (disableSourceTimer.current !== null) {
30
+ clearTimeout(disableSourceTimer.current);
31
+ disableSourceTimer.current = null;
32
+ }
33
+ event.currentTarget.classList.remove(draggingClassName, disabledSourceClassName);
34
+ dndProps === null || dndProps === void 0 ? void 0 : dndProps.onDragEnd(event);
35
+ };
36
+ return (React.createElement("div", Object.assign({ role: "button", className: b('item', { draggable: Boolean(dndProps) }, item.className), onClick: item.onClick, "data-qa": item.qa }, dndProps, { onDragStart: dndProps ? onDragStart : undefined, onDragEnd: dndProps ? onDragEnd : undefined }),
11
37
  React.createElement("div", { className: b('icon') }, item.icon),
12
38
  React.createElement("div", { className: b('title'), title: item.title }, item.title)));
13
39
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ActionPanel.js","sourceRoot":"../../../../src","sources":["components/ActionPanel/ActionPanel.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAC,aAAa,EAAC,MAAM,wBAAwB,CAAC;AAErD,OAAO,EAAC,eAAe,EAAC,uCAAoC;AAC5D,OAAO,EAAC,EAAE,EAAC,0BAAuB;AAIlC,2BAA4B;AAE5B,MAAM,CAAC,GAAG,EAAE,CAAC,sBAAsB,CAAC,CAAC;AAErC,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,EAAC,IAAI,EAA0B,EAAE,EAAE;IACxE,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IAEvC,OAAO,CACH,2CACI,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,EAAC,SAAS,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAC,EAAE,IAAI,CAAC,SAAS,CAAC,EACpE,OAAO,EAAE,IAAI,CAAC,OAAO,aACZ,IAAI,CAAC,EAAE,IACZ,QAAQ;QAEZ,6BAAK,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,IAAG,IAAI,CAAC,IAAI,CAAO;QAC5C,6BAAK,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,IACxC,IAAI,CAAC,KAAK,CACT,CACJ,CACT,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAuB,EAAE,EAAE;;IACnD,MAAM,UAAU,GAAG,MAAA,KAAK,CAAC,OAAO,mCAAI,KAAK,CAAC;IAC1C,MAAM,UAAU,GAAG,MAAA,KAAK,CAAC,eAAe,mCAAI,KAAK,CAAC;IAClD,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAwB,IAAI,CAAC,CAAC;IAE1D,MAAM,OAAO,GAAG,CACZ,6BAAK,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,IACjD,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAiB,EAAE,EAAE;YAArB,EAAC,MAAM,OAAU,EAAL,IAAI,cAAhB,UAAiB,CAAD;QAC9B,MAAM,GAAG,GAAG,mBAAmB,IAAI,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,QAAQ,GAAG,oBAAC,wBAAwB,IAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,GAAI,CAAC;QAEpE,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,iCAAK,IAAI,KAAE,GAAG,EAAE,QAAQ,IAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;IAChE,CAAC,CAAC,CACA,CACT,CAAC;IAEF,IAAI,UAAU,EAAE,CAAC;QACb,OAAO,CACH,oBAAC,aAAa,IACV,EAAE,EAAE,CAAC,UAAU,EACf,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,EACnB,OAAO,EAAE,GAAG,EACZ,aAAa,UAEZ,OAAO,CACI,CACnB,CAAC;IACN,CAAC;SAAM,CAAC;QACJ,OAAO,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;IACvC,CAAC;AACL,CAAC,CAAC","sourcesContent":["import React from 'react';\n\nimport {CSSTransition} from 'react-transition-group';\n\nimport {useDnDItemProps} from '../../hooks/useDnDItemProps';\nimport {cn} from '../../utils/cn';\n\nimport {ActionPanelItem, ActionPanelProps} from './types';\n\nimport './ActionPanel.scss';\n\nconst b = cn('dashkit-action-panel');\n\nexport const ActionPanelItemContainer = ({item}: {item: ActionPanelItem}) => {\n const dndProps = useDnDItemProps(item);\n\n return (\n <div\n role=\"button\"\n className={b('item', {draggable: Boolean(dndProps)}, item.className)}\n onClick={item.onClick}\n data-qa={item.qa}\n {...dndProps}\n >\n <div className={b('icon')}>{item.icon}</div>\n <div className={b('title')} title={item.title}>\n {item.title}\n </div>\n </div>\n );\n};\n\nexport const ActionPanel = (props: ActionPanelProps) => {\n const isDisabled = props.disable ?? false;\n const isAnimated = props.toggleAnimation ?? false;\n const nodeRef = React.useRef<HTMLDivElement | null>(null);\n\n const content = (\n <div ref={nodeRef} className={b(null, props.className)}>\n {props.items.map(({wrapTo, ...item}) => {\n const key = `dk-action-panel-${item.id}`;\n const children = <ActionPanelItemContainer key={key} item={item} />;\n\n return wrapTo ? wrapTo({...item, key, children}) : children;\n })}\n </div>\n );\n\n if (isAnimated) {\n return (\n <CSSTransition\n in={!isDisabled}\n nodeRef={nodeRef}\n classNames={b(null)}\n timeout={300}\n unmountOnExit\n >\n {content}\n </CSSTransition>\n );\n } else {\n return isDisabled ? null : content;\n }\n};\n"]}
1
+ {"version":3,"file":"ActionPanel.js","sourceRoot":"../../../../src","sources":["components/ActionPanel/ActionPanel.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\n\nimport {CSSTransition} from 'react-transition-group';\n\nimport {useDnDItemProps} from '../../hooks/useDnDItemProps';\nimport {cn} from '../../utils/cn';\n\nimport {ActionPanelItem, ActionPanelProps} from './types';\n\nimport './ActionPanel.scss';\n\nconst b = cn('dashkit-action-panel');\n\nexport const ActionPanelItemContainer = ({item}: {item: ActionPanelItem}) => {\n const dndProps = useDnDItemProps(item);\n const draggingClassName = `${b('item')}_dragging`;\n const disabledSourceClassName = `${b('item')}_dragging-source-disabled`;\n const disableSourceTimer = React.useRef<ReturnType<typeof setTimeout> | null>(null);\n\n React.useEffect(\n () => () => {\n if (disableSourceTimer.current !== null) {\n clearTimeout(disableSourceTimer.current);\n }\n },\n [],\n );\n\n const onDragStart = (event: React.DragEvent<HTMLDivElement>) => {\n const source = event.currentTarget;\n source.classList.add(draggingClassName);\n dndProps?.onDragStart(event);\n // The native drag image captures the solid item before the panel source is disabled.\n disableSourceTimer.current = setTimeout(() => {\n source.classList.add(disabledSourceClassName);\n disableSourceTimer.current = null;\n }, 0);\n };\n\n const onDragEnd = (event: React.DragEvent<HTMLDivElement>) => {\n if (disableSourceTimer.current !== null) {\n clearTimeout(disableSourceTimer.current);\n disableSourceTimer.current = null;\n }\n event.currentTarget.classList.remove(draggingClassName, disabledSourceClassName);\n dndProps?.onDragEnd(event);\n };\n\n return (\n <div\n role=\"button\"\n className={b('item', {draggable: Boolean(dndProps)}, item.className)}\n onClick={item.onClick}\n data-qa={item.qa}\n {...dndProps}\n onDragStart={dndProps ? onDragStart : undefined}\n onDragEnd={dndProps ? onDragEnd : undefined}\n >\n <div className={b('icon')}>{item.icon}</div>\n <div className={b('title')} title={item.title}>\n {item.title}\n </div>\n </div>\n );\n};\n\nexport const ActionPanel = (props: ActionPanelProps) => {\n const isDisabled = props.disable ?? false;\n const isAnimated = props.toggleAnimation ?? false;\n const nodeRef = React.useRef<HTMLDivElement | null>(null);\n\n const content = (\n <div ref={nodeRef} className={b(null, props.className)}>\n {props.items.map(({wrapTo, ...item}) => {\n const key = `dk-action-panel-${item.id}`;\n const children = <ActionPanelItemContainer key={key} item={item} />;\n\n return wrapTo ? wrapTo({...item, key, children}) : children;\n })}\n </div>\n );\n\n if (isAnimated) {\n return (\n <CSSTransition\n in={!isDisabled}\n nodeRef={nodeRef}\n classNames={b(null)}\n timeout={300}\n unmountOnExit\n >\n {content}\n </CSSTransition>\n );\n } else {\n return isDisabled ? null : content;\n }\n};\n"]}
@@ -1,11 +1,13 @@
1
1
  import React from 'react';
2
2
  import { DashKitDnDContext } from "../../context/index.js";
3
- const defaultImageSrc = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=';
4
3
  export const DashKitDnDWrapper = (props) => {
5
4
  const [dragProps, setDragProps] = React.useState(null);
6
5
  const dragImagePreview = React.useMemo(() => {
6
+ if (!props.dragImageSrc) {
7
+ return null;
8
+ }
7
9
  const img = new Image();
8
- img.src = props.dragImageSrc || defaultImageSrc;
10
+ img.src = props.dragImageSrc;
9
11
  return img;
10
12
  }, [props.dragImageSrc]);
11
13
  const onDragStartProp = props.onDragStart;
@@ -1 +1 @@
1
- {"version":3,"file":"DashKitDnDWrapper.js","sourceRoot":"../../../../src","sources":["components/DashKitDnDWrapper/DashKitDnDWrapper.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAC,iBAAiB,EAAC,+BAAsB;AAchD,MAAM,eAAe,GACjB,oHAAoH,CAAC;AAEzH,MAAM,CAAC,MAAM,iBAAiB,GAAqC,CAAC,KAAK,EAAE,EAAE;IACzE,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAuB,IAAI,CAAC,CAAC;IAE7E,MAAM,gBAAgB,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACxC,MAAM,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,GAAG,CAAC,GAAG,GAAG,KAAK,CAAC,YAAY,IAAI,eAAe,CAAC;QAChD,OAAO,GAAG,CAAC;IACf,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;IAEzB,MAAM,eAAe,GAAG,KAAK,CAAC,WAAW,CAAC;IAC1C,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,CACjC,CAAC,CAA2B,EAAE,aAA4B,EAAE,EAAE;QAC1D,YAAY,CAAC,aAAa,CAAC,CAAC;QAC5B,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAG,aAAa,CAAC,CAAC;IACrC,CAAC,EACD,CAAC,YAAY,EAAE,eAAe,CAAC,CAClC,CAAC;IAEF,MAAM,aAAa,GAAG,KAAK,CAAC,SAAS,CAAC;IACtC,MAAM,SAAS,GAAG,KAAK,CAAC,WAAW,CAC/B,CAAC,CAA2B,EAAE,EAAE;QAC5B,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,aAAa,aAAb,aAAa,uBAAb,aAAa,EAAI,CAAC;IACtB,CAAC,EACD,CAAC,YAAY,EAAE,aAAa,CAAC,CAChC,CAAC;IAEF,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACpC,OAAO;YACH,SAAS;YACT,gBAAgB;YAChB,WAAW;YACX,SAAS;YACT,cAAc,EAAE,KAAK,CAAC,cAAc;SACvC,CAAC;IACN,CAAC,EAAE,CAAC,SAAS,EAAE,gBAAgB,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;IAEhF,OAAO,CACH,oBAAC,iBAAiB,CAAC,QAAQ,IAAC,KAAK,EAAE,YAAY,IAC1C,KAAK,CAAC,QAAQ,CACU,CAChC,CAAC;AACN,CAAC,CAAC","sourcesContent":["import React from 'react';\n\nimport {DashKitDnDContext} from '../../context';\nimport type {DraggedOverItem, ItemDragProps} from '../../shared';\n\ntype DashKitDnDWrapperProps = {\n dragImageSrc?: string;\n onDropDragOver?: (\n draggedItem: DraggedOverItem,\n sharedItem: DraggedOverItem | null,\n ) => void | boolean;\n onDragStart?: (dragProps: ItemDragProps) => void;\n onDragEnd?: () => void;\n children: React.ReactElement;\n};\n\nconst defaultImageSrc =\n 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=';\n\nexport const DashKitDnDWrapper: React.FC<DashKitDnDWrapperProps> = (props) => {\n const [dragProps, setDragProps] = React.useState<ItemDragProps | null>(null);\n\n const dragImagePreview = React.useMemo(() => {\n const img = new Image();\n img.src = props.dragImageSrc || defaultImageSrc;\n return img;\n }, [props.dragImageSrc]);\n\n const onDragStartProp = props.onDragStart;\n const onDragStart = React.useCallback(\n (_: React.DragEvent<Element>, itemDragProps: ItemDragProps) => {\n setDragProps(itemDragProps);\n onDragStartProp?.(itemDragProps);\n },\n [setDragProps, onDragStartProp],\n );\n\n const onDragEndProp = props.onDragEnd;\n const onDragEnd = React.useCallback(\n (_: React.DragEvent<Element>) => {\n setDragProps(null);\n onDragEndProp?.();\n },\n [setDragProps, onDragEndProp],\n );\n\n const contextValue = React.useMemo(() => {\n return {\n dragProps,\n dragImagePreview,\n onDragStart,\n onDragEnd,\n onDropDragOver: props.onDropDragOver,\n };\n }, [dragProps, dragImagePreview, onDragStart, onDragEnd, props.onDropDragOver]);\n\n return (\n <DashKitDnDContext.Provider value={contextValue}>\n {props.children}\n </DashKitDnDContext.Provider>\n );\n};\n"]}
1
+ {"version":3,"file":"DashKitDnDWrapper.js","sourceRoot":"../../../../src","sources":["components/DashKitDnDWrapper/DashKitDnDWrapper.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAC,iBAAiB,EAAC,+BAAsB;AAchD,MAAM,CAAC,MAAM,iBAAiB,GAAqC,CAAC,KAAK,EAAE,EAAE;IACzE,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAuB,IAAI,CAAC,CAAC;IAE7E,MAAM,gBAAgB,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACxC,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;YACtB,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,GAAG,CAAC,GAAG,GAAG,KAAK,CAAC,YAAY,CAAC;QAC7B,OAAO,GAAG,CAAC;IACf,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;IAEzB,MAAM,eAAe,GAAG,KAAK,CAAC,WAAW,CAAC;IAC1C,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,CACjC,CAAC,CAA2B,EAAE,aAA4B,EAAE,EAAE;QAC1D,YAAY,CAAC,aAAa,CAAC,CAAC;QAC5B,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAG,aAAa,CAAC,CAAC;IACrC,CAAC,EACD,CAAC,YAAY,EAAE,eAAe,CAAC,CAClC,CAAC;IAEF,MAAM,aAAa,GAAG,KAAK,CAAC,SAAS,CAAC;IACtC,MAAM,SAAS,GAAG,KAAK,CAAC,WAAW,CAC/B,CAAC,CAA2B,EAAE,EAAE;QAC5B,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,aAAa,aAAb,aAAa,uBAAb,aAAa,EAAI,CAAC;IACtB,CAAC,EACD,CAAC,YAAY,EAAE,aAAa,CAAC,CAChC,CAAC;IAEF,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACpC,OAAO;YACH,SAAS;YACT,gBAAgB;YAChB,WAAW;YACX,SAAS;YACT,cAAc,EAAE,KAAK,CAAC,cAAc;SACvC,CAAC;IACN,CAAC,EAAE,CAAC,SAAS,EAAE,gBAAgB,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;IAEhF,OAAO,CACH,oBAAC,iBAAiB,CAAC,QAAQ,IAAC,KAAK,EAAE,YAAY,IAC1C,KAAK,CAAC,QAAQ,CACU,CAChC,CAAC;AACN,CAAC,CAAC","sourcesContent":["import React from 'react';\n\nimport {DashKitDnDContext} from '../../context';\nimport type {DraggedOverItem, ItemDragProps} from '../../shared';\n\ntype DashKitDnDWrapperProps = {\n dragImageSrc?: string;\n onDropDragOver?: (\n draggedItem: DraggedOverItem,\n sharedItem: DraggedOverItem | null,\n ) => void | boolean;\n onDragStart?: (dragProps: ItemDragProps) => void;\n onDragEnd?: () => void;\n children: React.ReactElement;\n};\n\nexport const DashKitDnDWrapper: React.FC<DashKitDnDWrapperProps> = (props) => {\n const [dragProps, setDragProps] = React.useState<ItemDragProps | null>(null);\n\n const dragImagePreview = React.useMemo(() => {\n if (!props.dragImageSrc) {\n return null;\n }\n\n const img = new Image();\n img.src = props.dragImageSrc;\n return img;\n }, [props.dragImageSrc]);\n\n const onDragStartProp = props.onDragStart;\n const onDragStart = React.useCallback(\n (_: React.DragEvent<Element>, itemDragProps: ItemDragProps) => {\n setDragProps(itemDragProps);\n onDragStartProp?.(itemDragProps);\n },\n [setDragProps, onDragStartProp],\n );\n\n const onDragEndProp = props.onDragEnd;\n const onDragEnd = React.useCallback(\n (_: React.DragEvent<Element>) => {\n setDragProps(null);\n onDragEndProp?.();\n },\n [setDragProps, onDragEndProp],\n );\n\n const contextValue = React.useMemo(() => {\n return {\n dragProps,\n dragImagePreview,\n onDragStart,\n onDragEnd,\n onDropDragOver: props.onDropDragOver,\n };\n }, [dragProps, dragImagePreview, onDragStart, onDragEnd, props.onDropDragOver]);\n\n return (\n <DashKitDnDContext.Provider value={contextValue}>\n {props.children}\n </DashKitDnDContext.Provider>\n );\n};\n"]}
@@ -45,6 +45,7 @@
45
45
  }
46
46
 
47
47
  .react-grid-item.dropping {
48
+ opacity: 0;
48
49
  user-select: none;
49
50
  pointer-events: none;
50
51
  touch-action: none;
@@ -79,9 +80,10 @@
79
80
  }
80
81
 
81
82
  .react-grid-item.react-grid-placeholder {
82
- --_-dashkit-placeholder-color: var(--dashkit-placeholder-color, #fc0);
83
- --_-dashkit-placeholder-opacity: var(--dashkit-placeholder-opacity, 0.2);
83
+ --_-dashkit-placeholder-color: var(--dashkit-placeholder-color, var(--g-color-base-brand));
84
+ --_-dashkit-placeholder-opacity: var(--dashkit-placeholder-opacity, 0.1);
84
85
  background: var(--_-dashkit-placeholder-color);
86
+ border-radius: var(--dashkit-grid-item-border-radius, 3px);
85
87
  opacity: var(--_-dashkit-placeholder-opacity);
86
88
  transition-duration: 100ms;
87
89
  z-index: 2;
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import type { DraggedOverItem, ItemDragProps } from "../shared/types/index.js";
3
3
  export type DashKitDnDCtxShape = {
4
4
  dragProps: ItemDragProps | null;
5
- dragImagePreview: HTMLImageElement;
5
+ dragImagePreview: HTMLImageElement | null;
6
6
  onDragStart: (e: React.DragEvent<Element>, itemDragProps: ItemDragProps) => void;
7
7
  onDragEnd: (e: React.DragEvent<Element>) => void;
8
8
  onDropDragOver?: (draggedItem: DraggedOverItem, sharedItem: DraggedOverItem | null) => void | boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"DashKitDnDContext.js","sourceRoot":"../../../src","sources":["context/DashKitDnDContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAe1B,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC,aAAa,CAA4B,SAAS,CAAC,CAAC","sourcesContent":["import React from 'react';\n\nimport type {DraggedOverItem, ItemDragProps} from '../shared/types';\n\nexport type DashKitDnDCtxShape = {\n dragProps: ItemDragProps | null;\n dragImagePreview: HTMLImageElement;\n onDragStart: (e: React.DragEvent<Element>, itemDragProps: ItemDragProps) => void;\n onDragEnd: (e: React.DragEvent<Element>) => void;\n onDropDragOver?: (\n draggedItem: DraggedOverItem,\n sharedItem: DraggedOverItem | null,\n ) => void | boolean;\n};\n\nexport const DashKitDnDContext = React.createContext<DashKitDnDCtxShape | void>(undefined);\n"]}
1
+ {"version":3,"file":"DashKitDnDContext.js","sourceRoot":"../../../src","sources":["context/DashKitDnDContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAe1B,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC,aAAa,CAA4B,SAAS,CAAC,CAAC","sourcesContent":["import React from 'react';\n\nimport type {DraggedOverItem, ItemDragProps} from '../shared/types';\n\nexport type DashKitDnDCtxShape = {\n dragProps: ItemDragProps | null;\n dragImagePreview: HTMLImageElement | null;\n onDragStart: (e: React.DragEvent<Element>, itemDragProps: ItemDragProps) => void;\n onDragEnd: (e: React.DragEvent<Element>) => void;\n onDropDragOver?: (\n draggedItem: DraggedOverItem,\n sharedItem: DraggedOverItem | null,\n ) => void | boolean;\n};\n\nexport const DashKitDnDContext = React.createContext<DashKitDnDCtxShape | void>(undefined);\n"]}
@@ -0,0 +1,2 @@
1
+ /** @jest-environment jsdom */
2
+ export {};
@@ -0,0 +1,42 @@
1
+ /** @jest-environment jsdom */
2
+ import React from 'react';
3
+ import { act, fireEvent, render, screen } from '@testing-library/react';
4
+ import { ActionPanel } from "../../components/ActionPanel/ActionPanel.js";
5
+ import { DashKitDnDWrapper } from "../../components/DashKitDnDWrapper/DashKitDnDWrapper.js";
6
+ const item = { id: 'chart', title: 'Chart', icon: 'icon', dragProps: { type: 'chart' } };
7
+ describe('ActionPanel drag preview', () => {
8
+ it('captures the solid item before disabling the panel source and restores it on drag end', () => {
9
+ jest.useFakeTimers();
10
+ const onDragStart = jest.fn();
11
+ const onDragEnd = jest.fn();
12
+ const setDragImage = jest.fn();
13
+ render(React.createElement(DashKitDnDWrapper, { onDragStart: onDragStart, onDragEnd: onDragEnd },
14
+ React.createElement(ActionPanel, { items: [item] })));
15
+ const source = screen.getByRole('button', { name: /Chart/ });
16
+ const disabledSourceClassName = 'dashkit-action-panel__item_dragging-source-disabled';
17
+ setDragImage.mockImplementation(() => {
18
+ expect(source.classList.contains('dashkit-action-panel__item_dragging')).toBe(true);
19
+ expect(source.classList.contains(disabledSourceClassName)).toBe(false);
20
+ });
21
+ fireEvent.dragStart(source, { dataTransfer: { setDragImage } });
22
+ expect(setDragImage).toHaveBeenCalledWith(source, 0, 0);
23
+ expect(onDragStart).toHaveBeenCalledWith(item.dragProps);
24
+ act(() => jest.runOnlyPendingTimers());
25
+ expect(source.classList.contains(disabledSourceClassName)).toBe(true);
26
+ fireEvent.dragEnd(source);
27
+ expect(source.classList.contains('dashkit-action-panel__item_dragging')).toBe(false);
28
+ expect(source.classList.contains(disabledSourceClassName)).toBe(false);
29
+ expect(onDragEnd).toHaveBeenCalledTimes(1);
30
+ jest.useRealTimers();
31
+ });
32
+ it('respects a custom drag image', () => {
33
+ const setDragImage = jest.fn();
34
+ render(React.createElement(DashKitDnDWrapper, { dragImageSrc: "data:image/png;base64,AAAA" },
35
+ React.createElement(ActionPanel, { items: [item] })));
36
+ fireEvent.dragStart(screen.getByRole('button', { name: /Chart/ }), {
37
+ dataTransfer: { setDragImage },
38
+ });
39
+ expect(setDragImage.mock.calls[0][0]).toBeInstanceOf(HTMLImageElement);
40
+ });
41
+ });
42
+ //# sourceMappingURL=useDnDItemProps.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDnDItemProps.test.js","sourceRoot":"../../../../src","sources":["hooks/__tests__/useDnDItemProps.test.tsx"],"names":[],"mappings":"AAAA,8BAA8B;AAE9B,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAC,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAC,MAAM,wBAAwB,CAAC;AAEtE,OAAO,EAAC,WAAW,EAAC,oDAAiD;AACrE,OAAO,EAAC,iBAAiB,EAAC,gEAA6D;AAEvF,MAAM,IAAI,GAAG,EAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,EAAC,IAAI,EAAE,OAAO,EAAC,EAAC,CAAC;AAErF,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACtC,EAAE,CAAC,uFAAuF,EAAE,GAAG,EAAE;QAC7F,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QAC9B,MAAM,SAAS,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QAC5B,MAAM,YAAY,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QAE/B,MAAM,CACF,oBAAC,iBAAiB,IAAC,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS;YAC7D,oBAAC,WAAW,IAAC,KAAK,EAAE,CAAC,IAAI,CAAC,GAAI,CACd,CACvB,CAAC;QACF,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAC,IAAI,EAAE,OAAO,EAAC,CAAC,CAAC;QAC3D,MAAM,uBAAuB,GAAG,qDAAqD,CAAC;QAEtF,YAAY,CAAC,kBAAkB,CAAC,GAAG,EAAE;YACjC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,qCAAqC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpF,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3E,CAAC,CAAC,CAAC;QACH,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,EAAC,YAAY,EAAE,EAAC,YAAY,EAAC,EAAC,CAAC,CAAC;QAC5D,MAAM,CAAC,YAAY,CAAC,CAAC,oBAAoB,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,WAAW,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzD,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC,CAAC;QACvC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEtE,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC1B,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,qCAAqC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrF,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,CAAC,SAAS,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAC3C,IAAI,CAAC,aAAa,EAAE,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACpC,MAAM,YAAY,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QAC/B,MAAM,CACF,oBAAC,iBAAiB,IAAC,YAAY,EAAC,4BAA4B;YACxD,oBAAC,WAAW,IAAC,KAAK,EAAE,CAAC,IAAI,CAAC,GAAI,CACd,CACvB,CAAC;QAEF,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAC,IAAI,EAAE,OAAO,EAAC,CAAC,EAAE;YAC7D,YAAY,EAAE,EAAC,YAAY,EAAC;SAC/B,CAAC,CAAC;QACH,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC","sourcesContent":["/** @jest-environment jsdom */\n\nimport React from 'react';\n\nimport {act, fireEvent, render, screen} from '@testing-library/react';\n\nimport {ActionPanel} from '../../components/ActionPanel/ActionPanel';\nimport {DashKitDnDWrapper} from '../../components/DashKitDnDWrapper/DashKitDnDWrapper';\n\nconst item = {id: 'chart', title: 'Chart', icon: 'icon', dragProps: {type: 'chart'}};\n\ndescribe('ActionPanel drag preview', () => {\n it('captures the solid item before disabling the panel source and restores it on drag end', () => {\n jest.useFakeTimers();\n const onDragStart = jest.fn();\n const onDragEnd = jest.fn();\n const setDragImage = jest.fn();\n\n render(\n <DashKitDnDWrapper onDragStart={onDragStart} onDragEnd={onDragEnd}>\n <ActionPanel items={[item]} />\n </DashKitDnDWrapper>,\n );\n const source = screen.getByRole('button', {name: /Chart/});\n const disabledSourceClassName = 'dashkit-action-panel__item_dragging-source-disabled';\n\n setDragImage.mockImplementation(() => {\n expect(source.classList.contains('dashkit-action-panel__item_dragging')).toBe(true);\n expect(source.classList.contains(disabledSourceClassName)).toBe(false);\n });\n fireEvent.dragStart(source, {dataTransfer: {setDragImage}});\n expect(setDragImage).toHaveBeenCalledWith(source, 0, 0);\n expect(onDragStart).toHaveBeenCalledWith(item.dragProps);\n act(() => jest.runOnlyPendingTimers());\n expect(source.classList.contains(disabledSourceClassName)).toBe(true);\n\n fireEvent.dragEnd(source);\n expect(source.classList.contains('dashkit-action-panel__item_dragging')).toBe(false);\n expect(source.classList.contains(disabledSourceClassName)).toBe(false);\n expect(onDragEnd).toHaveBeenCalledTimes(1);\n jest.useRealTimers();\n });\n\n it('respects a custom drag image', () => {\n const setDragImage = jest.fn();\n render(\n <DashKitDnDWrapper dragImageSrc=\"data:image/png;base64,AAAA\">\n <ActionPanel items={[item]} />\n </DashKitDnDWrapper>,\n );\n\n fireEvent.dragStart(screen.getByRole('button', {name: /Chart/}), {\n dataTransfer: {setDragImage},\n });\n expect(setDragImage.mock.calls[0][0]).toBeInstanceOf(HTMLImageElement);\n });\n});\n"]}
@@ -5,7 +5,7 @@ export const useDnDItemProps = (item) => {
5
5
  const onDragStart = React.useCallback((e) => {
6
6
  if (dragContext && item.dragProps) {
7
7
  dragContext.onDragStart(e, item.dragProps);
8
- e.dataTransfer.setDragImage(dragContext.dragImagePreview, 0, 0);
8
+ e.dataTransfer.setDragImage(dragContext.dragImagePreview || e.currentTarget, 0, 0);
9
9
  }
10
10
  }, [dragContext, item.dragProps]);
11
11
  const onDragEnd = React.useCallback((e) => {
@@ -1 +1 @@
1
- {"version":3,"file":"useDnDItemProps.js","sourceRoot":"../../../src","sources":["hooks/useDnDItemProps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAC,iBAAiB,EAAC,4BAAmB;AAS7C,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAqB,EAAY,EAAE;IAC/D,MAAM,WAAW,GAAG,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;IAExD,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,CACjC,CAAC,CAAkB,EAAE,EAAE;QACnB,IAAI,WAAW,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAChC,WAAW,CAAC,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;YAC3C,CAAC,CAAC,YAAY,CAAC,YAAY,CAAC,WAAW,CAAC,gBAAgB,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACpE,CAAC;IACL,CAAC,EACD,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,CAChC,CAAC;IAEF,MAAM,SAAS,GAAG,KAAK,CAAC,WAAW,CAC/B,CAAC,CAAC,EAAE,EAAE;QACF,IAAI,WAAW,EAAE,CAAC;YACd,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;IACL,CAAC,EACD,CAAC,WAAW,CAAC,CAChB,CAAC;IAEF,IAAI,WAAW,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QAChC,OAAO;YACH,SAAS,EAAE,IAAI;YACf,YAAY,EAAE,IAAI;YAClB,WAAW;YACX,SAAS;SACZ,CAAC;IACN,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC","sourcesContent":["import React from 'react';\n\nimport {ActionPanelItem} from '../components';\nimport {DashKitDnDContext} from '../context';\n\ntype DndProps = null | {\n draggable: true;\n unselectable: 'on';\n onDragStart: React.DragEventHandler<HTMLDivElement>;\n onDragEnd: React.DragEventHandler<HTMLDivElement>;\n};\n\nexport const useDnDItemProps = (item: ActionPanelItem): DndProps => {\n const dragContext = React.useContext(DashKitDnDContext);\n\n const onDragStart = React.useCallback(\n (e: React.DragEvent) => {\n if (dragContext && item.dragProps) {\n dragContext.onDragStart(e, item.dragProps);\n e.dataTransfer.setDragImage(dragContext.dragImagePreview, 0, 0);\n }\n },\n [dragContext, item.dragProps],\n );\n\n const onDragEnd = React.useCallback<React.DragEventHandler<HTMLDivElement>>(\n (e) => {\n if (dragContext) {\n dragContext.onDragEnd(e);\n }\n },\n [dragContext],\n );\n\n if (dragContext && item.dragProps) {\n return {\n draggable: true,\n unselectable: 'on',\n onDragStart,\n onDragEnd,\n };\n }\n\n return null;\n};\n"]}
1
+ {"version":3,"file":"useDnDItemProps.js","sourceRoot":"../../../src","sources":["hooks/useDnDItemProps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAC,iBAAiB,EAAC,4BAAmB;AAS7C,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAqB,EAAY,EAAE;IAC/D,MAAM,WAAW,GAAG,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;IAExD,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,CACjC,CAAC,CAAkB,EAAE,EAAE;QACnB,IAAI,WAAW,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAChC,WAAW,CAAC,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;YAC3C,CAAC,CAAC,YAAY,CAAC,YAAY,CAAC,WAAW,CAAC,gBAAgB,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACvF,CAAC;IACL,CAAC,EACD,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,CAChC,CAAC;IAEF,MAAM,SAAS,GAAG,KAAK,CAAC,WAAW,CAC/B,CAAC,CAAC,EAAE,EAAE;QACF,IAAI,WAAW,EAAE,CAAC;YACd,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;IACL,CAAC,EACD,CAAC,WAAW,CAAC,CAChB,CAAC;IAEF,IAAI,WAAW,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QAChC,OAAO;YACH,SAAS,EAAE,IAAI;YACf,YAAY,EAAE,IAAI;YAClB,WAAW;YACX,SAAS;SACZ,CAAC;IACN,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC","sourcesContent":["import React from 'react';\n\nimport {ActionPanelItem} from '../components';\nimport {DashKitDnDContext} from '../context';\n\ntype DndProps = null | {\n draggable: true;\n unselectable: 'on';\n onDragStart: React.DragEventHandler<HTMLDivElement>;\n onDragEnd: React.DragEventHandler<HTMLDivElement>;\n};\n\nexport const useDnDItemProps = (item: ActionPanelItem): DndProps => {\n const dragContext = React.useContext(DashKitDnDContext);\n\n const onDragStart = React.useCallback(\n (e: React.DragEvent) => {\n if (dragContext && item.dragProps) {\n dragContext.onDragStart(e, item.dragProps);\n e.dataTransfer.setDragImage(dragContext.dragImagePreview || e.currentTarget, 0, 0);\n }\n },\n [dragContext, item.dragProps],\n );\n\n const onDragEnd = React.useCallback<React.DragEventHandler<HTMLDivElement>>(\n (e) => {\n if (dragContext) {\n dragContext.onDragEnd(e);\n }\n },\n [dragContext],\n );\n\n if (dragContext && item.dragProps) {\n return {\n draggable: true,\n unselectable: 'on',\n onDragStart,\n onDragEnd,\n };\n }\n\n return null;\n};\n"]}
@@ -1 +1 @@
1
- {"version":"10.4.4","type":"module","sideEffects":["*.scss","*.css"]}
1
+ {"version":"10.5.0","type":"module","sideEffects":["*.scss","*.css"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/dashkit",
3
- "version": "10.4.4",
3
+ "version": "10.5.0",
4
4
  "description": "Library for rendering dashboard grid layout",
5
5
  "license": "MIT",
6
6
  "repository": {