tangled
alpha
login
or
join now
leaflet.pub
/
leaflet
289
fork
atom
a tool for shared writing and social publishing
289
fork
atom
overview
issues
28
pulls
pipelines
make things blocks easier to manuever in canvas
cozylittle.house
1 month ago
4e8a2f10
30fe237f
+49
-23
4 changed files
expand all
collapse all
unified
split
components
Blocks
Block.tsx
ButtonBlock.tsx
EmbedBlock.tsx
Canvas.tsx
+11
-2
components/Blocks/Block.tsx
···
68
68
// Block handles all block level events like
69
69
// mouse events, keyboard events and longPress, and setting AreYouSure state
70
70
// and shared styling like padding and flex for list layouting
71
71
-
let { rep } = useReplicache();
72
71
let mouseHandlers = useBlockMouseHandlers(props);
73
72
let handleDrop = useHandleDrop({
74
73
parent: props.parent,
···
76
75
nextPosition: props.nextPosition,
77
76
});
78
77
let entity_set = useEntitySetContext();
78
78
+
79
79
+
let { isLongPress, longPressHandlers } = useLongPress(() => {
80
80
+
if (isTextBlock[props.type]) return;
81
81
+
if (isLongPress.current) {
82
82
+
focusBlock(
83
83
+
{ type: props.type, value: props.entityID, parent: props.parent },
84
84
+
{ type: "start" },
85
85
+
);
86
86
+
}
87
87
+
});
79
88
80
89
let selected = useUIState(
81
90
(s) => !!s.selectedBlocks.find((b) => b.value === props.entityID),
···
107
116
108
117
return (
109
118
<div
110
110
-
{...(!props.preview ? { ...mouseHandlers } : {})}
119
119
+
{...(!props.preview ? { ...mouseHandlers, ...longPressHandlers } : {})}
111
120
id={
112
121
!props.preview ? elementId.block(props.entityID).container : undefined
113
122
}
-1
components/Blocks/ButtonBlock.tsx
···
193
193
<Separator />
194
194
<Input
195
195
type="text"
196
196
-
autoFocus
197
196
className="w-full grow border-none outline-hidden bg-transparent"
198
197
placeholder="button text"
199
198
value={textValue}
+3
-1
components/Blocks/EmbedBlock.tsx
···
111
111
<div
112
112
data-draggable
113
113
className={`resizeHandle
114
114
+
115
115
+
114
116
cursor-ns-resize shrink-0 z-10 w-6 h-[5px]
115
115
-
absolute bottom-2 right-1/2 translate-x-1/2 translate-y-[2px]
117
117
+
absolute bottom-[3px] right-1/2 translate-x-1/2
116
118
rounded-full bg-white border-2 border-[#8C8C8C] shadow-[0_0_0_1px_white,inset_0_0_0_1px_white]
117
119
${isCanvasBlock ? "hidden group-hover/canvas-block:block" : ""}`}
118
120
{...heightHandle.handlers}
+35
-19
components/Canvas.tsx
···
26
26
PubLeafletPublicationRecord,
27
27
} from "lexicons/api";
28
28
import { useHandleCanvasDrop } from "./Blocks/useHandleCanvasDrop";
29
29
+
import { useBlockMouseHandlers } from "./Blocks/useBlockMouseHandlers";
29
30
30
31
export function Canvas(props: {
31
32
entityID: string;
···
292
293
);
293
294
let { dragDelta, handlers: dragHandlers } = useDrag({
294
295
onDragEnd,
295
295
-
delay: isMobile,
296
296
});
297
297
298
298
let widthOnDragEnd = useCallback(
···
389
389
};
390
390
}, [props, type?.data.value]);
391
391
useBlockKeyboardHandlers(blockProps, areYouSure, setAreYouSure);
392
392
+
let mouseHandlers = useBlockMouseHandlers(blockProps);
393
393
+
392
394
let isList = useEntity(props.entityID, "block/is-list");
393
395
let isFocused = useUIState(
394
396
(s) => s.focusedEntity?.entityID === props.entityID,
···
397
399
return (
398
400
<div
399
401
ref={ref}
400
400
-
{...(isMobile && permissions.write ? { ...dragHandlers } : {})}
402
402
+
{...(!props.preview ? { ...longPressHandlers } : {})}
403
403
+
// {...(isMobile && permissions.write ? { ...dragHandlers } : {})}
401
404
id={props.preview ? undefined : elementId.block(props.entityID).container}
402
402
-
className={`absolute group/canvas-block will-change-transform rounded-lg flex items-stretch origin-center p-3 `}
405
405
+
className={`canvasBlockWrapper absolute group/canvas-block will-change-transform rounded-lg flex items-stretch origin-center p-3 `}
403
406
style={{
404
407
top: 0,
405
408
left: 0,
···
409
412
}}
410
413
>
411
414
{/* the gripper show on hover, but longpress logic needs to be added for mobile*/}
412
412
-
{!props.preview && permissions.write && <Gripper {...dragHandlers} />}
415
415
+
{!props.preview && permissions.write && (
416
416
+
<Gripper isFocused={isFocused} {...dragHandlers} />
417
417
+
)}
418
418
+
419
419
+
{/*mouseHandlers are being added here so they don't interfere with the dragHandlers in the div above*/}
413
420
<div
414
414
-
className={`contents ${dragDelta || widthHandle.dragDelta || rotateHandle.dragDelta ? "pointer-events-none" : ""} `}
421
421
+
className={` w-full ${dragDelta || widthHandle.dragDelta || rotateHandle.dragDelta ? "pointer-events-none" : ""} `}
422
422
+
{...(!props.preview ? { ...mouseHandlers } : {})}
415
423
>
416
424
<BaseBlock
417
425
{...blockProps}
···
429
437
<div
430
438
className={`resizeHandle
431
439
cursor-e-resize shrink-0 z-10
432
432
-
hidden group-hover/canvas-block:block
433
433
-
w-[5px] h-6 -ml-[3px]
434
434
-
absolute top-1/2 right-3 -translate-y-1/2 translate-x-[2px]
435
435
-
rounded-full bg-white border-2 border-[#8C8C8C] shadow-[0_0_0_1px_white,inset_0_0_0_1px_white]`}
440
440
+
group-hover/canvas-block:block
441
441
+
sm:w-[5px] w-3 sm:h-6 h-8
442
442
+
absolute top-1/2 sm:right-2 right-1 -translate-y-1/2
443
443
+
rounded-full bg-white border-2 border-[#8C8C8C] shadow-[0_0_0_1px_white,inset_0_0_0_1px_white]
444
444
+
${isFocused ? "block" : "hidden"}
445
445
+
446
446
+
`}
436
447
{...widthHandle.handlers}
437
448
/>
438
449
)}
···
441
452
<div
442
453
className={`rotateHandle
443
454
cursor-grab shrink-0 z-10
444
444
-
hidden group-hover/canvas-block:block
445
445
-
w-[8px] h-[8px]
446
446
-
absolute bottom-0 -right-0
455
455
+
group-hover/canvas-block:block
456
456
+
sm:w-[8px] sm:h-[8px] w-4 h-4
457
457
+
absolute sm:bottom-0 sm:right-0 -bottom-1 -right-1
447
458
-translate-y-1/2 -translate-x-1/2
448
448
-
rounded-full bg-white border-2 border-[#8C8C8C] shadow-[0_0_0_1px_white,inset_0_0_0_1px_white]`}
459
459
+
rounded-full bg-white border-2 border-[#8C8C8C] shadow-[0_0_0_1px_white,inset_0_0_0_1px_white]
460
460
+
${isFocused ? "block" : "hidden"}
461
461
+
`}
449
462
{...rotateHandle.handlers}
450
463
/>
451
464
)}
···
566
579
}
567
580
};
568
581
569
569
-
const Gripper = (props: { onMouseDown: (e: React.MouseEvent) => void }) => {
582
582
+
const Gripper = (props: {
583
583
+
onMouseDown: (e: React.MouseEvent) => void;
584
584
+
isFocused: boolean;
585
585
+
}) => {
570
586
return (
571
587
<div
572
588
onMouseDown={props.onMouseDown}
573
589
onPointerDown={props.onMouseDown}
574
574
-
className="w-[9px] shrink-0 py-1 mr-1 bg-bg-card cursor-grab touch-none"
590
590
+
className="gripper w-[9px] shrink-0 py-1 mr-1 cursor-grab touch-none"
575
591
>
576
576
-
<Media mobile={false} className="h-full grid grid-cols-1 grid-rows-1 ">
592
592
+
<div className="h-full grid grid-cols-1 grid-rows-1 ">
577
593
{/* the gripper is two svg's stacked on top of each other.
578
594
One for the actual gripper, the other is an outline to endure the gripper stays visible on image backgrounds */}
579
595
<div
580
580
-
className="h-full col-start-1 col-end-2 row-start-1 row-end-2 bg-bg-page hidden group-hover/canvas-block:block"
596
596
+
className={`h-full col-start-1 col-end-2 row-start-1 row-end-2 bg-bg-page group-hover/canvas-block:block ${props.isFocused ? "block" : "hidden"}`}
581
597
style={{ maskImage: "var(--gripperSVG2)", maskRepeat: "repeat" }}
582
598
/>
583
599
<div
584
584
-
className="h-full col-start-1 col-end-2 row-start-1 row-end-2 bg-tertiary hidden group-hover/canvas-block:block"
600
600
+
className={`h-full col-start-1 col-end-2 row-start-1 row-end-2 bg-tertiary group-hover/canvas-block:block ${props.isFocused ? "block" : "hidden"}`}
585
601
style={{ maskImage: "var(--gripperSVG)", maskRepeat: "repeat" }}
586
602
/>
587
587
-
</Media>
603
603
+
</div>
588
604
</div>
589
605
);
590
606
};