UNPKG

@navikt/ds-react

Version:

React components from the Norwegian Labour and Welfare Administration.

155 lines 7.37 kB
var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; import { endOfDay, isSameDay, startOfDay } from "date-fns"; import React, { forwardRef, useMemo, useRef, useState } from "react"; import { useRenameCSS } from "../theme/Theme.js"; import { AxisLabels } from "./AxisLabels.js"; import TimelineRow from "./TimelineRow.js"; import { RowContext } from "./hooks/useRowContext.js"; import { TimelineContext } from "./hooks/useTimelineContext.js"; import { useEarliestDate, useLatestDate, useTimelineRows, } from "./hooks/useTimelineRows.js"; import Period from "./period/index.js"; import Pin from "./pin/Pin.js"; import { parseRows } from "./utils/timeline.js"; import Zoom from "./zoom/index.js"; /** * A component that displays a timeline of events. Meant for Internal systems. * * Component is made for desktop enviroments and will start having issues on smaller screens. * * @see [📝 Documentation](https://aksel.nav.no/komponenter/core/timeline) * @see 🏷️ {@link TimelineProps} * * @example * ```jsx * <Timeline> * <Timeline.Row> * <Timeline.Period start={new Date("2020-01-01")} end={new Date("2020-01-31")}> * <p>Period 1</p> * </Timeline.Period> * <Timeline.Row> * </Timeline> * ``` */ export const Timeline = forwardRef((_a, ref) => { var { children, startDate, endDate, direction = "left", axisLabelTemplates } = _a, rest = __rest(_a, ["children", "startDate", "endDate", "direction", "axisLabelTemplates"]); const { cn } = useRenameCSS(); const isMultipleRows = Array.isArray(children); const firstFocusabled = useRef([]); if (!isMultipleRows) { children = [children]; } const rowChildren = React.Children.toArray(children).filter((c) => { var _a; return ((_a = c === null || c === void 0 ? void 0 : c.type) === null || _a === void 0 ? void 0 : _a.componentType) === "row"; }); const pins = React.Children.toArray(children) .filter((c) => { var _a; return ((_a = c === null || c === void 0 ? void 0 : c.type) === null || _a === void 0 ? void 0 : _a.componentType) === "pin"; }) .map((x) => () => x); const zoomComponent = React.Children.toArray(children).find((c) => { var _a; return ((_a = c === null || c === void 0 ? void 0 : c.type) === null || _a === void 0 ? void 0 : _a.componentType) === "zoom"; }); const rowsRaw = useMemo(() => { return parseRows(rowChildren); }, [rowChildren]); const rows = rowsRaw.map((r) => { if (r === null || r === void 0 ? void 0 : r.periods) { return r.periods; } return []; }); const initialStartDate = startOfDay(useEarliestDate({ startDate, rows })); const [start, setStart] = useState(initialStartDate); const [activeRow, setActiveRow] = useState(null); const [endInclusive, setEndInclusive] = useState(endOfDay(useLatestDate({ endDate, rows }))); const initialEndDate = endOfDay(useLatestDate({ endDate, rows })); const processedRows = useTimelineRows(rowsRaw, startDate !== null && startDate !== void 0 ? startDate : start, endDate !== null && endDate !== void 0 ? endDate : endInclusive, direction); const handleZoomChange = (zoomStart) => { if (startDate || endDate) { if (process.env.NODE_ENV !== "production") { console.warn("Zooming is not supported when startDate or endDate is set"); } return; } if (direction === "left") { if (isSameDay(zoomStart, start)) { setStart(initialStartDate); return; } setStart(zoomStart); } else { if (isSameDay(zoomStart, endInclusive)) { setEndInclusive(initialEndDate); return; } setEndInclusive(zoomStart); } }; const handleActiveRowChange = (key) => { var _a, _b, _c, _d; if (activeRow !== null && key === "ArrowDown") { for (let i = activeRow + 1; i < processedRows.length; i++) { const row = processedRows[i]; if (row.periods.find((p) => !!p.children || !!p.onSelectPeriod)) { setActiveRow(i); (_b = (_a = firstFocusabled.current.find((x) => x.id === i)) === null || _a === void 0 ? void 0 : _a.ref) === null || _b === void 0 ? void 0 : _b.focus(); break; } } return; } if (activeRow !== null && key === "ArrowUp") { for (let i = activeRow - 1; i >= 0; i--) { const row = processedRows[i]; if (row.periods.find((p) => !!p.children || !!p.onSelectPeriod)) { setActiveRow(i); (_d = (_c = firstFocusabled.current.find((x) => x.id === i)) === null || _c === void 0 ? void 0 : _c.ref) === null || _d === void 0 ? void 0 : _d.focus(); break; } } return; } }; const addFocusable = (btnRef, id) => { let items = firstFocusabled.current; items = items.filter((x) => x.id !== id); items.push({ ref: btnRef, id }); firstFocusabled.current = items; }; return (React.createElement(TimelineContext.Provider, { value: { startDate: startDate !== null && startDate !== void 0 ? startDate : start, endDate: endDate !== null && endDate !== void 0 ? endDate : endInclusive, direction, setStart: (d) => handleZoomChange(d), setEndInclusive: (d) => setEndInclusive(d), activeRow, setActiveRow: (key) => handleActiveRowChange(key), initiate: (i) => setActiveRow(i), addFocusable, } }, React.createElement("div", Object.assign({}, rest, { ref: ref }), React.createElement("div", { className: cn("navds-timeline") }, React.createElement(AxisLabels, { templates: axisLabelTemplates }), pins.map((PinChild, i) => (React.createElement(PinChild, { key: `pin-${i}` }))), processedRows.map((row, i) => { return (React.createElement(RowContext.Provider, { key: `row-${row.id}`, value: { periods: row.periods, id: row.id, active: activeRow === i, index: i, } }, React.createElement(TimelineRow, Object.assign({}, row === null || row === void 0 ? void 0 : row.restProps, { ref: row === null || row === void 0 ? void 0 : row.ref, label: row.label, icon: row.icon, headingTag: row.headingTag })))); })), zoomComponent))); }); Timeline.Row = TimelineRow; Timeline.Period = Period; Timeline.Pin = Pin; Timeline.Zoom = Zoom; export default Timeline; //# sourceMappingURL=Timeline.js.map