### Development Setup Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/packages/dnd-timeline/README.md Set up the development environment for contributing to dnd-timeline using turborepo. This command installs dependencies and starts the development server. ```sh npm install npm run dev ``` -------------------------------- ### Run Development Environment Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/README.md Commands to install dependencies and start the development server for the monorepo. ```sh pnpm install pnpm run dev ``` -------------------------------- ### Install dnd-timeline Library Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/guide/installation.md Install the dnd-timeline library after its peer dependency has been installed. ```bash npm install dnd-timeline ``` -------------------------------- ### Install Dependencies Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/README.md Install the required peer dependency and the library itself. ```sh npm install react ``` ```sh npm install dnd-timeline ``` -------------------------------- ### Install pnpm Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/README.md Enable pnpm using corepack for managing the monorepo. ```sh corepack enable pnpm ``` -------------------------------- ### Install React Peer Dependency Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/guide/installation.md Install the required React peer dependency before installing the library. ```bash npm install react ``` -------------------------------- ### Subrow Implementation Example Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/row/subrow.md This example demonstrates how to use the `groupItemsToSubrows` utility within a `Timeline` component to render items stacked in subrows. ```APIDOC ## Timeline Component with Subrow Rendering ### Description This component utilizes the `groupItemsToSubrows` utility to organize and render timeline items that have intersecting spans. Items that overlap are grouped into separate subrows for better visual clarity. ### Method N/A (Component Implementation) ### Endpoint N/A (Client-side Component) ### Parameters #### Props - **items** (ItemDefinition[]) - Required - An array of items to be displayed on the timeline. Each item must conform to the `ItemDefinition` type. - **range?** (Span) - Optional - A `Span` object used to filter items, rendering only those that intersect with the specified range. This optimizes performance by reducing the number of rendered items. ### Request Example ```tsx function Timeline(props: TimelineProps) { const { setTimelineRef, style, range } = useTimelineContext() const groupedSubrows = useMemo( () => groupItemsToSubrows(items, range), [items, range] ) return (
{props.rows.map((row) => }> {groupedSubrows[row.id]?.map((subrow, index) =>
{subrow.map((item) => // Render item here... )}
)}
)}
) } ``` ### Response N/A (Component Rendering) ### CSS Requirements To ensure proper rendering of subrows, apply the following CSS properties to the subrow elements: ```css position: relative; height: 50px; // Adjust height as per your row's design ``` ``` -------------------------------- ### Run Specific Example Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/README.md Use the turborepo filter operator to run a specific package and its dependencies. ```sh pnpm run dev --filter home... ``` -------------------------------- ### Implement Resize Callback Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/item/useitem.md Example of using the onResizeMove callback to update local state during a resize operation. ```tsx const onResizeMove = useCallback(() => { const updatedSpan = event.active.data.current.getSpanFromResizeEvent?.(event) // update some local state with the updated-span }, []) useItem({ id: props.id, span: props.span, onResizeMove, }) ``` -------------------------------- ### Render Rows in Timeline Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/row/README.md Usage example showing how to map and render Row components within the timeline context. ```tsx const { setTimelineRef, style } = useTimelineContext(); return (
{rows.map((row) => ( }> // render row items... ))}
); ``` -------------------------------- ### Define ResizeStartEvent Type Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/item/useitem.md Type definition for the resize start event callback. ```tsx onResizeMove?: (event: ResizeStartEvent) => void ``` ```tsx type ResizeStartEvent = { active: Omit direction: DragDirection // 'start' | 'end' } ``` -------------------------------- ### Get Delta X from Screen X Coordinate Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/usetimelinecontext.md Calculates the delta X distance from the timeline's start for a given screen X coordinate. Useful for positioning custom items relative to mouse events. ```typescript getDeltaXFromScreenX: (screenX: number) => number ``` -------------------------------- ### Handle DragEndEvent for Timeline Rows Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/row/userow.md This example demonstrates how to handle the DragEndEvent to identify if a dragged item is being dropped onto a 'timeline-row'. It shows how to retrieve relevance data and row types from the event. ```tsx const onDragEnd = (event: DragEndEvent) => { const updatedRelevance = event.active.data.current.getRelevanceFromDragEvent?.(event); const rowType = event.active.data.current.type; if (rowType === "timeline-row") { // update item with id activeItemId with the updatedRelevance, or the updated row using overedId } }; ``` -------------------------------- ### Set sidebar width Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/README.md Defines the sidebar width in pixels for layout calculations and provides a usage example for TimelineContext. ```tsx sidebarWidth: number; ``` ```tsx ``` -------------------------------- ### Get Value from Screen X Coordinate Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/usetimelinecontext.md Calculates the timeline value corresponding to a given screen X coordinate. Useful for determining the time from mouse events on the timeline. ```typescript getValueFromScreenX: (screenX: number) => number ``` -------------------------------- ### Define Item Span Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/item/useitem.md Object representing the start and end values of the item. ```tsx span: Span ``` -------------------------------- ### Use TimelineContext in Timeline Component Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/README.md The Timeline component utilizes the useTimelineContext hook to get a ref for the timeline's main element and its associated styles. This allows the timeline to be properly rendered and managed within the context. ```tsx function Timeline(props: TimelineProps){ const { setTimelineRef, style } = useTimelineContext() return (
{props.rows.map((row) => // Render rows here... )}
) } ``` -------------------------------- ### Initialize TimelineContext with State and Callbacks Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/README.md Initialize TimelineContext with state variables for rows, items, and the current time range. It also includes event handlers like onResizeEnd and onRangeChanged for interactive timeline manipulation. ```tsx function App() { const [rows, setRows] = useRows(); const [items, setItems] = useItems(); const [range, setRange] = useState(DEFAULT_TIMEFRAME); const onResizeEnd = useCallback((event: ResizeEndEvent) => { const updatedSpan = event.active.data.current.getSpanFromResizeEvent?.(event); if (!updatedSpan) return; const activeItemId = event.active.id; // Only update the changed item. This will cause only the changed items to re-render setItems((prev) => prev.map((item) => { if (item.id !== activeItemId) return item; return { ...item, span: updatedSpan, }; }), ); }, []); return ( ); } ``` -------------------------------- ### Initialize useItem Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/item/useitem.md Basic implementation of the useItem hook within a component. ```tsx useItem({ id: props.id, span: props.span, data: { type: 'timeline-item' }, }) ``` -------------------------------- ### Event Handlers Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/README.md Details on how to handle drag and resize events within the TimelineContext, utilizing helper functions provided in the event data. ```APIDOC ## Event Handlers ### Description Timeline events are based on dnd-kit. Each event provides a helper function (e.g., getSpanFromDragEvent or getSpanFromResizeEvent) attached to the event's active node data to calculate updated spans. ### Usage - **onDragStart, onDragEnd, onDragMove, onDragCancel**: Supported via dnd-kit. Use the helper function provided in `event.active.data.current` to calculate the new span. - **onResizeStart**: Triggered when a resize operation begins. Provides `active` node and `direction` ('start' | 'end'). ``` -------------------------------- ### Configure range grid snapping Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/README.md Enables snapping in the timeline using either a fixed number or an array of GridSizeDefinition objects for dynamic snapping. ```tsx rangeGridSizeDefinition?: number | GridSizeDefinition[] ``` ```tsx type GridSizeDefinition = { value: number; maxRangeSize?: number; }; ``` ```tsx const rangeGridSize: GridSizeDefinition[] = [ { value: hoursToMilliseconds(1), }, { value: minutesToMilliseconds(30), maxRangeSize: hoursToMilliseconds(24), }, ]; ``` -------------------------------- ### Applying CSS Transitions for Smoother Debouncing Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/zoom-and-pan/performance.md Apply CSS transitions to the item's style to make debounced or deferred updates feel smoother. This can be used in conjunction with `useDeferredValue` or throttling/debouncing techniques. ```tsx function Item(props: ItemProps) { ... const style: CSSProperties = { ...itemStyle, transition: 'left .2s linear, width .2s linear', // You can a CSS transition to make the debounce feel smoother } return (
...
) } ``` -------------------------------- ### Configure resize handle width Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/README.md Sets the width of the resize handle in pixels; setting to 0 disables resizing. ```tsx resizeHandleWidth?: number = 20 ``` -------------------------------- ### Wrap App with TimelineContext Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/README.md All timeline components must be wrapped within the TimelineContext. This sets up the necessary state management and event handling for the timeline. ```tsx function App() { return ( // You code here ) } ``` -------------------------------- ### useTimelineMonitor Hook API Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/usetimelinemonitor.md This hook allows you to monitor drag and resize events that occur on the timeline. It serves as a unified interface for handling both dnd-kit drag events and dnd-timeline specific resize events. ```APIDOC ## useTimelineMonitor Hook ### Description This hook allows you to monitor drag and resize events that occur on the timeline. It serves as a unified interface for handling both `dnd-kit` drag events and `dnd-timeline` specific resize events. ### Method HOOK ### Endpoint N/A (This is a React Hook) ### Parameters Accepts an object with the following optional callback functions: #### Drag Events (from `@dnd-kit/core`) - **onDragStart** (function) - Optional - Called when a drag operation starts. - **onDragMove** (function) - Optional - Called when a draggable item is moved. - **onDragOver** (function) - Optional - Called when a draggable item is moved over a droppable container. - **onDragEnd** (function) - Optional - Called when a drag operation ends. - **onDragCancel** (function) - Optional - Called when a drag operation is cancelled. #### Resize Events (specific to `dnd-timeline`) - **onResizeStart** (function) - Optional - Called when a resize operation starts. - **onResizeMove** (function) - Optional - Called when an item is being resized. - **onResizeEnd** (function) - Optional - Called when a resize operation ends. ### Request Example ```tsx import { useTimelineMonitor } from "dnd-timeline"; useTimelineMonitor({ onDragStart: (event) => { console.log("Drag started", event); }, onDragEnd: (event) => { console.log("Drag ended", event); }, onResizeStart: (event) => { console.log("Resize started", event); }, onResizeEnd: (event) => { console.log("Resize ended", event); }, }); ``` ### Response N/A (This hook does not return a value, but triggers callbacks) #### Success Response (N/A) #### Response Example N/A ``` -------------------------------- ### Enable resize animations Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/README.md Enables animations during resize interactions based on the span returned by getSpanFromResizeEvent. ```tsx useResizeAnimation?: boolean = false ``` -------------------------------- ### Define Resize Handle Width Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/item/useitem.md Optional width in pixels for the resize handle; setting to 0 disables resizing. ```tsx resizeHandleWidth?: number ``` -------------------------------- ### Configure pan and zoom strategy Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/README.md Defines how the timeline handles panning and zooming interactions. ```tsx usePanStrategy?: UsePanStrategy = useWheelStrategy ``` ```tsx type UsePanStrategy = ( timelineRef: React.MutableRefObject, onPanEnd: OnPanEnd, ) => void; type OnPanEnd = (event: PanEndEvent) => void; type PanEndEvent = { clientX?: number; clientY?: number; deltaX: number; deltaY: number; }; ``` -------------------------------- ### Monitor drag and resize events with useTimelineMonitor Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/usetimelinemonitor.md Registers callback functions for drag and resize lifecycle events within a timeline component. ```tsx import { useTimelineMonitor } from "dnd-timeline"; useTimelineMonitor({ onDragStart: (event) => { console.log("Drag started", event); }, onDragEnd: (event) => { console.log("Drag ended", event); }, onResizeStart: (event) => { console.log("Resize started", event); }, onResizeEnd: (event) => { console.log("Resize ended", event); }, }); ``` -------------------------------- ### Timeline Component Props Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/README.md Configuration props for the Timeline component to manage interactions, range, and layout. ```APIDOC ## Timeline Component Props ### Description Configuration options for the Timeline component to handle user interactions like resizing, dragging, panning, and range control. ### Parameters - **range** (Range) - Required - Object defining the viewable range in the timeline. - **onRangeChanged** (Function) - Required - Callback to update the controlled range state. - **sidebarWidth** (number) - Required - Width of the sidebar in pixels. - **onResizeMove** (Function) - Optional - Callback triggered during item resize. - **onResizeEnd** (Function) - Optional - Callback triggered when item resize ends. - **overlayed** (boolean) - Optional - Enables/disables rendering of items when dragging. Default: false. - **rangeGridSizeDefinition** (number | GridSizeDefinition[]) - Optional - Configures snapping in the timeline. - **usePanStrategy** (Function) - Optional - Configures panning and zooming. Default: useWheelStrategy. - **resizeHandleWidth** (number) - Optional - Width of the resize handle in pixels. Default: 20. - **useResizeAnimation** (boolean) - Optional - Enables resize animations. Default: false. - **getSpanFromDragEventStrategy** (Function) - Optional - Overrides how the active item's span is inferred during drag interactions. ``` -------------------------------- ### Configure overlayed rendering Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/README.md Enables or disables rendering of items during drag operations; set to true when using dnd-kit's DragOverlay. ```tsx overlayed?: boolean = false ``` -------------------------------- ### TimelineContext Component Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/README.md The TimelineContext component is the primary provider for the timeline state. All timeline components must be wrapped within this context. ```APIDOC ## TimelineContext ### Description A wrapper component that provides the necessary context for managing timeline state, including range, sidebar width, and event handlers for drag and resize operations. ### Props - **range** (Range) - Required - The current timeframe { start: number, end: number }. - **onRangeChanged** (OnRangeChanged) - Required - Callback triggered when the range changes. - **onResizeEnd** (OnResizeEnd) - Required - Callback triggered when a resize operation ends. - **sidebarWidth** (number) - Required - The width of the sidebar in pixels. - **overlayed** (boolean) - Optional - Whether the timeline is overlayed. - **onResizeMove** (OnResizeMove) - Optional - Callback for resize movement. - **onResizeStart** (OnResizeStart) - Optional - Callback for resize start. - **usePanStrategy** (UsePanStrategy) - Optional - Strategy for panning. - **rangeGridSizeDefinition** (number | GridSizeDefinition[]) - Optional - Grid size definition for the range. - **useResizeAnimation** (boolean) - Optional - Whether to enable resize animations. - **getSpanFromDragEventStrategy** (GetSpanFromDragEventStrategy) - Optional - Strategy for calculating span from drag events. - **getSpanFromResizeEventStrategy** (GetSpanFromResizeEventStrategy) - Optional - Strategy for calculating span from resize events. ``` -------------------------------- ### Default Wheel Zoom/Pan Strategy Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/zoom-and-pan/README.md This is the default strategy for handling zoom and pan interactions using the mouse wheel. It requires the `useLayoutEffect` hook and listens for 'wheel' events on the timeline element. It prevents default behavior for scroll events when Ctrl/Meta key is pressed. ```tsx export const useWheelStrategy: UsePanStrategy = (timelineBag, onPanEnd) => { useLayoutEffect(() => { const element = timelineBag.timelineRef.current; if (!element) return; const pointerWheelHandler = (event: WheelEvent) => { if (!event.ctrlKey && !event.metaKey) return; event.preventDefault(); const isHorizontal = event.shiftKey; const panEndEvent: PanEndEvent = { clientX: event.clientX, clientY: event.clientY, deltaX: isHorizontal ? event.deltaX || event.deltaY : 0, deltaY: isHorizontal ? 0 : event.deltaY, }; onPanEnd(panEndEvent); }; element.addEventListener("wheel", pointerWheelHandler, { passive: false }); return () => { element.removeEventListener("wheel", pointerWheelHandler); }; }, [onPanEnd, timelineBag.timelineRef]); }; ``` -------------------------------- ### Apply CSS for Subrow Layout Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/row/subrow.md Basic CSS configuration required for the subrow container to function correctly. ```css position: relative; height: 50px; // replace with your own row height ``` -------------------------------- ### Implement a custom Row component Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/row/README.md A basic implementation of a Row component using the useRow hook to manage drag-and-drop functionality. ```tsx interface RowProps extends RowDefinition { children: React.ReactNode; sidebar: React.ReactNode; } function Row(props: RowProps) { const { setNodeRef, rowWrapperStyle, rowStyle, rowSidebarStyle } = useRow({ id: props.id, }); return (
{props.sidebar}
{props.children}
); } ``` -------------------------------- ### Timeline Container Styles Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/usetimelinecontext.md Mandatory CSS properties that must be applied to the timeline container element. ```typescript style: CSSProperties ``` -------------------------------- ### Create useDebounce Hook Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/zoom-and-pan/performance.md A custom hook that delays updating a value until a specified delay period has passed. ```tsx export function useDebounce(value: T, delay = 500) { const [debouncedValue, setDebouncedValue] = useState(value); useEffect(() => { const handler = setTimeout(() => { setDebouncedValue(value); }, delay); return () => { clearTimeout(handler); }; }, [value, delay]); return debouncedValue; } ``` -------------------------------- ### ItemDefinition Type and Props Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/row/subrow.md Definitions for the item structure and optional range filtering. ```tsx items: ItemDefinition[] ``` ```tsx type ItemDefinition = { id: string rowId: string span: Span disabled?: boolean } ``` ```tsx range?: Span ``` -------------------------------- ### getSpanFromResizeEventStrategy Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/README.md A callback that overrides how `getSpanFromResizeEvent` infers the active item's span during resize interactions. If provided, this strategy will be used instead of the default resize span strategy. ```APIDOC ## `getSpanFromResizeEventStrategy?` ### Description A callback that overrides how `getSpanFromResizeEvent` infers the active item's span during resize interactions. If provided, this strategy will be used instead of the default resize span strategy. ### Method Callback Function ### Endpoint N/A (Callback) ### Parameters #### Function Parameters - **event** (ResizeMoveEvent | ResizeEndEvent) - Required - The resize event object. - **timelineBag** (TimelineBag) - Required - The timeline bag object containing timeline state. ### Request Example ```typescript (event: ResizeMoveEvent | ResizeEndEvent, timelineBag: TimelineBag) => Span | null ``` ### Response #### Success Response - **Span | null** - The inferred span or null if not applicable. ``` -------------------------------- ### Implement Debounced Range in App.tsx Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/zoom-and-pan/performance.md Integrate the useDebounce hook into the main application component to throttle range updates passed to the TimelineContext. ```tsx function App() { const [range, setRange] = useState(DEFAULT_TIMEFRAME); const debouncedRange = useDebounce(range, 300) ... return ( ) } ``` -------------------------------- ### Apply CSS Transitions in Item.tsx Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/zoom-and-pan/performance.md Add CSS transitions to timeline items to ensure smooth visual updates when using debounced state. ```tsx function Item(props: ItemProps) { ... const style: CSSProperties = { ...itemStyle, transition: 'left .2s linear, width .2s linear', // You can a CSS transition to make the debounce feel smoother } return (
...
) } ``` -------------------------------- ### Define Item Style Properties Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/item/useitem.md Required style properties for the item and its content wrapper elements. ```tsx itemStyle: CSSProperties ``` ```tsx itemContentStyle: CSSProperties ``` -------------------------------- ### Basic Item Component Implementation Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/item/README.md This TypeScript code defines a basic Item component using React and the useItem hook from dnd-timeline. It handles drag-and-drop functionality and styling, requiring a unique ID and span for each item. ```tsx interface ItemProps { id: string span: Span children: ReactNode } function Item(props: ItemProps) { const { setNodeRef, attributes, listeners, itemStyle, itemContentStyle, } = useItem({ id: props.id, span: props.span, }) return (
{props.children}
) } ``` -------------------------------- ### Timeline Container Ref Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/usetimelinecontext.md A mutable ref object pointing to the timeline container HTML element. ```typescript timelineRef: React.MutableRefObject ``` -------------------------------- ### Define onResizeEnd event handler Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/README.md The active object contains custom data and a getSpanFromResizeEvent function to calculate updated spans. ```tsx onResizeMove?: (event: ResizeEndEvent) => void ``` ```tsx type ResizeEndEvent = { active: Omit; delta: { x: number; }; direction: DragDirection; // 'start' | 'end' }; ``` -------------------------------- ### Handle Drag End Event Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/item/useitem.md Logic for processing drag completion and updating item spans based on row types. ```tsx const onDragEnd = (event: DragEndEvent) => { const updatedSpan = event.active.data.current.getSpanFromDragEvent?.(event) const rowType = event.active.data.current.type if (rowType === 'timeline-row' && itemType === 'timeline-item') { // update } if (rowType === 'timeline-disabled-row' && itemType === 'timeline-item') { // don't update, and pop an error message } } ``` -------------------------------- ### Implement Subrows in Timeline Component Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/row/subrow.md Use the groupItemsToSubrows utility within a useMemo hook to organize timeline items into subrows for rendering. ```tsx function Timeline(props: TimelineProps) { const { setTimelineRef, style, range } = useTimelineContext() const groupedSubrows = useMemo( () => groupItemsToSubrows(items, range), [items, range] ) return (
{props.rows.map((row) => }> {groupedSubrows[row.id]?.map((subrow, index) =>
{subrow.map((item) => // Render item here... )}
)}
)}
) } ``` -------------------------------- ### useTimelineContext API Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/usetimelinecontext.md The useTimelineContext hook provides access to the timeline's state and several utility functions for managing and interacting with timeline elements. ```APIDOC ## useTimelineContext API ### Description This hook provides access to the timeline's state and helper functions for managing its elements. ### Properties #### `style` - **style** (CSSProperties) - Required - A set of mandatory style properties that must be applied to the timeline container element. #### `timelineRef` - **timelineRef** (React.MutableRefObject) - Required - The ref for the timeline container element. #### `setTimelineRef` - **setTimelineRef** (function) - Required - A ref setter that must be passed to the timeline's container element. Accepts an `HTMLElement | null`. ### Helper Functions #### `valueToPixels` - **valueToPixels** (function) - Required - Receives a value (number) and returns its pixel representation relative to the timeline's container. Useful for inferring element sizes and positions. #### `pixelsToValue` - **pixelsToValue** (function) - Required - Receives a pixel value (number) and returns its equivalent duration relative to the timeline's container. Useful for converting pixel measurements to values. #### `getValueFromScreenX` - **getValueFromScreenX** (function) - Required - Receives an x-coordinate (number) on the client's screen and returns a date representation relative to the timeline's container. Useful for inferring time values from mouse events. #### `getDeltaXFromScreenX` - **getDeltaXFromScreenX** (function) - Required - Receives an x-coordinate (number) on the client's screen and returns the delta X distance from the timeline's start. Useful for inferring relative positions for custom items. #### `getSpanFromDragEvent` - **getSpanFromDragEvent** (function) - Required - Extracts span information from a drag event (DragStartEvent, DragEndEvent, DragCancelEvent, DragMoveEvent). Injected into dnd-kit events. #### `getSpanFromResizeEvent` - **getSpanFromResizeEvent** (function) - Required - Extracts span information from a resize event (ResizeStartEvent, ResizeMoveEvent, ResizeEndEvent). Injected into dnd-timeline resize events. ### Request Example ```typescript const { style, timelineRef, setTimelineRef, valueToPixels, pixelsToValue, getValueFromScreenX, getDeltaXFromScreenX, getSpanFromDragEvent, getSpanFromResizeEvent } = useTimelineContext(); // Example usage of setTimelineRef
{/* Timeline content */}
// Example usage of valueToPixels const pixels = valueToPixels(100); // Example usage of getSpanFromDragEvent const onDragEnd = (event: DragEndEvent) => { const updatedSpan = event.active.data.current.getSpanFromDragEvent?.(event); // update your state using the updated span }; ``` ### Response #### Success Response (200) - **style** (CSSProperties) - Style properties for the timeline container. - **timelineRef** (React.MutableRefObject) - Ref object for the timeline container. - **setTimelineRef** (function) - Function to set the timeline container ref. - **valueToPixels** (function) - Converts timeline values to pixels. - **pixelsToValue** (function) - Converts pixels to timeline values. - **getValueFromScreenX** (function) - Gets timeline value from screen X coordinate. - **getDeltaXFromScreenX** (function) - Gets delta X distance from screen X coordinate. - **getSpanFromDragEvent** (function) - Extracts span from drag events. - **getSpanFromResizeEvent** (function) - Extracts span from resize events. #### Response Example ```json { "style": { "width": "100%", "height": "500px" }, "timelineRef": { "current": "
" }, "setTimelineRef": "function", "valueToPixels": "function", "pixelsToValue": "function", "getValueFromScreenX": "function", "getDeltaXFromScreenX": "function", "getSpanFromDragEvent": "function", "getSpanFromResizeEvent": "function" } ``` ``` -------------------------------- ### useItem Hook Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/item/useitem.md The useItem hook is used to declare an HTML element as an item within a timeline. It accepts various options to configure the item's behavior and appearance. ```APIDOC ## useItem Hook ### Description A hook to declare a timeline item. Use this hook to declare an HTML element as an item in the timeline. ### Options #### `id` - **id** (string) - Required - A unique id to identify this item. #### `span` - **span** (Span) - Required - An object representing the start and end values of the item. #### `disabled?` - **disabled** (boolean) - Optional - An optional boolean to disable the interactivity of the item. #### `data?` - **data** (object) - Optional - Custom data that can be passed to the row. This can be passed to rows to identify their type. This type can later be used in the event callbacks to apply different behaviors to different row types. #### `resizeHandleWidth?` - **resizeHandleWidth** (number) - Optional - An optional resize handler width, in pixels. Defaults to the `resizeHandleWidth` provided to the context. Choosing a larger or a smaller `handleWidth` will change the resize action's sensitivity. If set to `0`, resizing will be disabled for the item. ### Events useItem can also receive callbacks, that will be called when the relevant event is triggered. #### `onResizeStart?` - **onResizeStart** ((event: ResizeStartEvent) => void) - Optional - Callback when resizing starts. - `ResizeStartEvent` includes `active` and `direction`. #### `onResizeMove?` - **onResizeMove** ((event: ResizeMoveEvent) => void) - Optional - Callback during resize movement. - `ResizeMoveEvent` includes `active`, `delta`, and `direction`. #### `onResizeEnd?` - **onResizeEnd** ((event: ResizeEndEvent) => void) - Optional - Callback when resizing ends. - `ResizeEndEvent` includes `active`, `delta`, and `direction`. ### API All of dnd-kit [useDraggable](https://docs.dndkit.com/api-documentation/draggable/usedraggable#properties) api are returned as well. #### `itemStyle` - **itemStyle** (CSSProperties) - Basic style properties that must be passed to the item wrapper element. #### `itemContentStyle` - **itemContentStyle** (CSSProperties) - Basic style properties that must be passed to the item's children wrapper element. ### Request Example ```tsx useItem({ id: props.id, span: props.span, data: { type: 'timeline-item' }, onResizeMove: onResizeMove, }) ``` ### Response Example ```json { "itemStyle": { /* CSSProperties */ }, "itemContentStyle": { /* CSSProperties */ } } ``` ``` -------------------------------- ### Throttling Range Updates with useThrottle Hook Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/zoom-and-pan/performance.md Implement throttling to limit the rate at which the range state is updated. This custom `useThrottle` hook ensures that the state only changes at a specified interval, reducing the number of re-renders. Provide the throttled range to the TimelineContext. ```tsx function App() { const [range, setRange] = useState(DEFAULT_TIMEFRAME); const debouncedRange = useThrottle(range, 300); ... return ( ) } ``` -------------------------------- ### Define onResizeMove event handler Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/README.md The active object contains custom data and a getSpanFromResizeEvent function to calculate updated spans. ```tsx onResizeMove?: (event: ResizeMoveEvent) => void ``` ```tsx type ResizeMoveEvent = { active: Omit; delta: { x: number; }; direction: DragDirection; // 'start' | 'end' }; ``` -------------------------------- ### Custom useThrottle Hook Implementation Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/zoom-and-pan/performance.md A custom React hook `useThrottle` that limits the rate at which a value is updated. It uses `useState` and `useRef` with `useEffect` to manage the throttled value and the last update time, ensuring updates occur only after a specified interval. ```tsx export function useThrottle(value: T, interval = 500) { const [throttledValue, setThrottledValue] = useState(value); const lastUpdated = useRef(null); useEffect(() => { const now = Date.now(); if (lastUpdated.current && now >= lastUpdated.current + interval) { lastUpdated.current = now; setThrottledValue(value); } else { const id = window.setTimeout(() => { lastUpdated.current = now; setThrottledValue(value); }, interval); return () => { window.clearTimeout(id) }; } }, [value, interval]); return throttledValue; } ``` -------------------------------- ### Timeline Container Ref Setter Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/usetimelinecontext.md A function to set the ref for the timeline's container element. ```typescript setTimelineRef: (element: HTMLElement | null) => void ``` -------------------------------- ### useRow Hook Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/row/userow.md The useRow hook is used to register a component as a droppable row within the timeline, accepting configuration options and returning style properties. ```APIDOC ## useRow Hook ### Description Registers an HTML element as a row in the timeline. This hook is based on dnd-kit's useDroppable hook. ### Parameters #### Options - **id** (string) - Required - A unique id for this row used to bind items. - **disabled** (boolean) - Optional - Whether the row is disabled. - **data** (object) - Optional - Custom data passed to the row, useful for identifying row types. ### Request Example ```tsx useRow({ id: props.id, data: { type: "timeline-row" }, }); ``` ### Response #### Returned Properties - **rowWrapperStyle** (CSSProperties) - Basic styles for the row container element. - **rowStyle** (CSSProperties) - Basic styles for the row element. - **rowSidebarStyle** (CSSProperties) - Basic styles for the row sidebar element, including width matching the TimelineContext. - **Additional Properties** - All properties returned by dnd-kit's useDroppable hook. ``` -------------------------------- ### Handle range changes Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/README.md Callback used to update the controlled state of the timeline range. ```tsx onRangeChanged: OnRangeChanged; ``` ```tsx type OnRangeChanged = (updateFunction: (prev: Range) => Range) => void; ``` -------------------------------- ### Override Resize Span Strategy Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/README.md Provide a custom callback to override the default behavior of inferring the active item's span during resize interactions. This strategy is used instead of the default when provided. ```typescript getSpanFromResizeEventStrategy?: ( event: ResizeMoveEvent | ResizeEndEvent, timelineBag: TimelineBag, ) => Span | null ``` -------------------------------- ### Declare a Timeline Row with useRow Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/row/userow.md Use this hook to declare an HTML element as a row in the timeline. It requires a unique ID and can optionally include custom data for identification. ```tsx useRow({ id: props.id, data: { type: "timeline-row" }, }); ``` -------------------------------- ### Configure timeline range Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/README.md Defines the viewable range in the timeline as a fully controlled field. ```tsx range: Range; ``` ```tsx type Range = { start: number; end: number; }; ``` -------------------------------- ### Convert Value to Pixels Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/usetimelinecontext.md Converts a given value into its pixel representation relative to the timeline container. Useful for calculating element sizes and positions based on duration. ```typescript valueToPixels: (value: number) => number ``` -------------------------------- ### Define ResizeMoveEvent Type Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/item/useitem.md Type definition for the resize move event callback. ```tsx onResizeMove?: (event: ResizeMoveEvent) => void ``` ```tsx type ResizeMoveEvent = { active: Omit delta: { x: number } direction: DragDirection // 'start' | 'end' } ``` -------------------------------- ### Infer Updated Span from Resize Event Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/README.md During a resize event, utilize the getSpanFromResizeEvent helper function available in event.active.data.current to calculate the item's new span. This ensures accurate state updates for resized items. ```tsx const updatedSpan = event.active.data.current.getSpanFromResizeEvent?.(event) ``` -------------------------------- ### Convert Pixels to Value Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/usetimelinecontext.md Converts a pixel measurement into its equivalent duration value relative to the timeline container. Useful for inferring item spans from their position or width. ```typescript pixelsToValue: (pixels: number) => number ``` -------------------------------- ### Define ResizeEndEvent Type Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/item/useitem.md Type definition for the resize end event callback. ```tsx onResizeMove?: (event: ResizeEndEvent) => void ``` ```tsx type ResizeEndEvent = { active: Omit delta: { x: number } direction: DragDirection // 'start' | 'end' } ``` -------------------------------- ### Rendering Items within a Row Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/item/README.md This React code demonstrates how to render multiple Item components as children of a Row component. It maps over grouped items, passing the necessary id and span props to each Item. ```tsx {groupedItems[row.id].map((item) => // item content... )} ``` -------------------------------- ### Infer Span from Resize Event Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/usetimelinecontext.md Extracts the span of a resized item from a dnd-timeline resize event. This helper is injected into resize events and uses a default strategy, which can be overridden. ```typescript getSpanFromResizeEvent: (event: ResizeEvent) => Span | null ``` ```typescript type ResizeEvent = ResizeStartEvent | ResizeMoveEvent | ResizeEndEvent ``` ```tsx const onResizeEnd = (event: ResizeEndEvent) => { const updatedSpan = event.active.data.current.getSpanFromResizeEvent?.(event) // update your state using the updated span. } ``` -------------------------------- ### Override drag span strategy Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/README.md Provides a custom callback to infer the active item's span during drag interactions. ```tsx getSpanFromDragEventStrategy?: ( event: DragStartEvent | DragMoveEvent | DragEndEvent | DragCancelEvent, timelineBag: TimelineBag, ) => Span | null ``` -------------------------------- ### groupItemsToSubrows API Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/row/subrow.md Details of the `groupItemsToSubrows` utility function, which is crucial for organizing intersecting timeline items into distinct subrows. ```APIDOC ## `groupItemsToSubrows` Utility Function ### Description A helper function designed to group timeline items that have overlapping spans into separate subrows. This function is essential for managing the visual stacking of items within the `dnd-timeline` component. ### Method `groupItemsToSubrows` ### Endpoint N/A (Utility Function) ### Parameters #### `items` - **items** (ItemDefinition[]) - Required - An array of items, each conforming to the `ItemDefinition` type, that need to be grouped. #### `range?` - **range** (Span) - Optional - An optional `Span` object. If provided, the function will only consider items that intersect with this range, aiding in performance optimization. ### Request Body N/A ### Response - **Record** - An object where keys are `rowId`s and values are 2D arrays of `ItemDefinition`. The outer array represents subrows, and the inner array contains items within each subrow. ### Response Example ```json { "row-1": [ [ { "id": "item-1", "rowId": "row-1", "span": { "start": 10, "end": 20 } }, { "id": "item-2", "rowId": "row-1", "span": { "start": 15, "end": 25 } } ], [ { "id": "item-3", "rowId": "row-1", "span": { "start": 30, "end": 40 } } ] ], "row-2": [ [ { "id": "item-4", "rowId": "row-2", "span": { "start": 5, "end": 15 } } ] ] } ``` ### ItemDefinition Type ```typescript type ItemDefinition = { id: string; rowId: string; span: Span; disabled?: boolean; } ``` ### Span Type ```typescript type Span = { start: number; end: number; } ``` ``` -------------------------------- ### Define Item Data Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/item/useitem.md Custom data object for identifying item types or other metadata. ```tsx data?: object ``` -------------------------------- ### Define Item Disabled State Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/item/useitem.md Optional boolean to disable item interactivity. ```tsx disabled?: boolean ``` -------------------------------- ### Extend RowDefinition type Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/row/README.md Helper type provided by dnd-timeline to define the structure of a row. ```typescript type RowDefinition = { id: string; disabled?: boolean; }; ``` -------------------------------- ### Define Item ID Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/item/useitem.md Unique identifier for the timeline item. ```tsx id: string ``` -------------------------------- ### groupItemsToSubrows API Definition Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/row/subrow.md Signature for the utility function that groups items by rowId and subrow index. ```tsx groupItemsToSubrows: (items: ItemDefinition[], range?: Span) => Record ``` -------------------------------- ### Infer Span from Drag Event Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/usetimelinecontext.md Extracts the span of a dragged item from a dnd-kit drag event. This helper is injected into drag events and uses a default strategy, which can be overridden. ```typescript getSpanFromDragEvent: (event: DragEvent) => Span | null ``` ```typescript type DragEvent = DragStartEvent | DragEndEvent | DragCancelEvent | DragMoveEvent ``` ```tsx const onDragEnd = (event: DragEndEvent) => { const updatedSpan = event.active.data.current.getSpanFromDragEvent?.(event) // update your state using the updated span. } ``` -------------------------------- ### Infer Updated Span from Drag Event Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/timelinecontext/README.md When a drag event ends, use the provided getSpanFromDragEvent helper function from event.active.data.current to accurately determine the item's updated span. Avoid manual span calculation. ```tsx const onDragEnd = (event: DragEndEvent) => { const overedId = event.over?.id.toString() if (!overedId) return const activeItemId = event.active.id const updatedSpan = event.active.data.current.getSpanFromDragEvent?.(event) // update your state using the updated span. } ``` -------------------------------- ### Deferring Range Updates with useDeferredValue Source: https://github.com/samuelarbibe/dnd-timeline/blob/main/docs/v3/documentation/zoom-and-pan/performance.md Use `useDeferredValue` from React 18+ to defer UI updates when the range changes. This hook helps prevent stuttering and frame drops during frequent state changes like zooming or panning. Provide the debounced range to the TimelineContext. ```tsx function App() { const [range, setRange] = useState(DEFAULT_TIMEFRAME); const debouncedRange = useDeferredValue(range); ... return ( ) } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.