CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-fullcalendar--interaction

Interactive functionality for FullCalendar including event dragging, resizing, date clicking, and external drag-and-drop support

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

third-party-integration.mddocs/

Third-Party Drag Integration

Third-party drag integration allows you to bridge existing drag-and-drop libraries (like Sortable.js, dragula, or custom implementations) with FullCalendar. This provides flexibility to use your preferred drag system while maintaining FullCalendar's drop handling.

Capabilities

ThirdPartyDraggable Class

Bridges third-party drag-and-drop systems with FullCalendar by detecting drag operations and translating them into FullCalendar-compatible events.

/**
 * Bridges third-party drag-n-drop systems with FullCalendar
 * Must be instantiated and destroyed by caller
 * @param containerOrSettings - Event target container or settings object
 * @param settings - Configuration options when first param is container
 */
export class ThirdPartyDraggable {
  constructor(
    containerOrSettings?: EventTarget | ThirdPartyDraggableSettings,
    settings?: ThirdPartyDraggableSettings
  );
  
  /** Destroys the third-party draggable instance and removes listeners */
  destroy(): void;
  
  /** Internal dragging implementation (read-only) */
  readonly dragging: InferredElementDragging;
}

Usage Examples:

import { ThirdPartyDraggable } from '@fullcalendar/interaction';

// Global drag detection (detects drags anywhere in document)
const globalDraggable = new ThirdPartyDraggable({
  itemSelector: '[data-event]',
  eventData: (el) => ({
    title: el.dataset.title,
    duration: el.dataset.duration
  })
});

// Container-specific drag detection
const containerEl = document.getElementById('external-container');
const containerDraggable = new ThirdPartyDraggable(containerEl, {
  itemSelector: '.draggable-event',
  mirrorSelector: '.drag-mirror',
  eventData: {
    title: 'Third-party Event',
    backgroundColor: '#ff9f43'
  }
});

// Cleanup
globalDraggable.destroy();
containerDraggable.destroy();

ThirdPartyDraggableSettings

Configuration interface for third-party drag integration.

interface ThirdPartyDraggableSettings {
  /** Event data or function to generate event data when dropped */
  eventData?: DragMetaGenerator;
  
  /** CSS selector for draggable items */
  itemSelector?: string;
  
  /** CSS selector for drag mirror element */
  mirrorSelector?: string;
}

Property Details:

  • eventData: Same as ExternalDraggable - defines event data for dropped elements
  • itemSelector: CSS selector to identify draggable items (defaults to [data-event] for document container)
  • mirrorSelector: CSS selector to identify the drag mirror/ghost element created by third-party library

Constructor Variations

The ThirdPartyDraggable constructor supports multiple patterns:

// Pattern 1: Settings only (uses document as container)
new ThirdPartyDraggable(settings);

// Pattern 2: Container and settings
new ThirdPartyDraggable(container, settings);

// Pattern 3: Document container explicitly
new ThirdPartyDraggable(document, settings);

Pattern Examples:

// Document-wide detection with default selector
const docDraggable = new ThirdPartyDraggable({
  eventData: { title: 'Document Event' }
}); // Uses [data-event] selector by default

// Specific container
const listContainer = document.getElementById('sortable-list');
const listDraggable = new ThirdPartyDraggable(listContainer, {
  itemSelector: '.list-item',
  eventData: (el) => ({ title: el.textContent })
});

// Document with custom selector
const customDraggable = new ThirdPartyDraggable(document, {
  itemSelector: '.custom-draggable',
  eventData: { title: 'Custom Event' }
});

Integration with Popular Libraries

Sortable.js Integration:

import Sortable from 'sortablejs';
import { ThirdPartyDraggable } from '@fullcalendar/interaction';

// Set up Sortable.js
const listEl = document.getElementById('sortable-list');
const sortable = Sortable.create(listEl, {
  group: {
    name: 'shared',
    pull: 'clone',
    put: false
  },
  sort: false,
  ghostClass: 'sortable-ghost'
});

// Bridge with FullCalendar
const thirdPartyDraggable = new ThirdPartyDraggable(listEl, {
  itemSelector: '.sortable-item',
  mirrorSelector: '.sortable-ghost',
  eventData: (el) => ({
    title: el.textContent,
    backgroundColor: el.dataset.color,
    duration: el.dataset.duration || '01:00'
  })
});

Custom Drag Library Integration:

// Assuming a custom drag library that adds 'dragging' class
const customDraggable = new ThirdPartyDraggable({
  itemSelector: '.my-draggable',
  mirrorSelector: '.dragging', // Element with dragging class
  eventData: (el) => {
    const config = JSON.parse(el.dataset.eventConfig || '{}');
    return {
      title: config.title || el.textContent,
      backgroundColor: config.color || '#007bff',
      extendedProps: config.props || {}
    };
  }
});

Advanced Usage Patterns

Multiple Third-Party Sources:

// Different drag sources with different configurations
const sidebarDraggable = new ThirdPartyDraggable(
  document.getElementById('sidebar'),
  {
    itemSelector: '.sidebar-item',
    eventData: (el) => ({
      title: el.dataset.title,
      backgroundColor: '#28a745',
      extendedProps: { source: 'sidebar' }
    })
  }
);

const toolboxDraggable = new ThirdPartyDraggable(
  document.getElementById('toolbox'),
  {
    itemSelector: '.tool-item',
    eventData: (el) => ({
      title: el.dataset.name,
      backgroundColor: '#dc3545',
      extendedProps: { 
        source: 'toolbox',
        toolType: el.dataset.type
      }
    })
  }
);

Dynamic Event Data with Complex Logic:

const complexDraggable = new ThirdPartyDraggable({
  itemSelector: '.complex-item',
  eventData: (el) => {
    // Complex logic based on element state
    const isUrgent = el.classList.contains('urgent');
    const category = el.dataset.category;
    const baseColor = el.style.backgroundColor;
    
    return {
      title: el.querySelector('.item-title').textContent,
      backgroundColor: isUrgent ? '#ff0000' : baseColor,
      borderColor: isUrgent ? '#cc0000' : 'transparent',
      duration: isUrgent ? '00:30' : '01:00',
      extendedProps: {
        category,
        urgent: isUrgent,
        originalId: el.id,
        metadata: JSON.parse(el.dataset.metadata || '{}')
      }
    };
  }
});

Integration with FullCalendar Events

Third-party dragging integrates with the same FullCalendar event system:

const calendar = new Calendar(calendarEl, {
  plugins: [interactionPlugin],
  
  drop: (info) => {
    console.log('Third-party element dropped:', info.draggedEl);
    // info.draggedEl is the original dragged element
    // info.jsEvent is the drop event
    // info.date, info.dateStr, info.allDay provide drop location info
  },
  
  eventReceive: (info) => {
    console.log('Event created from third-party drag:', info.event.title);
    // info.event is the newly created event
    // info.relatedEvents are any related events
    // info.revert() can undo the operation
  }
});

Important Considerations

Pointer Events: The third-party drag system automatically disables pointer event checking for drag mirrors, since third-party libraries may not follow FullCalendar's pointer event conventions.

Mirror Detection: If your third-party library creates drag mirrors/ghosts, specify the mirrorSelector to help FullCalendar identify the visual feedback element.

Performance: For document-wide detection, consider using specific containers when possible to reduce event listener overhead.

Cleanup: Always call destroy() when removing third-party draggable instances to prevent memory leaks.

docs

external-dragging.md

index.md

interaction-types.md

third-party-integration.md

tile.json