Planner
@spartanfx/react / Planner
Variable: Planner
constPlanner:React.FC<IPlannerProps>
High-level timeline planner component with drag-and-drop support.
Remarks
The Planner accepts raw data as an array of Record<string, unknown> items together with
an IPlannerSchema that describes how each raw record maps to the internal planner
item properties (id, title, start/end dates, group, color, etc.). The component transforms
the raw items into IPlannerItem entries internally — consumers never need to build
IPlannerItem objects themselves.
- Initializes and sorts items on load and whenever
props.itemsor color filters change. - Automatically computes the visible month range from
options.startDateandoptions.endDate. - When
containerWidthis not provided, the component measures the parent element and subtracts horizontal padding to determine the planner width. - View navigation (
week/month/year) updatesonPlannerDatesChangedwith computed date ranges based on the selected period. - Drag-and-drop behavior is enabled by the React DnD provider. If
options.callBacks.onItemChangeis supplied, drops will emit a change payload (create/update/delete) for the consumer to persist. - A contextual menu is conditionally populated based on which callbacks are provided in
options.callBacks, and whether the context targets a range child item.
Examples
import * as React from "react";
import { Planner } from "./Planner";
import { ViewBy, PeriodCount, IPlannerSchema } from "./types/plannerTypes";
const schema: IPlannerSchema = {
idField: { fieldName: "Id" },
titleField: { fieldName: "Title" },
startDateField: { fieldName: "StartDate" },
endDateField: { fieldName: "EndDate" },
groupField: { fieldName: "Department" },
};
export function MinimalPlanner() {
return (
<Planner
items={[]}
schema={schema}
options={{
startDate: new Date(2025, 0, 1),
endDate: new Date(2025, 11, 31),
callBacks: {},
}}
viewBy={ViewBy.month}
periodCount={PeriodCount.one}
/>
);
}
import * as React from "react";
import { Planner } from "./Planner";
import { ViewBy, PeriodCount, IPlannerSchema } from "./types/plannerTypes";
// Define the schema to map raw item fields to planner item properties.
const schema: IPlannerSchema = {
idField: { fieldName: "Id" },
titleField: { fieldName: "Title" },
startDateField: { fieldName: "StartDate" },
endDateField: { fieldName: "EndDate" },
groupField: { fieldName: "Department" },
descriptionField: { fieldName: "Notes" },
colorField: { fieldName: "Status" },
rangeGroupField: { fieldName: "ProjectId" },
durationField: { fieldName: "DurationDays" },
};
// Raw items — each record's keys must match the fieldName values in the schema.
const items: Array<Record<string, unknown>> = [
{
Id: 1,
Title: "Kickoff",
StartDate: new Date(2025, 0, 6),
EndDate: new Date(2025, 0, 10),
Department: "Engineering",
Notes: "Project kickoff meeting",
Status: "active",
ProjectId: "A",
DurationDays: 5,
},
{
Id: 2,
Title: "Design Phase",
StartDate: new Date(2025, 0, 13),
EndDate: new Date(2025, 0, 24),
Department: "Engineering",
Notes: "UI/UX design iteration",
Status: "pending",
ProjectId: "A",
DurationDays: 12,
},
];
export function AdvancedPlanner() {
const [currentMonth, setCurrentMonth] = React.useState(0);
return (
<Planner
className="myPlanner"
items={items}
schema={schema}
grouped
allowDragDrop
allowViewByWeek
allowViewByYear
allowPeriodCountSelection
maxPeriodCount={PeriodCount.three}
currentMonth={currentMonth}
onChangeCurrentMonth={setCurrentMonth}
onPlannerDatesChanged={(start, end) => {
console.log("Planner range changed:", start, end);
}}
options={{
startDate: new Date(2025, 0, 1),
endDate: new Date(2025, 11, 31),
callBacks: {
onItemChange: (change) => console.log("Item change:", change),
onMoveItemClick: (item) => console.log("Move item:", item),
onDuplicateItemClick: (item) => console.log("Duplicate item:", item),
onReAssignItemClick: (item) => console.log("Reassign item:", item),
onAddNewClick: () => console.log("Add new"),
},
}}
viewBy={ViewBy.month}
periodCount={PeriodCount.one}
showLegend
colorMapping={{ active: "green", pending: "orange" }}
/>
);
}
// When raw item fields need transformation (e.g., nested objects or
// different date formats), use the onGetData callback in the schema field.
const schema: IPlannerSchema = {
idField: { fieldName: "id" },
titleField: { fieldName: "attributes", onGetData: (item) => item.attributes?.name },
startDateField: { fieldName: "start", onGetData: (item) => new Date(item.start) },
endDateField: { fieldName: "end", onGetData: (item) => new Date(item.end) },
groupField: { fieldName: "team" },
};
Param
Configuration and data for the planner surface.
Returns
The planner UI, including optional legend, drag-and-drop provider, and contextual menu.