@getsoren/design-system 4.48.1 → 4.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ import { SvgIconProps } from '@mui/material/SvgIcon';
2
+ declare const KeyboardArrowLeftRoundedIcon: (props: SvgIconProps) => import("@emotion/react/jsx-runtime").JSX.Element;
3
+ export default KeyboardArrowLeftRoundedIcon;
@@ -0,0 +1,3 @@
1
+ import { SvgIconProps } from '@mui/material/SvgIcon';
2
+ declare const KeyboardArrowRightRoundedIcon: (props: SvgIconProps) => import("@emotion/react/jsx-runtime").JSX.Element;
3
+ export default KeyboardArrowRightRoundedIcon;
@@ -0,0 +1,3 @@
1
+ import { SvgIconProps } from '@mui/material/SvgIcon';
2
+ declare const KeyboardDoubleArrowLeftRoundedIcon: (props: SvgIconProps) => import("@emotion/react/jsx-runtime").JSX.Element;
3
+ export default KeyboardDoubleArrowLeftRoundedIcon;
@@ -0,0 +1,3 @@
1
+ import { SvgIconProps } from '@mui/material/SvgIcon';
2
+ declare const KeyboardDoubleArrowRightRoundedIcon: (props: SvgIconProps) => import("@emotion/react/jsx-runtime").JSX.Element;
3
+ export default KeyboardDoubleArrowRightRoundedIcon;
@@ -0,0 +1,3 @@
1
+ import { PlanningTimelineProps, PlanningTimelineTask } from './types';
2
+ declare const PlanningTimeline: <T extends PlanningTimelineTask>({ tasks, isLoading, onClick, onBarResize, renderRow, renderBar, renderTooltip, isTaskSelected, recenterKey, sidebarTitle, locale, labels, defaultViewMode, localStorageKeys, sidebarWidth, rowHeight, }: PlanningTimelineProps<T>) => import("@emotion/react/jsx-runtime").JSX.Element;
3
+ export default PlanningTimeline;
@@ -0,0 +1,47 @@
1
+ import { ReactNode } from 'react';
2
+ import { PlanningTimelineBarContext, PlanningTimelineTask } from '../types';
3
+ import { TimeScale } from '../utils/timeScale';
4
+ interface TaskBarProps<T extends PlanningTimelineTask> {
5
+ /**
6
+ * The task row this bar represents — its start/end drive the bar geometry, its statusColor the
7
+ * hue, and its overdue/plannedEnd/incidents the hatched overlays.
8
+ */
9
+ task: T;
10
+ /**
11
+ * The active time scale — converts the task dates to px (position/width) and the dragged px back
12
+ * to a date on resize.
13
+ */
14
+ scale: TimeScale;
15
+ /**
16
+ * Row height in px; the bar fills it minus a vertical padding.
17
+ */
18
+ rowHeight: number;
19
+ /**
20
+ * Whether the left column is collapsed — forwarded to `renderBar` so the bar can surface the
21
+ * identity the sidebar no longer shows.
22
+ */
23
+ sidebarCollapsed: boolean;
24
+ /**
25
+ * Highlight the bar (e.g. its detail view is open).
26
+ */
27
+ selected?: boolean;
28
+ /**
29
+ * Click on the bar (not fired for the click ending a resize).
30
+ */
31
+ onClick?: (task: T) => void;
32
+ /**
33
+ * Drag of the right-edge handle committed — `newEnd` is the date matching the new width. Omitting
34
+ * it hides the handle and disables resizing.
35
+ */
36
+ onBarResize?: (task: T, newEnd: Date) => void;
37
+ /**
38
+ * Inner content of the bar.
39
+ */
40
+ renderBar?: (task: T, context: PlanningTimelineBarContext) => ReactNode;
41
+ /**
42
+ * Content of the tooltip shown while hovering the bar; nothing is shown when omitted.
43
+ */
44
+ renderTooltip?: (task: T) => ReactNode;
45
+ }
46
+ declare const TaskBar: <T extends PlanningTimelineTask>({ task, scale, rowHeight, sidebarCollapsed, selected, onClick, onBarResize, renderBar, renderTooltip, }: TaskBarProps<T>) => import("@emotion/react/jsx-runtime").JSX.Element;
47
+ export default TaskBar;
@@ -0,0 +1,20 @@
1
+ import { TimeScale } from '../utils/timeScale';
2
+ interface TimelineHeaderProps {
3
+ /**
4
+ * The active time scale (range, zoom, ticks) — the header draws one cell per minor/major tick and
5
+ * positions them with its px converters.
6
+ */
7
+ scale: TimeScale;
8
+ /**
9
+ * Total header height in px, split in two: major groupings (month/year) on the top half, minor
10
+ * cells (day/week/month) on the bottom half.
11
+ */
12
+ height: number;
13
+ /**
14
+ * The focus date (from the toolbar nav) — its minor cell is emphasised so navigation is visible.
15
+ */
16
+ selectedDate?: Date;
17
+ }
18
+ /** Two-tier time axis: major groupings (month/year) on top, minor cells (day/week/month) below. */
19
+ declare const TimelineHeader: ({ scale, height, selectedDate }: TimelineHeaderProps) => import("@emotion/react/jsx-runtime").JSX.Element;
20
+ export default TimelineHeader;
@@ -0,0 +1,24 @@
1
+ import { PointerEvent as ReactPointerEvent } from 'react';
2
+ interface UseBarDragOptions {
3
+ /** Called on pointer-up with the horizontal drag distance in px (only when it actually moved). */
4
+ onCommit: (deltaPx: number) => void;
5
+ disabled?: boolean;
6
+ }
7
+ interface UseBarDragResult {
8
+ /** Live horizontal delta (px) while dragging, 0 otherwise — add it to the bar width for a live preview. */
9
+ deltaPx: number;
10
+ dragging: boolean;
11
+ /** Spread onto the right-edge drag handle element. */
12
+ handleProps: {
13
+ onPointerDown: (event: ReactPointerEvent) => void;
14
+ onPointerMove: (event: ReactPointerEvent) => void;
15
+ onPointerUp: (event: ReactPointerEvent) => void;
16
+ onPointerCancel: (event: ReactPointerEvent) => void;
17
+ };
18
+ }
19
+ /**
20
+ * Native pointer-events drag for resizing a bar's right edge. Uses setPointerCapture so the gesture
21
+ * keeps tracking even when the pointer leaves the thin handle — no third-party drag lib needed.
22
+ */
23
+ export declare const useBarDrag: ({ onCommit, disabled }: UseBarDragOptions) => UseBarDragResult;
24
+ export {};
@@ -0,0 +1,98 @@
1
+ import { ReactNode } from 'react';
2
+ import { ViewMode } from './utils/timeScale';
3
+ export type PlanningTimelineViewMode = ViewMode;
4
+ export type PlanningTimelineTaskType = "task" | "project";
5
+ /** MUI palette color driving a bar's hue; "default" renders muted (grey). */
6
+ export type PlanningTimelineStatusColor = "default" | "error" | "info" | "success" | "warning";
7
+ /** An incident (e.g. a breakdown) rendered as a hatched day-wide segment on the bar. */
8
+ export interface PlanningTimelineIncident {
9
+ incidentDate: string | Date;
10
+ }
11
+ /**
12
+ * A timeline row. A "project" row is a group header (collapsible), a "task" row is a bar on the
13
+ * time axis. Extend this interface to attach your own domain data and get it back, typed, in every
14
+ * render prop and callback.
15
+ */
16
+ export interface PlanningTimelineTask {
17
+ id: string;
18
+ type: PlanningTimelineTaskType;
19
+ name: string;
20
+ start: Date;
21
+ end: Date;
22
+ /** For project rows: whether its children rows are collapsed. */
23
+ hideChildren?: boolean;
24
+ /** For task rows: id of the parent project (group) row. */
25
+ project?: string;
26
+ /** Incidents rendered as red hatched day-wide segments on the bar. */
27
+ incidents?: PlanningTimelineIncident[];
28
+ /** Original planned end (before any overdue extension of `end`). */
29
+ plannedEnd?: Date;
30
+ /** Task past its planned end — the segment `plannedEnd` → `end` is hatched in warning. */
31
+ overdue?: boolean;
32
+ /** MUI palette color of the bar. @default "default" */
33
+ statusColor?: PlanningTimelineStatusColor;
34
+ /** For project (group header) rows: number of task rows in the group. */
35
+ childCount?: number;
36
+ /** For project rows: the group's data is being fetched. */
37
+ loading?: boolean;
38
+ }
39
+ /** Context given to `renderRow` for a left-column cell. */
40
+ export interface PlanningTimelineRowContext<T extends PlanningTimelineTask = PlanningTimelineTask> {
41
+ /** Forwarded `onClick` — call it to make the whole cell clickable like the bar. */
42
+ onJump: (task: T) => void;
43
+ selected: boolean;
44
+ sidebarCollapsed: boolean;
45
+ }
46
+ /** Context given to `renderBar` for a bar's inner content. */
47
+ export interface PlanningTimelineBarContext {
48
+ sidebarCollapsed: boolean;
49
+ }
50
+ /** localStorage keys used to persist the timeline UI preferences. */
51
+ export interface PlanningTimelineLocalStorageKeys {
52
+ /** Key storing the selected view mode. @default "soren-planning-timeline-view-mode" */
53
+ viewMode: string;
54
+ }
55
+ /** Built-in UI strings; each falls back to the design-system locale (en/fr) when not overridden. */
56
+ export interface PlanningTimelineLabels {
57
+ day: string;
58
+ week: string;
59
+ month: string;
60
+ year: string;
61
+ today: string;
62
+ noResult: string;
63
+ }
64
+ export interface PlanningTimelineProps<T extends PlanningTimelineTask = PlanningTimelineTask> {
65
+ tasks?: T[];
66
+ isLoading?: boolean;
67
+ /** Click a bar — e.g. open the row's detail view. */
68
+ onClick?: (task: T) => void;
69
+ /** Drag the right edge of a bar — extend the task to `newEnd`. Omit to disable resizing. */
70
+ onBarResize?: (task: T, newEnd: Date) => void;
71
+ /** Left-column cell renderer (group header or task row). Defaults to the task name. */
72
+ renderRow?: (task: T, context: PlanningTimelineRowContext<T>) => ReactNode;
73
+ /** Inner content of a bar. Defaults to the task name. */
74
+ renderBar?: (task: T, context: PlanningTimelineBarContext) => ReactNode;
75
+ renderTooltip?: (task: T) => ReactNode;
76
+ /** Whether a task row is the currently selected one (e.g. its detail view is open). */
77
+ isTaskSelected?: (task: T) => boolean;
78
+ /** Opaque value that changes when filters change — the timeline re-centres on today when it does. */
79
+ recenterKey?: string;
80
+ /** Title of the left (frozen) column, also used as the collapse button tooltip. */
81
+ sidebarTitle?: string;
82
+ /** BCP 47 locale for the axis and toolbar date labels (e.g. "fr"). @default "en" */
83
+ locale?: string;
84
+ /** Override the built-in labels (e.g. to plug the host app's i18n). */
85
+ labels?: Partial<PlanningTimelineLabels>;
86
+ /** Initial zoom level, when none is persisted yet. @default "day" */
87
+ defaultViewMode?: PlanningTimelineViewMode;
88
+ /**
89
+ * localStorage keys used to persist UI preferences. Override them to namespace the keys per
90
+ * screen/app so timelines don't share their saved view.
91
+ * @default { viewMode: "soren-planning-timeline-view-mode" }
92
+ */
93
+ localStorageKeys?: Partial<PlanningTimelineLocalStorageKeys>;
94
+ /** Width (px) of the left column. @default 300 */
95
+ sidebarWidth?: number;
96
+ /** Height (px) of every row. @default 56 */
97
+ rowHeight?: number;
98
+ }
@@ -0,0 +1,77 @@
1
+ /** Zoom level of the timeline. Each mode is just a different px-per-day and tick granularity. */
2
+ export type ViewMode = "day" | "week" | "month" | "year";
3
+ export declare const MS_PER_DAY: number;
4
+ /**
5
+ * Horizontal zoom per mode. Bar geometry is always computed in px-per-day, so switching mode only
6
+ * rescales the same linear axis — it never changes the bar maths (avoids variable-width month columns).
7
+ */
8
+ export declare const PX_PER_DAY: Record<ViewMode, number>;
9
+ export interface DateRange {
10
+ start: Date;
11
+ end: Date;
12
+ }
13
+ /** A single header cell (a day/week/month for the minor row, a month/year for the major row). */
14
+ export interface Tick {
15
+ key: string;
16
+ /** Left offset in px from the range start. */
17
+ x: number;
18
+ /** Cell width in px. */
19
+ width: number;
20
+ label: string;
21
+ }
22
+ export interface TimeScale {
23
+ mode: ViewMode;
24
+ rangeStart: Date;
25
+ rangeEnd: Date;
26
+ pxPerDay: number;
27
+ /** Total timeline width in px. */
28
+ width: number;
29
+ /** Map a date to its x offset (px) from the range start. */
30
+ dateToX: (date: Date | number) => number;
31
+ /** Inverse of `dateToX`. */
32
+ xToDate: (x: number) => Date;
33
+ ticks: {
34
+ minor: Tick[];
35
+ major: Tick[];
36
+ };
37
+ }
38
+ /** Local-midnight start of the given day. */
39
+ export declare const startOfDay: (date: Date | number) => Date;
40
+ /** Last millisecond of the given day (23:59:59.999, local time). */
41
+ export declare const endOfDay: (date: Date | number) => Date;
42
+ export declare const startOfMonth: (date: Date | number) => Date;
43
+ export declare const startOfYear: (date: Date | number) => Date;
44
+ export declare const addDays: (date: Date | number, days: number) => Date;
45
+ /** Add calendar months, clamping to the last day of the target month (Jan 31 + 1 month → Feb 28/29). */
46
+ export declare const addMonths: (date: Date | number, months: number) => Date;
47
+ /** Step a date by one `mode` unit (toolbar prev/next arrows). */
48
+ export declare const addViewModeStep: (date: Date, direction: 1 | -1, mode: ViewMode) => Date;
49
+ /** Toolbar label for the focused date: "05 Jan 2026" (day/week), "January 2026" (month), "2026" (year). */
50
+ export declare const formatViewDateLabel: (date: Date, mode: ViewMode, locale?: string) => string;
51
+ /**
52
+ * Compute the visible date span: from the earliest start to the latest end, padded on both sides.
53
+ * The end always keeps at least `horizonMonths` of runway after today, so a rental can be dragged /
54
+ * extended well into the future even when every loaded booking ends sooner. Invalid dates (NaN) are
55
+ * ignored — a single corrupt row must not poison the whole axis. Falls back to a window around today
56
+ * when no valid date remains.
57
+ */
58
+ export declare const computeRange: (tasks: {
59
+ start: Date;
60
+ end: Date;
61
+ }[], padDays?: number, horizonMonths?: number) => DateRange;
62
+ /** Map a date to its x offset (px) from `rangeStart`, at ms precision. */
63
+ export declare const dateToX: (date: Date | number, rangeStart: Date | number, pxPerDay: number) => number;
64
+ /** Inverse of `dateToX`: map an x offset (px) back to a date. */
65
+ export declare const xToDate: (x: number, rangeStart: Date | number, pxPerDay: number) => Date;
66
+ /** Snap a date to the nearest day boundary (midnight) — used when committing a dragged bar end. */
67
+ export declare const snapDateToDay: (date: Date | number) => Date;
68
+ /** Build the two-tier header ticks (minor cells + their major groupings) for the given range and mode. */
69
+ export declare const getTicks: (rangeStart: Date, rangeEnd: Date, mode: ViewMode, locale?: string) => {
70
+ minor: Tick[];
71
+ major: Tick[];
72
+ };
73
+ /** Build the full scale (range, zoom, width, converters, ticks) for a set of rows in a given mode. */
74
+ export declare const createTimeScale: (tasks: {
75
+ start: Date;
76
+ end: Date;
77
+ }[], mode: ViewMode, locale?: string, padDays?: number) => TimeScale;
@@ -1,8 +1,14 @@
1
1
  declare const _default: {
2
2
  apply: string;
3
3
  clickToUpload: string;
4
+ day: string;
4
5
  files: string;
6
+ month: string;
7
+ noResult: string;
5
8
  reset: string;
6
9
  selectAll: string;
10
+ today: string;
11
+ week: string;
12
+ year: string;
7
13
  };
8
14
  export default _default;
@@ -1,8 +1,14 @@
1
1
  declare const _default: {
2
2
  apply: string;
3
3
  clickToUpload: string;
4
+ day: string;
4
5
  files: string;
6
+ month: string;
7
+ noResult: string;
5
8
  reset: string;
6
9
  selectAll: string;
10
+ today: string;
11
+ week: string;
12
+ year: string;
7
13
  };
8
14
  export default _default;
@@ -27,6 +27,8 @@ export * from './components/DataDisplay/ListItemCard';
27
27
  export { default as ListItemCard } from './components/DataDisplay/ListItemCard';
28
28
  export * from './components/DataDisplay/Logo';
29
29
  export { default as Logo } from './components/DataDisplay/Logo';
30
+ export { default as PlanningTimeline } from './components/DataDisplay/PlanningTimeline/PlanningTimeline';
31
+ export * from './components/DataDisplay/PlanningTimeline/types';
30
32
  export * from './components/DataDisplay/StatusIcon';
31
33
  export { default as StatusIcon } from './components/DataDisplay/StatusIcon';
32
34
  export * from './components/DataDisplay/TimeLine';
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@getsoren/design-system",
3
3
  "description": "Design System React library",
4
4
  "sideEffects": false,
5
- "version": "4.48.1",
5
+ "version": "4.49.0",
6
6
  "license": "ISC",
7
7
  "type": "module",
8
8
  "types": "./dist/src/main.d.ts",