draggableRuleListItem.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import {DraggableSyntheticListeners} from '@dnd-kit/core';
  2. import {useSortable} from '@dnd-kit/sortable';
  3. import {Transform} from '@dnd-kit/utilities';
  4. import styled from '@emotion/styled';
  5. type UseSortableOutputProps = ReturnType<typeof useSortable>;
  6. export type DraggableRuleListItemProps = {
  7. renderItem(args: {
  8. dragging: boolean;
  9. sorting: boolean;
  10. value: DraggableRuleListItemProps['value'];
  11. attributes?: DraggableRuleListItemProps['attributes'];
  12. index?: DraggableRuleListItemProps['index'];
  13. listeners?: DraggableRuleListItemProps['listeners'];
  14. transform?: DraggableRuleListItemProps['transform'];
  15. transition?: DraggableRuleListItemProps['transition'];
  16. }): React.ReactElement | null;
  17. value: React.ReactNode;
  18. attributes?: UseSortableOutputProps['attributes'];
  19. dragging?: boolean;
  20. forwardRef?: React.Ref<HTMLDivElement>;
  21. index?: number;
  22. listeners?: DraggableSyntheticListeners;
  23. sorting?: boolean;
  24. transform?: Transform | null;
  25. transition?: string | null;
  26. wrapperStyle?: React.CSSProperties;
  27. };
  28. export function DraggableRuleListItem({
  29. value,
  30. dragging,
  31. index,
  32. transform,
  33. listeners,
  34. sorting,
  35. transition,
  36. forwardRef,
  37. attributes,
  38. renderItem,
  39. wrapperStyle,
  40. }: DraggableRuleListItemProps) {
  41. return (
  42. <Wrapper
  43. data-test-id="sampling-rule"
  44. ref={forwardRef}
  45. style={
  46. {
  47. ...wrapperStyle,
  48. transition,
  49. '--translate-x': transform ? `${Math.round(transform.x)}px` : undefined,
  50. '--translate-y': transform ? `${Math.round(transform.y)}px` : undefined,
  51. '--scale-x': transform?.scaleX ? `${transform.scaleX}` : undefined,
  52. '--scale-y': transform?.scaleY ? `${transform.scaleY}` : undefined,
  53. } as React.CSSProperties
  54. }
  55. >
  56. <InnerWrapper>
  57. {renderItem({
  58. dragging: Boolean(dragging),
  59. sorting: Boolean(sorting),
  60. listeners,
  61. transform,
  62. transition,
  63. value,
  64. index,
  65. attributes,
  66. })}
  67. </InnerWrapper>
  68. </Wrapper>
  69. );
  70. }
  71. const boxShadowBorder = '0 0 0 calc(1px / var(--scale-x, 1)) rgba(63, 63, 68, 0.05)';
  72. const boxShadowCommon = '0 1px calc(3px / var(--scale-x, 1)) 0 rgba(34, 33, 81, 0.15)';
  73. const boxShadow = `${boxShadowBorder}, ${boxShadowCommon}`;
  74. const Wrapper = styled('div')`
  75. transform: translate3d(var(--translate-x, 0), var(--translate-y, 0), 0)
  76. scaleX(var(--scale-x, 1)) scaleY(var(--scale-y, 1));
  77. transform-origin: 0 0;
  78. touch-action: manipulation;
  79. --box-shadow: ${boxShadow};
  80. --box-shadow-picked-up: ${boxShadowBorder}, -1px 0 15px 0 rgba(34, 33, 81, 0.01),
  81. 0px 15px 15px 0 rgba(34, 33, 81, 0.25);
  82. `;
  83. const InnerWrapper = styled('div')`
  84. background-color: ${p => p.theme.background};
  85. animation: pop 200ms cubic-bezier(0.18, 0.67, 0.6, 1.22);
  86. box-shadow: var(--box-shadow-picked-up);
  87. opacity: 1;
  88. :focus {
  89. box-shadow: 0 0px 4px 1px rgba(76, 159, 254, 1), ${boxShadow};
  90. }
  91. @keyframes pop {
  92. 0% {
  93. transform: scale(1);
  94. box-shadow: var(--box-shadow);
  95. }
  96. 100% {
  97. box-shadow: var(--box-shadow-picked-up);
  98. }
  99. }
  100. `;