@carbon/utilities 0.18.0-rc.0 → 0.18.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/es/makeDraggable/index.d.ts +2 -1
- package/es/makeDraggable/index.js +81 -15
- package/lib/makeDraggable/index.js +81 -15
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/makeDraggable/makeDraggable.d.ts
|
|
2
2
|
/**
|
|
3
|
-
* Copyright IBM Corp. 2025,
|
|
3
|
+
* Copyright IBM Corp. 2025, 2026
|
|
4
4
|
*
|
|
5
5
|
* This source code is licensed under the Apache-2.0 license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
@@ -41,6 +41,7 @@ declare const makeDraggable: ({
|
|
|
41
41
|
shiftDragStep
|
|
42
42
|
}: DraggableProps) => {
|
|
43
43
|
cleanup: () => void;
|
|
44
|
+
init: () => void;
|
|
44
45
|
};
|
|
45
46
|
//#endregion
|
|
46
47
|
export { makeDraggable };
|
|
@@ -9,8 +9,49 @@ const makeDraggable = ({ el, dragHandle, focusableDragHandle, dragStep, shiftDra
|
|
|
9
9
|
el.style.cursor = "default";
|
|
10
10
|
} else el.style.cursor = "move";
|
|
11
11
|
let isDragging = false;
|
|
12
|
-
let
|
|
13
|
-
let
|
|
12
|
+
let currentX = 0;
|
|
13
|
+
let currentY = 0;
|
|
14
|
+
let initialMouseX = 0;
|
|
15
|
+
let initialMouseY = 0;
|
|
16
|
+
let baseMatrix = null;
|
|
17
|
+
/**
|
|
18
|
+
* Syncs position and extracts base matrix from computed style.
|
|
19
|
+
* Reads from getComputedStyle() to include all transform sources (inline, classes, etc.).
|
|
20
|
+
*/
|
|
21
|
+
const syncTransformState = () => {
|
|
22
|
+
const transformString = window.getComputedStyle(el).transform;
|
|
23
|
+
if (!transformString || transformString === "none") {
|
|
24
|
+
currentX = 0;
|
|
25
|
+
currentY = 0;
|
|
26
|
+
baseMatrix = null;
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const matrix = new DOMMatrix(transformString);
|
|
30
|
+
currentX = matrix.m41;
|
|
31
|
+
currentY = matrix.m42;
|
|
32
|
+
if (matrix.a === 1 && matrix.b === 0 && matrix.c === 0 && matrix.d === 1 && matrix.e === 0 && matrix.f === 0) baseMatrix = null;
|
|
33
|
+
else baseMatrix = new DOMMatrix([
|
|
34
|
+
matrix.a,
|
|
35
|
+
matrix.b,
|
|
36
|
+
matrix.c,
|
|
37
|
+
matrix.d,
|
|
38
|
+
0,
|
|
39
|
+
0
|
|
40
|
+
]);
|
|
41
|
+
};
|
|
42
|
+
syncTransformState();
|
|
43
|
+
/**
|
|
44
|
+
* Applies transform by combining translation with base matrix using matrix multiplication.
|
|
45
|
+
*/
|
|
46
|
+
const applyTransform = (x, y) => {
|
|
47
|
+
if (baseMatrix) {
|
|
48
|
+
const translationMatrix = new DOMMatrix();
|
|
49
|
+
translationMatrix.m41 = x;
|
|
50
|
+
translationMatrix.m42 = y;
|
|
51
|
+
const combined = translationMatrix.multiply(baseMatrix);
|
|
52
|
+
el.style.transform = combined.toString();
|
|
53
|
+
} else el.style.transform = `translate(${x}px, ${y}px)`;
|
|
54
|
+
};
|
|
14
55
|
const dispatch = (type, detail) => {
|
|
15
56
|
const eventInit = {
|
|
16
57
|
detail,
|
|
@@ -19,9 +60,13 @@ const makeDraggable = ({ el, dragHandle, focusableDragHandle, dragStep, shiftDra
|
|
|
19
60
|
el.dispatchEvent(new CustomEvent(type, eventInit));
|
|
20
61
|
};
|
|
21
62
|
const onKeyDown = (e) => {
|
|
22
|
-
if (e.key === "Enter")
|
|
23
|
-
|
|
24
|
-
|
|
63
|
+
if (e.key === "Enter") {
|
|
64
|
+
isDragging = !isDragging;
|
|
65
|
+
if (isDragging) {
|
|
66
|
+
syncTransformState();
|
|
67
|
+
dispatch("dragstart", { keyboard: true });
|
|
68
|
+
} else dispatch("dragend", { keyboard: true });
|
|
69
|
+
}
|
|
25
70
|
if (!isDragging) return;
|
|
26
71
|
const distance = e.shiftKey ? shiftDragStep ?? 32 : dragStep ?? 8;
|
|
27
72
|
switch (e.key) {
|
|
@@ -30,16 +75,20 @@ const makeDraggable = ({ el, dragHandle, focusableDragHandle, dragStep, shiftDra
|
|
|
30
75
|
e.preventDefault();
|
|
31
76
|
break;
|
|
32
77
|
case "ArrowLeft":
|
|
33
|
-
|
|
78
|
+
currentX -= distance;
|
|
79
|
+
applyTransform(currentX, currentY);
|
|
34
80
|
break;
|
|
35
81
|
case "ArrowRight":
|
|
36
|
-
|
|
82
|
+
currentX += distance;
|
|
83
|
+
applyTransform(currentX, currentY);
|
|
37
84
|
break;
|
|
38
85
|
case "ArrowUp":
|
|
39
|
-
|
|
86
|
+
currentY -= distance;
|
|
87
|
+
applyTransform(currentX, currentY);
|
|
40
88
|
break;
|
|
41
89
|
case "ArrowDown":
|
|
42
|
-
|
|
90
|
+
currentY += distance;
|
|
91
|
+
applyTransform(currentX, currentY);
|
|
43
92
|
break;
|
|
44
93
|
}
|
|
45
94
|
};
|
|
@@ -47,8 +96,9 @@ const makeDraggable = ({ el, dragHandle, focusableDragHandle, dragStep, shiftDra
|
|
|
47
96
|
const target = e.target;
|
|
48
97
|
if (!(target instanceof Node)) return;
|
|
49
98
|
if (!(dragHandle ? dragHandle.contains(target) : el.contains(target))) return;
|
|
50
|
-
|
|
51
|
-
|
|
99
|
+
syncTransformState();
|
|
100
|
+
initialMouseX = e.clientX;
|
|
101
|
+
initialMouseY = e.clientY;
|
|
52
102
|
isDragging = true;
|
|
53
103
|
dispatch("dragstart", { mouse: true });
|
|
54
104
|
document.addEventListener("mousemove", onMouseMove);
|
|
@@ -56,11 +106,16 @@ const makeDraggable = ({ el, dragHandle, focusableDragHandle, dragStep, shiftDra
|
|
|
56
106
|
};
|
|
57
107
|
const onMouseMove = (e) => {
|
|
58
108
|
if (!isDragging) return;
|
|
59
|
-
|
|
60
|
-
|
|
109
|
+
const dx = e.clientX - initialMouseX;
|
|
110
|
+
const dy = e.clientY - initialMouseY;
|
|
111
|
+
applyTransform(currentX + dx, currentY + dy);
|
|
61
112
|
};
|
|
62
|
-
const onMouseUp = () => {
|
|
113
|
+
const onMouseUp = (e) => {
|
|
63
114
|
if (!isDragging) return;
|
|
115
|
+
const dx = e.clientX - initialMouseX;
|
|
116
|
+
const dy = e.clientY - initialMouseY;
|
|
117
|
+
currentX += dx;
|
|
118
|
+
currentY += dy;
|
|
64
119
|
isDragging = false;
|
|
65
120
|
dispatch("dragend", { mouse: true });
|
|
66
121
|
document.removeEventListener("mousemove", onMouseMove);
|
|
@@ -75,7 +130,18 @@ const makeDraggable = ({ el, dragHandle, focusableDragHandle, dragStep, shiftDra
|
|
|
75
130
|
document.removeEventListener("mousemove", onMouseMove);
|
|
76
131
|
document.removeEventListener("mouseup", onMouseUp);
|
|
77
132
|
};
|
|
78
|
-
|
|
133
|
+
/**
|
|
134
|
+
* Re-initialize the draggable position from the element's current computed transform.
|
|
135
|
+
* Call this if the element has been repositioned externally (e.g., via CSS animation,
|
|
136
|
+
* class changes, or other scripts) to prevent position jumps on the next drag.
|
|
137
|
+
*/
|
|
138
|
+
const init = () => {
|
|
139
|
+
syncTransformState();
|
|
140
|
+
};
|
|
141
|
+
return {
|
|
142
|
+
cleanup: draggableCleanup,
|
|
143
|
+
init
|
|
144
|
+
};
|
|
79
145
|
};
|
|
80
146
|
|
|
81
147
|
//#endregion
|
|
@@ -11,8 +11,49 @@ const makeDraggable = ({ el, dragHandle, focusableDragHandle, dragStep, shiftDra
|
|
|
11
11
|
el.style.cursor = "default";
|
|
12
12
|
} else el.style.cursor = "move";
|
|
13
13
|
let isDragging = false;
|
|
14
|
-
let
|
|
15
|
-
let
|
|
14
|
+
let currentX = 0;
|
|
15
|
+
let currentY = 0;
|
|
16
|
+
let initialMouseX = 0;
|
|
17
|
+
let initialMouseY = 0;
|
|
18
|
+
let baseMatrix = null;
|
|
19
|
+
/**
|
|
20
|
+
* Syncs position and extracts base matrix from computed style.
|
|
21
|
+
* Reads from getComputedStyle() to include all transform sources (inline, classes, etc.).
|
|
22
|
+
*/
|
|
23
|
+
const syncTransformState = () => {
|
|
24
|
+
const transformString = window.getComputedStyle(el).transform;
|
|
25
|
+
if (!transformString || transformString === "none") {
|
|
26
|
+
currentX = 0;
|
|
27
|
+
currentY = 0;
|
|
28
|
+
baseMatrix = null;
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const matrix = new DOMMatrix(transformString);
|
|
32
|
+
currentX = matrix.m41;
|
|
33
|
+
currentY = matrix.m42;
|
|
34
|
+
if (matrix.a === 1 && matrix.b === 0 && matrix.c === 0 && matrix.d === 1 && matrix.e === 0 && matrix.f === 0) baseMatrix = null;
|
|
35
|
+
else baseMatrix = new DOMMatrix([
|
|
36
|
+
matrix.a,
|
|
37
|
+
matrix.b,
|
|
38
|
+
matrix.c,
|
|
39
|
+
matrix.d,
|
|
40
|
+
0,
|
|
41
|
+
0
|
|
42
|
+
]);
|
|
43
|
+
};
|
|
44
|
+
syncTransformState();
|
|
45
|
+
/**
|
|
46
|
+
* Applies transform by combining translation with base matrix using matrix multiplication.
|
|
47
|
+
*/
|
|
48
|
+
const applyTransform = (x, y) => {
|
|
49
|
+
if (baseMatrix) {
|
|
50
|
+
const translationMatrix = new DOMMatrix();
|
|
51
|
+
translationMatrix.m41 = x;
|
|
52
|
+
translationMatrix.m42 = y;
|
|
53
|
+
const combined = translationMatrix.multiply(baseMatrix);
|
|
54
|
+
el.style.transform = combined.toString();
|
|
55
|
+
} else el.style.transform = `translate(${x}px, ${y}px)`;
|
|
56
|
+
};
|
|
16
57
|
const dispatch = (type, detail) => {
|
|
17
58
|
const eventInit = {
|
|
18
59
|
detail,
|
|
@@ -21,9 +62,13 @@ const makeDraggable = ({ el, dragHandle, focusableDragHandle, dragStep, shiftDra
|
|
|
21
62
|
el.dispatchEvent(new CustomEvent(type, eventInit));
|
|
22
63
|
};
|
|
23
64
|
const onKeyDown = (e) => {
|
|
24
|
-
if (e.key === "Enter")
|
|
25
|
-
|
|
26
|
-
|
|
65
|
+
if (e.key === "Enter") {
|
|
66
|
+
isDragging = !isDragging;
|
|
67
|
+
if (isDragging) {
|
|
68
|
+
syncTransformState();
|
|
69
|
+
dispatch("dragstart", { keyboard: true });
|
|
70
|
+
} else dispatch("dragend", { keyboard: true });
|
|
71
|
+
}
|
|
27
72
|
if (!isDragging) return;
|
|
28
73
|
const distance = e.shiftKey ? shiftDragStep ?? 32 : dragStep ?? 8;
|
|
29
74
|
switch (e.key) {
|
|
@@ -32,16 +77,20 @@ const makeDraggable = ({ el, dragHandle, focusableDragHandle, dragStep, shiftDra
|
|
|
32
77
|
e.preventDefault();
|
|
33
78
|
break;
|
|
34
79
|
case "ArrowLeft":
|
|
35
|
-
|
|
80
|
+
currentX -= distance;
|
|
81
|
+
applyTransform(currentX, currentY);
|
|
36
82
|
break;
|
|
37
83
|
case "ArrowRight":
|
|
38
|
-
|
|
84
|
+
currentX += distance;
|
|
85
|
+
applyTransform(currentX, currentY);
|
|
39
86
|
break;
|
|
40
87
|
case "ArrowUp":
|
|
41
|
-
|
|
88
|
+
currentY -= distance;
|
|
89
|
+
applyTransform(currentX, currentY);
|
|
42
90
|
break;
|
|
43
91
|
case "ArrowDown":
|
|
44
|
-
|
|
92
|
+
currentY += distance;
|
|
93
|
+
applyTransform(currentX, currentY);
|
|
45
94
|
break;
|
|
46
95
|
}
|
|
47
96
|
};
|
|
@@ -49,8 +98,9 @@ const makeDraggable = ({ el, dragHandle, focusableDragHandle, dragStep, shiftDra
|
|
|
49
98
|
const target = e.target;
|
|
50
99
|
if (!(target instanceof Node)) return;
|
|
51
100
|
if (!(dragHandle ? dragHandle.contains(target) : el.contains(target))) return;
|
|
52
|
-
|
|
53
|
-
|
|
101
|
+
syncTransformState();
|
|
102
|
+
initialMouseX = e.clientX;
|
|
103
|
+
initialMouseY = e.clientY;
|
|
54
104
|
isDragging = true;
|
|
55
105
|
dispatch("dragstart", { mouse: true });
|
|
56
106
|
document.addEventListener("mousemove", onMouseMove);
|
|
@@ -58,11 +108,16 @@ const makeDraggable = ({ el, dragHandle, focusableDragHandle, dragStep, shiftDra
|
|
|
58
108
|
};
|
|
59
109
|
const onMouseMove = (e) => {
|
|
60
110
|
if (!isDragging) return;
|
|
61
|
-
|
|
62
|
-
|
|
111
|
+
const dx = e.clientX - initialMouseX;
|
|
112
|
+
const dy = e.clientY - initialMouseY;
|
|
113
|
+
applyTransform(currentX + dx, currentY + dy);
|
|
63
114
|
};
|
|
64
|
-
const onMouseUp = () => {
|
|
115
|
+
const onMouseUp = (e) => {
|
|
65
116
|
if (!isDragging) return;
|
|
117
|
+
const dx = e.clientX - initialMouseX;
|
|
118
|
+
const dy = e.clientY - initialMouseY;
|
|
119
|
+
currentX += dx;
|
|
120
|
+
currentY += dy;
|
|
66
121
|
isDragging = false;
|
|
67
122
|
dispatch("dragend", { mouse: true });
|
|
68
123
|
document.removeEventListener("mousemove", onMouseMove);
|
|
@@ -77,7 +132,18 @@ const makeDraggable = ({ el, dragHandle, focusableDragHandle, dragStep, shiftDra
|
|
|
77
132
|
document.removeEventListener("mousemove", onMouseMove);
|
|
78
133
|
document.removeEventListener("mouseup", onMouseUp);
|
|
79
134
|
};
|
|
80
|
-
|
|
135
|
+
/**
|
|
136
|
+
* Re-initialize the draggable position from the element's current computed transform.
|
|
137
|
+
* Call this if the element has been repositioned externally (e.g., via CSS animation,
|
|
138
|
+
* class changes, or other scripts) to prevent position jumps on the next drag.
|
|
139
|
+
*/
|
|
140
|
+
const init = () => {
|
|
141
|
+
syncTransformState();
|
|
142
|
+
};
|
|
143
|
+
return {
|
|
144
|
+
cleanup: draggableCleanup,
|
|
145
|
+
init
|
|
146
|
+
};
|
|
81
147
|
};
|
|
82
148
|
|
|
83
149
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@carbon/utilities",
|
|
3
3
|
"description": "Utilities and helpers to drive consistency across software products using the Carbon Design System",
|
|
4
|
-
"version": "0.18.0
|
|
4
|
+
"version": "0.18.0",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"module": "es/index.js",
|
|
@@ -66,5 +66,5 @@
|
|
|
66
66
|
"@ibm/telemetry-js": "^1.6.1",
|
|
67
67
|
"@internationalized/number": "^3.6.1"
|
|
68
68
|
},
|
|
69
|
-
"gitHead": "
|
|
69
|
+
"gitHead": "aeaaa31889990fc76c7e0e8a29ec0bf96ce33f82"
|
|
70
70
|
}
|