@trackunit/react-date-and-time-components 1.0.16 → 1.0.18

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.
package/index.cjs.js CHANGED
@@ -388,9 +388,18 @@ const Timeline = ({ className, dataTestId, children, dateHeader, customHeader, t
388
388
  const childProps = React.isValidElement(firstChild) ? firstChild.props : {};
389
389
  const lastChild = remainingChildren.pop();
390
390
  const middleChildren = remainingChildren;
391
+ React.useEffect(() => {
392
+ // Set maxHeight dynamically for smooth animation
393
+ if (ref.current) {
394
+ ref.current.style.maxHeight = isOpen ? `${ref.current.scrollHeight}px` : "0px";
395
+ }
396
+ }, [isOpen]);
391
397
  const renderToggleButton = () => (jsxRuntime.jsxs("div", { className: cvaTimelineElement(), children: [childProps?.date ? (jsxRuntime.jsx("div", { className: cvaTimelineElementTime({
392
398
  width: hourCycle === "h12" || hourCycle === "h11" ? "large" : "small",
393
- }) })) : null, jsxRuntime.jsx("div", { className: cvaDotWrapper(), children: jsxRuntime.jsx("div", { className: cvaLine({ lineStyle: childProps?.lineStyle }) }) }), jsxRuntime.jsxs("div", { className: "flex text-sm text-secondary-500 cursor-pointer items-center min-h-8 hover:text-secondary-600", "data-testid": "timeline-toggle-btn", onClick: () => setIsOpen(!isOpen), children: [jsxRuntime.jsx(reactComponents.Icon, { className: cvaToggleBtnIcon({ rotated: isOpen }), name: "ChevronDown", size: "small" }), jsxRuntime.jsx("span", { children: isOpen ? toggleButton?.collapsedLabel : toggleButton?.expandedLabel })] })] }));
399
+ }) })) : null, jsxRuntime.jsx("div", { className: cvaDotWrapper(), children: jsxRuntime.jsx("div", { className: cvaLine({ lineStyle: childProps?.lineStyle }) }) }), jsxRuntime.jsxs("div", { className: "text-secondary-500 hover:text-secondary-600 flex min-h-8 cursor-pointer items-center text-sm", "data-testid": "timeline-toggle-btn", onClick: () => {
400
+ toggleButton?.onClick && toggleButton.onClick();
401
+ setIsOpen(!isOpen);
402
+ }, children: [jsxRuntime.jsx(reactComponents.Icon, { className: cvaToggleBtnIcon({ rotated: isOpen }), name: "ChevronDown", size: "small" }), jsxRuntime.jsx("span", { children: isOpen ? toggleButton?.collapsedLabel : toggleButton?.expandedLabel })] })] }));
394
403
  const renderDateHeader = () => {
395
404
  if (!dateHeader) {
396
405
  return null;
@@ -401,7 +410,7 @@ const Timeline = ({ className, dataTestId, children, dateHeader, customHeader, t
401
410
  const { date, dateRange, showTime } = dateHeader;
402
411
  return (jsxRuntime.jsx("div", { className: "pb-4", "data-testid": "timeline-date-header", children: date ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(reactComponents.Text, { size: "medium", type: "span", weight: "thick", children: formatDate(date, { selectFormat: !showTime ? "dateOnly" : undefined }) }), jsxRuntime.jsx(reactComponents.Text, { className: "text-secondary-500", size: "medium", type: "span", weight: "thick", children: ` (${dateAndTimeUtils.timeSinceAuto(date, new Date())})` })] })) : (jsxRuntime.jsx(reactComponents.Text, { className: "pr-1", size: "medium", type: "span", weight: "thick", children: formatRange(dateRange, { dateStyle: !showTime ? "medium" : undefined }) })) }));
403
412
  };
404
- return (jsxRuntime.jsxs("div", { className: className, "data-testid": dataTestId, children: [renderDateHeader(), customHeader ? jsxRuntime.jsx("div", { className: "pb-4 font-semibold text-sm", children: customHeader }) : null, toggleButton && middleChildren.length > 0 ? (jsxRuntime.jsxs("div", { children: [firstChild, middleChildren.length > 0 ? renderToggleButton() : null, jsxRuntime.jsxs("div", { "aria-hidden": !isOpen, className: "transition-all duration-300 overflow-hidden", ref: ref, style: { height: isOpen ? `${ref.current?.scrollHeight}px` : "0px" }, children: [jsxRuntime.jsx("div", {}), middleChildren, jsxRuntime.jsx("div", {})] }), lastChild] })) : (jsxRuntime.jsx("div", { children: children }))] }));
413
+ return (jsxRuntime.jsxs("div", { className: className, "data-testid": dataTestId, children: [renderDateHeader(), customHeader ? jsxRuntime.jsx("div", { className: "text-sm font-semibold", children: customHeader }) : null, toggleButton && middleChildren.length > 0 ? (jsxRuntime.jsxs("div", { children: [firstChild, middleChildren.length > 0 ? renderToggleButton() : null, jsxRuntime.jsxs("div", { "aria-hidden": !isOpen, className: "overflow-hidden transition-all duration-300", ref: ref, children: [jsxRuntime.jsx("div", {}), middleChildren, jsxRuntime.jsx("div", {})] }), lastChild] })) : (jsxRuntime.jsx("div", { children: children }))] }));
405
414
  };
406
415
 
407
416
  /**
@@ -415,9 +424,7 @@ const TimelineElement = ({ date, children, className, dataTestId = "timeline-ele
415
424
  const [isHovered, setIsHovered] = React.useState(false);
416
425
  const { formatDate } = reactDateAndTimeHooks.useDateAndTime();
417
426
  const locale = reactDateAndTimeHooks.useLocale();
418
- const formattedDate = date
419
- ? formatDate(date, { selectFormat: "timeOnly", timeFormat: "short" })
420
- : null;
427
+ const formattedDate = date ? formatDate(date, { selectFormat: "timeOnly", timeFormat: "short" }) : null;
421
428
  const handleMouseEnter = () => {
422
429
  if (hoverBehavior) {
423
430
  setIsHovered(true);
@@ -428,24 +435,24 @@ const TimelineElement = ({ date, children, className, dataTestId = "timeline-ele
428
435
  setIsHovered(false);
429
436
  }
430
437
  };
431
- return (jsxRuntime.jsxs("div", { className: cvaTimelineElement({ className, selected, hoverBehavior }), "data-date": date, "data-testid": dataTestId, onClick: onClick, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [renderDate(formattedDate, locale), jsxRuntime.jsxs("div", { className: cvaDotWrapper(), children: [renderDot(customDot, isHovered, selected), jsxRuntime.jsx("div", { className: cvaLine({ lineStyle }) })] }), jsxRuntime.jsxs("div", { className: "pt-2 pb-2", children: [renderHeader(header), renderChildren(children), renderActionButton(actionButton)] })] }));
438
+ return (jsxRuntime.jsxs("div", { className: cvaTimelineElement({ className, selected, hoverBehavior }), "data-date": date, "data-testid": dataTestId, onClick: onClick, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [renderDate(formattedDate, locale), jsxRuntime.jsxs("div", { className: cvaDotWrapper(), children: [renderDot(customDot, isHovered, selected), jsxRuntime.jsx("div", { className: cvaLine({ lineStyle }) })] }), jsxRuntime.jsxs("div", { className: "pb-2 pt-2", children: [renderHeader(header), renderChildren(children), renderActionButton(actionButton)] })] }));
432
439
  };
433
440
  const renderDate = (formattedDate, locale) => {
434
441
  if (!formattedDate) {
435
442
  return null;
436
443
  }
437
- return (jsxRuntime.jsx("div", { className: "pt-2 items-center", children: timelineElementTime(formattedDate, locale) }));
444
+ return jsxRuntime.jsx("div", { className: "items-center pt-2", children: timelineElementTime(formattedDate, locale) });
438
445
  };
439
446
  const renderDot = (customDot, isHovered, selected) => {
440
447
  return customDot?.name
441
- ? customDotElement(customDot.name, isHovered, selected, customDot.color)
448
+ ? customDotElement(customDot.name, isHovered, selected, customDot.color, customDot.keepOnSelection)
442
449
  : defaultDot(isHovered, selected);
443
450
  };
444
451
  const renderHeader = (header) => {
445
452
  if (!header) {
446
453
  return null;
447
454
  }
448
- return jsxRuntime.jsx("div", { className: "text-sm mt-0.5 content-center font-medium", children: header });
455
+ return jsxRuntime.jsx("div", { className: "mt-0.5 content-center text-sm font-medium", children: header });
449
456
  };
450
457
  const renderChildren = (children) => {
451
458
  if (!children) {
@@ -462,15 +469,13 @@ const renderActionButton = (actionButton) => {
462
469
  const timelineElementTime = (formattedDate, locale) => {
463
470
  const hourCycle = dateAndTimeUtils.getHourCycle(locale);
464
471
  return (jsxRuntime.jsx(reactComponents.Text, { align: "right", className: cvaTimelineElementTime({
465
- width: hourCycle === "h12" || hourCycle === "h11" ? "large" : "small"
472
+ width: hourCycle === "h12" || hourCycle === "h11" ? "large" : "small",
466
473
  }), size: "small", subtle: true, children: formattedDate }));
467
474
  };
468
475
  const CircleIcon = ({ selected, hovered }) => (jsxRuntime.jsxs("svg", { className: "relative z-[2]", "data-testid": "timeline-circle-icon", height: "24", viewBox: "0 0 24 24", width: "24", children: [jsxRuntime.jsx("circle", { cx: "12", cy: "12", fill: selected ? "#EFF6FF" : hovered ? "#F9FAFB" : "white", r: "10" }), jsxRuntime.jsx("circle", { cx: "12", cy: "12", fill: "#2563EB", r: "8" }), jsxRuntime.jsx("circle", { cx: "12", cy: "12", fill: "white", r: "3" })] }));
469
476
  const DotIcon = () => (jsxRuntime.jsxs("svg", { className: "relative z-[2]", "data-testid": "timeline-dot-icon", height: "24", viewBox: "0 0 24 24", width: "24", children: [jsxRuntime.jsx("circle", { cx: "12", cy: "12", fill: "white", r: "6" }), jsxRuntime.jsx("circle", { cx: "12", cy: "12", fill: "#2563EB", r: "4" })] }));
470
- const defaultDot = (hovered, selected) => (hovered || selected) ? jsxRuntime.jsx(CircleIcon, { hovered: hovered, selected: selected }) : jsxRuntime.jsx(DotIcon, {});
471
- const customDotElement = (name, hovered, selected, color) => (hovered || selected
472
- ? jsxRuntime.jsx(CircleIcon, { hovered: hovered, selected: selected })
473
- : (jsxRuntime.jsx("div", { className: "w-6 h-6 flex items-center justify-center", children: jsxRuntime.jsx("div", { className: cvaCustomDot(), children: jsxRuntime.jsx(reactComponents.Icon, { className: "block", color: color, dataTestId: "timeline-custom-dot", name: name, size: "small" }) }) })));
477
+ const defaultDot = (hovered, selected) => hovered || selected ? jsxRuntime.jsx(CircleIcon, { hovered: hovered, selected: selected }) : jsxRuntime.jsx(DotIcon, {});
478
+ const customDotElement = (name, hovered, selected, color, keepOnSelection) => (hovered || selected) && !keepOnSelection ? (jsxRuntime.jsx(CircleIcon, { hovered: hovered, selected: selected })) : (jsxRuntime.jsx("div", { className: "flex h-6 w-6 items-center justify-center", children: jsxRuntime.jsx("div", { className: cvaCustomDot(), children: jsxRuntime.jsx(reactComponents.Icon, { className: "block", color: color, dataTestId: "timeline-custom-dot", name: name, size: "small" }) }) }));
474
479
 
475
480
  /*
476
481
  * ----------------------------
package/index.esm.js CHANGED
@@ -386,9 +386,18 @@ const Timeline = ({ className, dataTestId, children, dateHeader, customHeader, t
386
386
  const childProps = React.isValidElement(firstChild) ? firstChild.props : {};
387
387
  const lastChild = remainingChildren.pop();
388
388
  const middleChildren = remainingChildren;
389
+ useEffect(() => {
390
+ // Set maxHeight dynamically for smooth animation
391
+ if (ref.current) {
392
+ ref.current.style.maxHeight = isOpen ? `${ref.current.scrollHeight}px` : "0px";
393
+ }
394
+ }, [isOpen]);
389
395
  const renderToggleButton = () => (jsxs("div", { className: cvaTimelineElement(), children: [childProps?.date ? (jsx("div", { className: cvaTimelineElementTime({
390
396
  width: hourCycle === "h12" || hourCycle === "h11" ? "large" : "small",
391
- }) })) : null, jsx("div", { className: cvaDotWrapper(), children: jsx("div", { className: cvaLine({ lineStyle: childProps?.lineStyle }) }) }), jsxs("div", { className: "flex text-sm text-secondary-500 cursor-pointer items-center min-h-8 hover:text-secondary-600", "data-testid": "timeline-toggle-btn", onClick: () => setIsOpen(!isOpen), children: [jsx(Icon, { className: cvaToggleBtnIcon({ rotated: isOpen }), name: "ChevronDown", size: "small" }), jsx("span", { children: isOpen ? toggleButton?.collapsedLabel : toggleButton?.expandedLabel })] })] }));
397
+ }) })) : null, jsx("div", { className: cvaDotWrapper(), children: jsx("div", { className: cvaLine({ lineStyle: childProps?.lineStyle }) }) }), jsxs("div", { className: "text-secondary-500 hover:text-secondary-600 flex min-h-8 cursor-pointer items-center text-sm", "data-testid": "timeline-toggle-btn", onClick: () => {
398
+ toggleButton?.onClick && toggleButton.onClick();
399
+ setIsOpen(!isOpen);
400
+ }, children: [jsx(Icon, { className: cvaToggleBtnIcon({ rotated: isOpen }), name: "ChevronDown", size: "small" }), jsx("span", { children: isOpen ? toggleButton?.collapsedLabel : toggleButton?.expandedLabel })] })] }));
392
401
  const renderDateHeader = () => {
393
402
  if (!dateHeader) {
394
403
  return null;
@@ -399,7 +408,7 @@ const Timeline = ({ className, dataTestId, children, dateHeader, customHeader, t
399
408
  const { date, dateRange, showTime } = dateHeader;
400
409
  return (jsx("div", { className: "pb-4", "data-testid": "timeline-date-header", children: date ? (jsxs(Fragment, { children: [jsx(Text, { size: "medium", type: "span", weight: "thick", children: formatDate(date, { selectFormat: !showTime ? "dateOnly" : undefined }) }), jsx(Text, { className: "text-secondary-500", size: "medium", type: "span", weight: "thick", children: ` (${timeSinceAuto(date, new Date())})` })] })) : (jsx(Text, { className: "pr-1", size: "medium", type: "span", weight: "thick", children: formatRange(dateRange, { dateStyle: !showTime ? "medium" : undefined }) })) }));
401
410
  };
402
- return (jsxs("div", { className: className, "data-testid": dataTestId, children: [renderDateHeader(), customHeader ? jsx("div", { className: "pb-4 font-semibold text-sm", children: customHeader }) : null, toggleButton && middleChildren.length > 0 ? (jsxs("div", { children: [firstChild, middleChildren.length > 0 ? renderToggleButton() : null, jsxs("div", { "aria-hidden": !isOpen, className: "transition-all duration-300 overflow-hidden", ref: ref, style: { height: isOpen ? `${ref.current?.scrollHeight}px` : "0px" }, children: [jsx("div", {}), middleChildren, jsx("div", {})] }), lastChild] })) : (jsx("div", { children: children }))] }));
411
+ return (jsxs("div", { className: className, "data-testid": dataTestId, children: [renderDateHeader(), customHeader ? jsx("div", { className: "text-sm font-semibold", children: customHeader }) : null, toggleButton && middleChildren.length > 0 ? (jsxs("div", { children: [firstChild, middleChildren.length > 0 ? renderToggleButton() : null, jsxs("div", { "aria-hidden": !isOpen, className: "overflow-hidden transition-all duration-300", ref: ref, children: [jsx("div", {}), middleChildren, jsx("div", {})] }), lastChild] })) : (jsx("div", { children: children }))] }));
403
412
  };
404
413
 
405
414
  /**
@@ -413,9 +422,7 @@ const TimelineElement = ({ date, children, className, dataTestId = "timeline-ele
413
422
  const [isHovered, setIsHovered] = useState(false);
414
423
  const { formatDate } = useDateAndTime();
415
424
  const locale = useLocale$1();
416
- const formattedDate = date
417
- ? formatDate(date, { selectFormat: "timeOnly", timeFormat: "short" })
418
- : null;
425
+ const formattedDate = date ? formatDate(date, { selectFormat: "timeOnly", timeFormat: "short" }) : null;
419
426
  const handleMouseEnter = () => {
420
427
  if (hoverBehavior) {
421
428
  setIsHovered(true);
@@ -426,24 +433,24 @@ const TimelineElement = ({ date, children, className, dataTestId = "timeline-ele
426
433
  setIsHovered(false);
427
434
  }
428
435
  };
429
- return (jsxs("div", { className: cvaTimelineElement({ className, selected, hoverBehavior }), "data-date": date, "data-testid": dataTestId, onClick: onClick, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [renderDate(formattedDate, locale), jsxs("div", { className: cvaDotWrapper(), children: [renderDot(customDot, isHovered, selected), jsx("div", { className: cvaLine({ lineStyle }) })] }), jsxs("div", { className: "pt-2 pb-2", children: [renderHeader(header), renderChildren(children), renderActionButton(actionButton)] })] }));
436
+ return (jsxs("div", { className: cvaTimelineElement({ className, selected, hoverBehavior }), "data-date": date, "data-testid": dataTestId, onClick: onClick, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [renderDate(formattedDate, locale), jsxs("div", { className: cvaDotWrapper(), children: [renderDot(customDot, isHovered, selected), jsx("div", { className: cvaLine({ lineStyle }) })] }), jsxs("div", { className: "pb-2 pt-2", children: [renderHeader(header), renderChildren(children), renderActionButton(actionButton)] })] }));
430
437
  };
431
438
  const renderDate = (formattedDate, locale) => {
432
439
  if (!formattedDate) {
433
440
  return null;
434
441
  }
435
- return (jsx("div", { className: "pt-2 items-center", children: timelineElementTime(formattedDate, locale) }));
442
+ return jsx("div", { className: "items-center pt-2", children: timelineElementTime(formattedDate, locale) });
436
443
  };
437
444
  const renderDot = (customDot, isHovered, selected) => {
438
445
  return customDot?.name
439
- ? customDotElement(customDot.name, isHovered, selected, customDot.color)
446
+ ? customDotElement(customDot.name, isHovered, selected, customDot.color, customDot.keepOnSelection)
440
447
  : defaultDot(isHovered, selected);
441
448
  };
442
449
  const renderHeader = (header) => {
443
450
  if (!header) {
444
451
  return null;
445
452
  }
446
- return jsx("div", { className: "text-sm mt-0.5 content-center font-medium", children: header });
453
+ return jsx("div", { className: "mt-0.5 content-center text-sm font-medium", children: header });
447
454
  };
448
455
  const renderChildren = (children) => {
449
456
  if (!children) {
@@ -460,15 +467,13 @@ const renderActionButton = (actionButton) => {
460
467
  const timelineElementTime = (formattedDate, locale) => {
461
468
  const hourCycle = getHourCycle(locale);
462
469
  return (jsx(Text, { align: "right", className: cvaTimelineElementTime({
463
- width: hourCycle === "h12" || hourCycle === "h11" ? "large" : "small"
470
+ width: hourCycle === "h12" || hourCycle === "h11" ? "large" : "small",
464
471
  }), size: "small", subtle: true, children: formattedDate }));
465
472
  };
466
473
  const CircleIcon = ({ selected, hovered }) => (jsxs("svg", { className: "relative z-[2]", "data-testid": "timeline-circle-icon", height: "24", viewBox: "0 0 24 24", width: "24", children: [jsx("circle", { cx: "12", cy: "12", fill: selected ? "#EFF6FF" : hovered ? "#F9FAFB" : "white", r: "10" }), jsx("circle", { cx: "12", cy: "12", fill: "#2563EB", r: "8" }), jsx("circle", { cx: "12", cy: "12", fill: "white", r: "3" })] }));
467
474
  const DotIcon = () => (jsxs("svg", { className: "relative z-[2]", "data-testid": "timeline-dot-icon", height: "24", viewBox: "0 0 24 24", width: "24", children: [jsx("circle", { cx: "12", cy: "12", fill: "white", r: "6" }), jsx("circle", { cx: "12", cy: "12", fill: "#2563EB", r: "4" })] }));
468
- const defaultDot = (hovered, selected) => (hovered || selected) ? jsx(CircleIcon, { hovered: hovered, selected: selected }) : jsx(DotIcon, {});
469
- const customDotElement = (name, hovered, selected, color) => (hovered || selected
470
- ? jsx(CircleIcon, { hovered: hovered, selected: selected })
471
- : (jsx("div", { className: "w-6 h-6 flex items-center justify-center", children: jsx("div", { className: cvaCustomDot(), children: jsx(Icon, { className: "block", color: color, dataTestId: "timeline-custom-dot", name: name, size: "small" }) }) })));
475
+ const defaultDot = (hovered, selected) => hovered || selected ? jsx(CircleIcon, { hovered: hovered, selected: selected }) : jsx(DotIcon, {});
476
+ const customDotElement = (name, hovered, selected, color, keepOnSelection) => (hovered || selected) && !keepOnSelection ? (jsx(CircleIcon, { hovered: hovered, selected: selected })) : (jsx("div", { className: "flex h-6 w-6 items-center justify-center", children: jsx("div", { className: cvaCustomDot(), children: jsx(Icon, { className: "block", color: color, dataTestId: "timeline-custom-dot", name: name, size: "small" }) }) }));
472
477
 
473
478
  /*
474
479
  * ----------------------------
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-date-and-time-components",
3
- "version": "1.0.16",
3
+ "version": "1.0.18",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -11,7 +11,7 @@
11
11
  "date-fns": "^2.30.0",
12
12
  "tailwind-merge": "^2.0.0",
13
13
  "react": "18.3.1",
14
- "@trackunit/react-components": "^1.0.13",
14
+ "@trackunit/react-components": "^1.1.0",
15
15
  "@trackunit/react-date-and-time-hooks": "^1.0.8",
16
16
  "@trackunit/react-core-hooks": "^1.0.5",
17
17
  "@trackunit/date-and-time-utils": "^1.0.1",
@@ -6,6 +6,7 @@ export interface TimelineProps extends CommonProps {
6
6
  toggleButton?: {
7
7
  expandedLabel: string;
8
8
  collapsedLabel: string;
9
+ onClick?: () => void;
9
10
  };
10
11
  dateHeader?: ({
11
12
  date: Date;
@@ -1,6 +1,6 @@
1
- import React from "react";
2
1
  import { CommonProps, IconColors } from "@trackunit/react-components";
3
2
  import { IconName } from "@trackunit/ui-icons";
3
+ import React from "react";
4
4
  interface TimeLineElementProps extends CommonProps {
5
5
  date?: Date;
6
6
  header?: React.ReactNode;
@@ -8,8 +8,9 @@ interface TimeLineElementProps extends CommonProps {
8
8
  customDot?: {
9
9
  name: IconName;
10
10
  color: IconColors;
11
+ keepOnSelection?: boolean;
11
12
  };
12
- onClick?: () => void;
13
+ onClick?: (e?: React.MouseEvent<HTMLDivElement>) => void;
13
14
  actionButton?: {
14
15
  label: string;
15
16
  iconName: IconName;