### 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 (
)
}
```
--------------------------------
### 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.