solid-dnd.tsx 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. import { useDragDropContext } from "@thisbeyond/solid-dnd"
  2. import type { Transformer } from "@thisbeyond/solid-dnd"
  3. import { createRoot, onCleanup, type JSXElement } from "solid-js"
  4. type DragEvent = { draggable?: { id?: unknown } }
  5. const isDragEvent = (event: unknown): event is DragEvent => {
  6. if (typeof event !== "object" || event === null) return false
  7. return "draggable" in event
  8. }
  9. export const getDraggableId = (event: unknown): string | undefined => {
  10. if (!isDragEvent(event)) return undefined
  11. const draggable = event.draggable
  12. if (!draggable) return undefined
  13. return typeof draggable.id === "string" ? draggable.id : undefined
  14. }
  15. const createTransformer = (id: string, axis: "x" | "y"): Transformer => ({
  16. id,
  17. order: 100,
  18. callback: (transform) => (axis === "x" ? { ...transform, x: 0 } : { ...transform, y: 0 }),
  19. })
  20. const createAxisConstraint = (axis: "x" | "y", transformerId: string) => (): JSXElement => {
  21. const context = useDragDropContext()
  22. if (!context) return null
  23. const [, { onDragStart, onDragEnd, addTransformer, removeTransformer }] = context
  24. const transformer = createTransformer(transformerId, axis)
  25. const dispose = createRoot((dispose) => {
  26. onDragStart((event) => {
  27. const id = getDraggableId(event)
  28. if (!id) return
  29. addTransformer("draggables", id, transformer)
  30. })
  31. onDragEnd((event) => {
  32. const id = getDraggableId(event)
  33. if (!id) return
  34. removeTransformer("draggables", id, transformer.id)
  35. })
  36. return dispose
  37. })
  38. onCleanup(dispose)
  39. return null
  40. }
  41. export const ConstrainDragXAxis = createAxisConstraint("x", "constrain-x-axis")
  42. export const ConstrainDragYAxis = createAxisConstraint("y", "constrain-y-axis")