Skip to content

Commit 9facbf2

Browse files
smoores-devpdiffley
authored andcommitted
Preserve drag clone styles exactly (#25)
1 parent 60897ed commit 9facbf2

8 files changed

Lines changed: 71 additions & 39 deletions

File tree

.yarn/versions/79b8c4fd.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
releases:
2+
"@pitter-patter/shuffle": patch

packages/docs/src/components/demos/shuffle.css

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,7 @@ img {
1212

1313
[data-node-type] {
1414
border-radius: 0.25rem;
15-
}
16-
17-
[data-node-type][data-shuffle-clone] {
1815
background-color: #f3efea;
19-
color: #351900;
2016
}
2117

2218
.shuffle-block {
@@ -38,7 +34,8 @@ img {
3834
border-radius: 0.25rem;
3935
justify-content: space-around;
4036
padding: 1rem;
41-
margin: 2rem;
37+
margin-top: 2rem;
38+
margin-bottom: 2rem;
4239
}
4340

4441
.card {
@@ -48,10 +45,10 @@ img {
4845
border-radius: 0.25rem;
4946
}
5047

51-
.card.shuffle-hover-block {
52-
border: 1px solid lightblue;
48+
.card p {
49+
background-color: white;
5350
}
5451

55-
.card[data-shuffle-clone] {
56-
background-color: white;
52+
.card.shuffle-hover-block {
53+
border: 1px solid lightblue;
5754
}

packages/docs/src/components/demos/shuffle.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import {
1818
shuffle,
1919
addShuffleNodes,
2020
DragHandles,
21+
DragHandle,
22+
type DragHandleProps,
2123
ShuffleSkeleton,
2224
ResizeHandles,
2325
} from "@pitter-patter/shuffle";
@@ -156,12 +158,19 @@ export function ShuffleDemo() {
156158
<ShuffleSkeleton>
157159
<ProseMirrorDoc />
158160
<ResizeHandles />
159-
<DragHandles />
161+
<DragHandles handleComponent={CustomHandle} />
160162
</ShuffleSkeleton>
161163
</ProseMirror>
162164
);
163165
}
164166

167+
function CustomHandle(props: DragHandleProps) {
168+
if (["image", "card", "card_deck"].includes(props.node.type.name)) {
169+
return null;
170+
}
171+
return <DragHandle {...props} />;
172+
}
173+
165174
function CardDeck({ nodeProps: _, ref, children, ...props }: NodeViewComponentProps) {
166175
return (
167176
<div

packages/shuffle/src/components/DragHandles.tsx

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ import {
1414

1515
import { shufflePluginKey, startDragOnPointerDown, ViewDesc } from "../plugin.js";
1616

17+
export interface DragHandleProps {
18+
style: { top: number; left: number };
19+
onPointerDown: EventHandler<SyntheticPointerEvent>;
20+
node: Node;
21+
}
22+
1723
interface Props {
18-
handleComponent?: ComponentType<{
19-
style: { top: number; left: number };
20-
onPointerDown: EventHandler<SyntheticPointerEvent>;
21-
node: Node;
22-
}>;
24+
handleComponent?: ComponentType<DragHandleProps>;
2325
}
2426

2527
export function DragHandles({ handleComponent }: Props) {
@@ -32,18 +34,18 @@ export function DragHandles({ handleComponent }: Props) {
3234
return (
3335
<>
3436
{hoverPositions.map(({ from }) => (
35-
<DragHandle key={from} pos={from} handleComponent={handleComponent} />
37+
<DragHandleRenderer key={from} pos={from} handleComponent={handleComponent} />
3638
))}
3739
</>
3840
);
3941
}
4042

41-
interface DragHandleProps {
43+
interface DragHandleRendererProps {
4244
pos: number;
4345
handleComponent?: Props["handleComponent"];
4446
}
4547

46-
export function DragHandle({ pos, handleComponent: Handle }: DragHandleProps) {
48+
export function DragHandleRenderer({ pos, handleComponent: Handle }: DragHandleRendererProps) {
4749
const [left, setLeft] = useState(0);
4850
const [top, setTop] = useState(0);
4951

@@ -84,13 +86,17 @@ export function DragHandle({ pos, handleComponent: Handle }: DragHandleProps) {
8486
return <Handle style={{ top, left }} node={node} onPointerDown={handlePointerDown} />;
8587
}
8688

89+
return <DragHandle style={{ top, left }} onPointerDown={handlePointerDown} node={node} />;
90+
}
91+
92+
export function DragHandle({ style, node, onPointerDown }: DragHandleProps) {
8793
return (
8894
<button
8995
type="button"
9096
className="shuffle-drag-handle"
91-
style={{ top, left }}
97+
style={style}
9298
draggable="false"
93-
onPointerDown={handlePointerDown}
99+
onPointerDown={onPointerDown}
94100
>
95101
{node.type.name}
96102
</button>

packages/shuffle/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ export {
1515
} from "./plugin.js";
1616
export { ShuffleSkeleton } from "./components/Skeleton.js";
1717
export { ResizeHandles, useResizeHandlePointerDown } from "./components/ResizeHandles.js";
18-
export { DragHandles } from "./components/DragHandles.js";
18+
export { type DragHandleProps, DragHandles, DragHandle } from "./components/DragHandles.js";

packages/shuffle/src/plugin.ts

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -306,14 +306,22 @@ export function startDragOnPointerDown(
306306

307307
const domRect = dom.getBoundingClientRect();
308308

309-
const transform = new DOMMatrixReadOnly(getComputedStyle(dom).transform);
309+
const domStyle = getComputedStyle(dom);
310+
const transform = new DOMMatrixReadOnly(domStyle.transform);
310311
const originX = transform.m41;
311312
const originY = transform.m42;
312313

313314
const startX = clientX;
314315
const startY = clientY;
315316

316-
const translateCalc = new TranslateCalculator(originX, originY, startX, startY, domRect);
317+
const translateCalc = new TranslateCalculator(
318+
originX,
319+
originY,
320+
startX,
321+
startY,
322+
domRect,
323+
parseInt(domStyle.marginTop, 10),
324+
);
317325

318326
let clone: HTMLElement | null = null;
319327
let initialStyles: InitialStyles | null = null;
@@ -455,11 +463,31 @@ function startDrag(dom: HTMLElement, translateCalc: TranslateCalculator) {
455463
const bodyRect = document.body.getBoundingClientRect();
456464

457465
const clone = dom.cloneNode(true) as HTMLElement;
466+
467+
let cloneQueue: Element[] = [clone];
468+
let domQueue: Element[] = [dom];
469+
470+
while (cloneQueue.length && domQueue.length) {
471+
const domElement = domQueue.pop();
472+
const cloneElement = cloneQueue.pop();
473+
474+
if (!(domElement instanceof HTMLElement && cloneElement instanceof HTMLElement)) {
475+
continue;
476+
}
477+
478+
const domStyles = getComputedStyle(domElement);
479+
for (let i = 0; i < domStyles.length; i++) {
480+
const property = domStyles.item(i);
481+
cloneElement.style.setProperty(property, domStyles.getPropertyValue(property));
482+
}
483+
484+
cloneQueue.push(...cloneElement.children);
485+
domQueue.push(...domElement.children);
486+
}
487+
458488
clone.style.position = "absolute";
459489
clone.style.top = `${domRect.top - bodyRect.top}px`;
460490
clone.style.left = `${domRect.left - bodyRect.left}px`;
461-
clone.style.width = `${domRect.width}px`;
462-
clone.style.height = `${domRect.height}px`;
463491
document.body.appendChild(clone);
464492

465493
dom.dataset["shuffleActive"] = "true";

packages/shuffle/src/translation.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ export class TranslateCalculator {
55
public startX: number,
66
public startY: number,
77
private rect: DOMRect,
8+
private marginTop: number,
89
) {}
910

1011
slide(x: number, y: number) {
1112
const dx = x - this.startX;
12-
const dy = y - this.startY;
13+
const dy = y - this.startY - this.marginTop;
1314
return {
1415
transform: `rotateX(0) scale(1.05) translate(${this.originX + dx}px, ${this.originY + dy}px)`,
15-
transformOrigin: `${this.startX - this.rect.x}px ${this.startY - this.rect.y}px`,
16+
transformOrigin: `${this.startX - this.rect.x}px ${this.startY - this.rect.y - this.marginTop}px`,
1617
};
1718
}
1819

@@ -21,7 +22,7 @@ export class TranslateCalculator {
2122
const offsetY = this.rect.y - this.startY;
2223

2324
const dx = x - this.startX - offsetX;
24-
const dy = y - this.startY - offsetY;
25+
const dy = y - this.startY - offsetY - this.marginTop;
2526

2627
return {
2728
transform: `rotateX(0) scale(1) translate(${this.originX + dx}px, ${this.originY + dy}px)`,

packages/shuffle/style/shuffle.css

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,6 @@
3232
grid-row-start: 1 !important;
3333
}
3434

35-
/* The drag clone gets a little messed up since
36-
its grid-template-columns is set to subgrid, but
37-
it's absolutely positioned. So we manually duplicate
38-
the grid template columns. This isn't perfect, but
39-
it looks much less broken. */
40-
[data-shuffle-clone].row {
41-
grid-template-columns:
42-
minmax(0, 1fr) repeat(12, minmax(0, var(--shuffle-column-width, 3rem)))
43-
minmax(0, 1fr);
44-
}
45-
4635
.shuffle-block {
4736
width: 100%;
4837
}

0 commit comments

Comments
 (0)