@elaraai/east-ui-components 0.0.1-beta.1 → 0.0.1-beta.2

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/dist/index.js CHANGED
@@ -5,9 +5,9 @@ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
5
5
  import * as React from "react";
6
6
  import React__default, { memo as memo$2, useMemo, useId as useId$1, isValidElement, forwardRef, useContext, createContext, useState, useCallback, useRef, useImperativeHandle, useEffect, PureComponent, useLayoutEffect, cloneElement, createElement as createElement$1, Children, Component, useReducer } from "react";
7
7
  import { match, equalFor, printFor, encodeBeast2For, IRType, BlobType } from "@elaraai/east";
8
- import { Text as Text$1, Button as Button$1, IconButton as IconButton$1, Sparkline, Chart, Box as Box$1, Stack as Stack$1, Separator as Separator$1, Grid as Grid$1, Splitter as Splitter$1, Accordion as Accordion$1, Carousel as Carousel$1, Tabs as Tabs$1, DataList as DataList$1, Table as Table$1, Icon as Icon$1, TreeView as TreeView$1, Badge as Badge$1, Tag as Tag$1, Avatar as Avatar$1, Stat as Stat$1, Input as Input$1, Checkbox as Checkbox$1, Switch as Switch$1, Select as Select$1, Slider as Slider$1, Field as Field$1, Textarea as Textarea$1, TagsInput as TagsInput$1, FileUpload as FileUpload$1, Alert as Alert$1, Progress as Progress$1, Card as Card$1, Tooltip as Tooltip$2, Menu as Menu$1, Popover as Popover$1, HoverCard as HoverCard$1, Dialog as Dialog$1, Drawer as Drawer$1, ActionBar as ActionBar$1, ToggleTip, UIComponentType, state_write, state_read } from "@elaraai/east-ui";
8
+ import { Text as Text$1, Button as Button$1, IconButton as IconButton$1, Sparkline, Chart, Box as Box$1, Stack as Stack$1, Separator as Separator$1, Grid as Grid$1, Splitter as Splitter$1, Accordion as Accordion$1, Carousel as Carousel$1, Tabs as Tabs$1, DataList as DataList$1, Table as Table$1, Icon as Icon$1, TreeView as TreeView$1, Gantt, Badge as Badge$1, Tag as Tag$1, Avatar as Avatar$1, Stat as Stat$1, Input as Input$1, Checkbox as Checkbox$1, Switch as Switch$1, Select as Select$1, Slider as Slider$1, Field as Field$1, Textarea as Textarea$1, TagsInput as TagsInput$1, FileUpload as FileUpload$1, Alert as Alert$1, Progress as Progress$1, Card as Card$1, Tooltip as Tooltip$2, Menu as Menu$1, Popover as Popover$1, HoverCard as HoverCard$1, Dialog as Dialog$1, Drawer as Drawer$1, ActionBar as ActionBar$1, ToggleTip, UIComponentType, state_write, state_read } from "@elaraai/east-ui";
9
9
  import { State, state_read as state_read2, state_write as state_write2 } from "@elaraai/east-ui";
10
- import { Text as Text$2, Button, IconButton, useChakraContext, useLocaleContext, Box, defineStyle, Stack, Flex, ColorSwatch, HStack, Span, Separator, Show, AbsoluteCenter, Grid, GridItem, Splitter, Accordion, Carousel, Tabs, DataList, Table, Skeleton, createTreeCollection, TreeView, Badge, Tag, Avatar, Stat, Input, Checkbox, Switch, createListCollection, Select, Portal, Slider, Field, Fieldset, Textarea, TagsInput, FileUpload, Alert, Progress, Card, Tooltip as Tooltip$1, Menu, Popover, HoverCard, Dialog, CloseButton, Drawer, ActionBar } from "@chakra-ui/react";
10
+ import { Text as Text$2, Button, IconButton, useChakraContext, useLocaleContext, Box, defineStyle, Stack, Flex, ColorSwatch, HStack, Span, Separator, Show, AbsoluteCenter, Grid, GridItem, Splitter, Accordion, Carousel, Tabs, DataList, Table, Skeleton, createTreeCollection, TreeView, useToken, Badge, Tag, Avatar, Stat, Input, Checkbox, Switch, createListCollection, Select, Portal, Slider, Field, Fieldset, Textarea, TagsInput, FileUpload, Alert, Progress, Card, Tooltip as Tooltip$1, Menu, Popover, HoverCard, Dialog, CloseButton, Drawer, ActionBar } from "@chakra-ui/react";
11
11
  import { createPortal, flushSync } from "react-dom";
12
12
  const getSomeorUndefined = (opt) => {
13
13
  return match(opt, {
@@ -18223,7 +18223,7 @@ function useChart(props) {
18223
18223
  },
18224
18224
  [env.locale]
18225
18225
  );
18226
- const formatDate = React.useCallback(
18226
+ const formatDate2 = React.useCallback(
18227
18227
  (options) => {
18228
18228
  return (value) => new Date(value).toLocaleDateString(env.locale, options);
18229
18229
  },
@@ -18294,7 +18294,7 @@ function useChart(props) {
18294
18294
  spacing,
18295
18295
  // formatters
18296
18296
  formatNumber,
18297
- formatDate,
18297
+ formatDate: formatDate2,
18298
18298
  // state
18299
18299
  highlightedSeries,
18300
18300
  setHighlightedSeries,
@@ -53296,7 +53296,7 @@ class RowStateManager {
53296
53296
  }
53297
53297
  }
53298
53298
  const tableRootEqual = equalFor(Table$1.Types.Root);
53299
- function toChakraTableRoot(value) {
53299
+ function toChakraTableRoot$1(value) {
53300
53300
  var _a, _b, _c;
53301
53301
  const style = getSomeorUndefined(value.style);
53302
53302
  return {
@@ -53320,7 +53320,7 @@ const EastChakraTable = memo$2(function EastChakraTable2({
53320
53320
  loadingDelay = 200,
53321
53321
  enableColumnResizing = true
53322
53322
  }) {
53323
- const props = useMemo(() => toChakraTableRoot(value), [value]);
53323
+ const props = useMemo(() => toChakraTableRoot$1(value), [value]);
53324
53324
  const tableContainerRef = useRef(null);
53325
53325
  const [rowStateManager] = useState(() => new RowStateManager());
53326
53326
  const [rowStates, setRowStates] = useState(/* @__PURE__ */ new Map());
@@ -53739,6 +53739,898 @@ function toChakraTreeViewRoot(value) {
53739
53739
  selectionMode: style ? (_c = getSomeorUndefined(style.selectionMode)) == null ? void 0 : _c.type : void 0
53740
53740
  };
53741
53741
  }
53742
+ const formatDate = (date2) => {
53743
+ return date2.toLocaleDateString("en-US", {
53744
+ month: "short",
53745
+ day: "numeric"
53746
+ });
53747
+ };
53748
+ const generateDateTicks = (startDate, endDate, maxTicks = 8) => {
53749
+ const totalDays = Math.ceil((endDate.getTime() - startDate.getTime()) / (1e3 * 60 * 60 * 24));
53750
+ const tickInterval = Math.max(1, Math.ceil(totalDays / maxTicks));
53751
+ const ticks2 = [];
53752
+ const current2 = new Date(startDate);
53753
+ while (current2 <= endDate) {
53754
+ ticks2.push(new Date(current2));
53755
+ current2.setDate(current2.getDate() + tickInterval);
53756
+ }
53757
+ return ticks2;
53758
+ };
53759
+ const getDatePosition = (date2, startDate, endDate, width) => {
53760
+ const totalTimeDiff = endDate.getTime() - startDate.getTime();
53761
+ const currentTimeDiff = date2.getTime() - startDate.getTime();
53762
+ const ratio = currentTimeDiff / totalTimeDiff;
53763
+ return ratio * width;
53764
+ };
53765
+ const LABEL_HALF_WIDTH = 40;
53766
+ const EventAxis = ({
53767
+ startDate,
53768
+ endDate,
53769
+ width,
53770
+ height
53771
+ }) => {
53772
+ const ticks2 = useMemo(() => {
53773
+ const dates = generateDateTicks(startDate, endDate, Math.floor(width / 100));
53774
+ return dates.map((date2, index) => {
53775
+ const x2 = getDatePosition(date2, startDate, endDate, width);
53776
+ if (x2 >= LABEL_HALF_WIDTH && x2 <= width - LABEL_HALF_WIDTH) {
53777
+ return { date: date2, x: x2, index };
53778
+ }
53779
+ return null;
53780
+ }).filter(Boolean);
53781
+ }, [startDate, endDate, width]);
53782
+ return /* @__PURE__ */ jsx(
53783
+ HStack,
53784
+ {
53785
+ position: "relative",
53786
+ width: "100%",
53787
+ height: `${height}px`,
53788
+ px: "3",
53789
+ alignItems: "center",
53790
+ borderBottomWidth: "1px",
53791
+ borderColor: "border.muted",
53792
+ gap: 0,
53793
+ children: ticks2.map(({ date: date2, x: x2, index }) => /* @__PURE__ */ jsx(
53794
+ Box,
53795
+ {
53796
+ position: "absolute",
53797
+ left: `${x2}px`,
53798
+ transform: "translateX(-50%)",
53799
+ children: /* @__PURE__ */ jsx(
53800
+ Text$2,
53801
+ {
53802
+ fontSize: "sm",
53803
+ fontWeight: "semibold",
53804
+ color: "fg.default",
53805
+ whiteSpace: "nowrap",
53806
+ children: formatDate(date2)
53807
+ }
53808
+ )
53809
+ },
53810
+ `tick-${index}`
53811
+ ))
53812
+ }
53813
+ );
53814
+ };
53815
+ const GanttTask = ({
53816
+ x: x2,
53817
+ y: y2,
53818
+ width,
53819
+ height,
53820
+ value,
53821
+ onClick
53822
+ }) => {
53823
+ const [isHovered, setIsHovered] = useState(false);
53824
+ const { colorPalette, label, progress } = useMemo(() => {
53825
+ var _a;
53826
+ return {
53827
+ colorPalette: ((_a = getSomeorUndefined(value.colorPalette)) == null ? void 0 : _a.type) ?? "blue",
53828
+ label: getSomeorUndefined(value.label),
53829
+ progress: getSomeorUndefined(value.progress)
53830
+ };
53831
+ }, [value]);
53832
+ const [fillColor, strokeColor] = useToken("colors", [
53833
+ `${colorPalette}.500`,
53834
+ `${colorPalette}.600`
53835
+ ]);
53836
+ const fontSize = useMemo(() => Math.min(height * 0.7, 14), [height]);
53837
+ const textX = useMemo(() => x2 + 8, [x2]);
53838
+ const taskWidth = useMemo(() => Math.max(width, 4), [width]);
53839
+ const progressWidth = useMemo(() => taskWidth * ((progress ?? 0) / 100), [taskWidth, progress]);
53840
+ const handleMouseEnter = useCallback(() => setIsHovered(true), []);
53841
+ const handleMouseLeave = useCallback(() => setIsHovered(false), []);
53842
+ return /* @__PURE__ */ jsxs("g", { children: [
53843
+ /* @__PURE__ */ jsx(
53844
+ "rect",
53845
+ {
53846
+ x: x2,
53847
+ y: y2,
53848
+ width: taskWidth,
53849
+ height,
53850
+ fill: fillColor,
53851
+ stroke: strokeColor,
53852
+ strokeWidth: isHovered ? 3 : 2,
53853
+ opacity: isHovered ? 1 : 0.9,
53854
+ rx: 4,
53855
+ ry: 4,
53856
+ onClick,
53857
+ onMouseEnter: handleMouseEnter,
53858
+ onMouseLeave: handleMouseLeave,
53859
+ style: { cursor: onClick ? "pointer" : "default" }
53860
+ }
53861
+ ),
53862
+ progress !== void 0 && /* @__PURE__ */ jsx(
53863
+ "rect",
53864
+ {
53865
+ x: x2,
53866
+ y: y2,
53867
+ width: progressWidth,
53868
+ height,
53869
+ fill: "rgba(255,255,255,0.3)",
53870
+ rx: 4,
53871
+ ry: 4,
53872
+ style: { pointerEvents: "none" }
53873
+ }
53874
+ ),
53875
+ label && /* @__PURE__ */ jsx(
53876
+ "foreignObject",
53877
+ {
53878
+ x: textX,
53879
+ y: y2,
53880
+ width: 180,
53881
+ height,
53882
+ style: { pointerEvents: "auto" },
53883
+ children: /* @__PURE__ */ jsx(
53884
+ Text$2,
53885
+ {
53886
+ fontSize: `${fontSize}px`,
53887
+ color: "fg.default",
53888
+ opacity: isHovered ? 1 : 0.9,
53889
+ whiteSpace: "nowrap",
53890
+ cursor: onClick ? "pointer" : "default",
53891
+ userSelect: "none",
53892
+ lineHeight: "1",
53893
+ overflow: "hidden",
53894
+ textOverflow: "ellipsis",
53895
+ display: "flex",
53896
+ alignItems: "center",
53897
+ height: "100%",
53898
+ onMouseEnter: handleMouseEnter,
53899
+ onMouseLeave: handleMouseLeave,
53900
+ onClick,
53901
+ m: 0,
53902
+ p: 0,
53903
+ children: label
53904
+ }
53905
+ )
53906
+ }
53907
+ )
53908
+ ] });
53909
+ };
53910
+ const makeDiamondPoints = (x2, y2, size) => {
53911
+ const centerX = x2;
53912
+ const centerY = y2 + size / 2;
53913
+ return `${centerX},${y2} ${centerX + size / 2},${centerY} ${centerX},${y2 + size} ${centerX - size / 2},${centerY}`;
53914
+ };
53915
+ const GanttMilestone = ({
53916
+ x: x2,
53917
+ y: y2,
53918
+ height,
53919
+ value,
53920
+ onClick
53921
+ }) => {
53922
+ const [isHovered, setIsHovered] = useState(false);
53923
+ const { colorPalette, label } = useMemo(() => {
53924
+ var _a;
53925
+ return {
53926
+ colorPalette: ((_a = getSomeorUndefined(value.colorPalette)) == null ? void 0 : _a.type) ?? "blue",
53927
+ label: getSomeorUndefined(value.label)
53928
+ };
53929
+ }, [value]);
53930
+ const [fillColor, strokeColor] = useToken("colors", [
53931
+ `${colorPalette}.500`,
53932
+ `${colorPalette}.600`
53933
+ ]);
53934
+ const fontSize = useMemo(() => Math.min(height * 0.7, 14), [height]);
53935
+ const diamondSize = useMemo(() => height, [height]);
53936
+ const textX = useMemo(() => x2 + diamondSize / 2 + 4, [x2, diamondSize]);
53937
+ const diamondPoints = useMemo(() => makeDiamondPoints(x2, y2, diamondSize), [x2, y2, diamondSize]);
53938
+ const handleMouseEnter = useCallback(() => setIsHovered(true), []);
53939
+ const handleMouseLeave = useCallback(() => setIsHovered(false), []);
53940
+ return /* @__PURE__ */ jsxs("g", { children: [
53941
+ /* @__PURE__ */ jsx(
53942
+ "polygon",
53943
+ {
53944
+ points: diamondPoints,
53945
+ fill: fillColor,
53946
+ stroke: strokeColor,
53947
+ strokeWidth: isHovered ? 3 : 2,
53948
+ opacity: isHovered ? 1 : 0.9,
53949
+ onClick,
53950
+ onMouseEnter: handleMouseEnter,
53951
+ onMouseLeave: handleMouseLeave,
53952
+ style: { cursor: onClick ? "pointer" : "default" }
53953
+ }
53954
+ ),
53955
+ label && /* @__PURE__ */ jsx(
53956
+ "foreignObject",
53957
+ {
53958
+ x: textX,
53959
+ y: y2,
53960
+ width: 200,
53961
+ height,
53962
+ style: { pointerEvents: "auto" },
53963
+ children: /* @__PURE__ */ jsx(
53964
+ Text$2,
53965
+ {
53966
+ fontSize: `${fontSize}px`,
53967
+ color: "fg.default",
53968
+ opacity: isHovered ? 1 : 0.9,
53969
+ whiteSpace: "nowrap",
53970
+ cursor: onClick ? "pointer" : "default",
53971
+ userSelect: "none",
53972
+ lineHeight: "1",
53973
+ display: "flex",
53974
+ alignItems: "center",
53975
+ height: "100%",
53976
+ onMouseEnter: handleMouseEnter,
53977
+ onMouseLeave: handleMouseLeave,
53978
+ onClick,
53979
+ m: 0,
53980
+ p: 0,
53981
+ children: label
53982
+ }
53983
+ )
53984
+ }
53985
+ )
53986
+ ] });
53987
+ };
53988
+ const getEventPosition = (event, startDate, endDate, width) => {
53989
+ const totalTimespan = endDate.getTime() - startDate.getTime();
53990
+ if (event.type === "Milestone") {
53991
+ const eventDate = event.value.date;
53992
+ const eventTime = eventDate.getTime();
53993
+ if (eventTime >= startDate.getTime() && eventTime <= endDate.getTime()) {
53994
+ const position = (eventTime - startDate.getTime()) / totalTimespan;
53995
+ return {
53996
+ x: position * width,
53997
+ width: 0,
53998
+ isMilestone: true
53999
+ };
54000
+ }
54001
+ return { x: 0, width: 0, isMilestone: true };
54002
+ }
54003
+ const taskValue = event.value;
54004
+ const eventStart = taskValue.start;
54005
+ const eventEnd = taskValue.end;
54006
+ const clampedStart = Math.max(eventStart.getTime(), startDate.getTime());
54007
+ const clampedEnd = Math.min(eventEnd.getTime(), endDate.getTime());
54008
+ const startOffset = (clampedStart - startDate.getTime()) / totalTimespan;
54009
+ const duration = (clampedEnd - clampedStart) / totalTimespan;
54010
+ return {
54011
+ x: startOffset * width,
54012
+ width: Math.max(duration * width, 2),
54013
+ isMilestone: false
54014
+ };
54015
+ };
54016
+ const GanttEventRow = ({
54017
+ events,
54018
+ rowIndex,
54019
+ y: y2,
54020
+ width,
54021
+ height,
54022
+ startDate,
54023
+ endDate,
54024
+ onEventClick
54025
+ }) => {
54026
+ const renderedEvents = useMemo(() => {
54027
+ const eventHeight = height - 24;
54028
+ const eventY = y2 + 12;
54029
+ return events.map((event, eventIndex) => {
54030
+ const position = getEventPosition(event, startDate, endDate, width);
54031
+ if (position.x < 0 || position.x > width) return null;
54032
+ if (event.type === "Milestone") {
54033
+ return /* @__PURE__ */ jsx(
54034
+ GanttMilestone,
54035
+ {
54036
+ x: position.x,
54037
+ y: eventY,
54038
+ height: eventHeight,
54039
+ value: event.value,
54040
+ onClick: onEventClick ? () => onEventClick(event, rowIndex, eventIndex) : () => {
54041
+ }
54042
+ },
54043
+ `${rowIndex}-${eventIndex}`
54044
+ );
54045
+ }
54046
+ return /* @__PURE__ */ jsx(
54047
+ GanttTask,
54048
+ {
54049
+ x: position.x,
54050
+ y: eventY,
54051
+ width: position.width,
54052
+ height: eventHeight,
54053
+ value: event.value,
54054
+ onClick: onEventClick ? () => onEventClick(event, rowIndex, eventIndex) : () => {
54055
+ }
54056
+ },
54057
+ `${rowIndex}-${eventIndex}`
54058
+ );
54059
+ }).filter(Boolean);
54060
+ }, [events, rowIndex, y2, width, height, startDate, endDate, onEventClick]);
54061
+ return /* @__PURE__ */ jsx("g", { children: renderedEvents });
54062
+ };
54063
+ const ganttRootEqual = equalFor(Gantt.Types.Root);
54064
+ function toChakraTableRoot(value) {
54065
+ var _a, _b, _c;
54066
+ const style = getSomeorUndefined(value.style);
54067
+ return {
54068
+ variant: style ? (_a = getSomeorUndefined(style.variant)) == null ? void 0 : _a.type : void 0,
54069
+ size: style ? (_b = getSomeorUndefined(style.size)) == null ? void 0 : _b.type : void 0,
54070
+ striped: style ? getSomeorUndefined(style.striped) : void 0,
54071
+ interactive: style ? getSomeorUndefined(style.interactive) : void 0,
54072
+ stickyHeader: style ? getSomeorUndefined(style.stickyHeader) : void 0,
54073
+ showColumnBorder: style ? getSomeorUndefined(style.showColumnBorder) : void 0,
54074
+ colorPalette: style ? (_c = getSomeorUndefined(style.colorPalette)) == null ? void 0 : _c.type : void 0
54075
+ };
54076
+ }
54077
+ const EastChakraGantt = memo$2(function EastChakraGantt2({
54078
+ value,
54079
+ height = "400px",
54080
+ rowHeight = 48,
54081
+ overscan = 8,
54082
+ onSortChange,
54083
+ enableMultiSort = true,
54084
+ maxSortColumns = 5,
54085
+ loadingDelay = 200,
54086
+ enableColumnResizing = true,
54087
+ onEventClick,
54088
+ tablePanelSize = 40
54089
+ }) {
54090
+ const props = useMemo(() => toChakraTableRoot(value), [value]);
54091
+ const headerHeight = 56;
54092
+ const [gridLineColor] = useToken("colors", ["gray.300"]);
54093
+ const tableContainerRef = useRef(null);
54094
+ const timelineContainerRef = useRef(null);
54095
+ const [timelineWidth, setTimelineWidth] = useState(400);
54096
+ const [rowStateManager] = useState(() => new RowStateManager());
54097
+ const [rowStates, setRowStates] = useState(/* @__PURE__ */ new Map());
54098
+ const visibleRowsRef = useRef(/* @__PURE__ */ new Set());
54099
+ const dateRange = useMemo(() => {
54100
+ let minDate = null;
54101
+ let maxDate = null;
54102
+ value.rows.forEach((row) => {
54103
+ row.events.forEach((event) => {
54104
+ if (event.type === "Milestone") {
54105
+ const date2 = event.value.date;
54106
+ if (minDate === null || date2 < minDate) minDate = date2;
54107
+ if (maxDate === null || date2 > maxDate) maxDate = date2;
54108
+ } else {
54109
+ const start = event.value.start;
54110
+ const end3 = event.value.end;
54111
+ if (minDate === null || start < minDate) minDate = start;
54112
+ if (maxDate === null || end3 > maxDate) maxDate = end3;
54113
+ }
54114
+ });
54115
+ });
54116
+ if (minDate === null) minDate = /* @__PURE__ */ new Date();
54117
+ if (maxDate === null) maxDate = /* @__PURE__ */ new Date();
54118
+ const totalDuration = maxDate.getTime() - minDate.getTime();
54119
+ const bufferDuration = Math.max(totalDuration * 0.1, 24 * 60 * 60 * 1e3);
54120
+ return {
54121
+ start: new Date(minDate.getTime() - bufferDuration),
54122
+ end: new Date(maxDate.getTime() + bufferDuration)
54123
+ };
54124
+ }, [value.rows]);
54125
+ const gridLinePositions = useMemo(() => {
54126
+ const dates = generateDateTicks(dateRange.start, dateRange.end, Math.floor(timelineWidth / 100));
54127
+ return dates.map((date2) => getDatePosition(date2, dateRange.start, dateRange.end, timelineWidth)).filter((x2) => x2 >= 0 && x2 <= timelineWidth);
54128
+ }, [dateRange.start, dateRange.end, timelineWidth]);
54129
+ useEffect(() => {
54130
+ const container = timelineContainerRef.current;
54131
+ if (!container) return;
54132
+ const updateWidth = () => {
54133
+ const width = container.offsetWidth;
54134
+ setTimelineWidth(Math.max(200, width));
54135
+ };
54136
+ updateWidth();
54137
+ const resizeObserver = new ResizeObserver(updateWidth);
54138
+ resizeObserver.observe(container);
54139
+ return () => resizeObserver.disconnect();
54140
+ }, []);
54141
+ useEffect(() => {
54142
+ return rowStateManager.subscribe(() => {
54143
+ setRowStates(new Map(rowStateManager.getStates()));
54144
+ });
54145
+ }, [rowStateManager]);
54146
+ useEffect(() => {
54147
+ return () => {
54148
+ rowStateManager.clear();
54149
+ };
54150
+ }, [rowStateManager]);
54151
+ const columnHelper = createColumnHelper();
54152
+ const columns = useMemo(() => {
54153
+ return value.columns.map((col) => {
54154
+ const print = printFor(col.type);
54155
+ return columnHelper.accessor(
54156
+ (row) => row.cells.get(col.key),
54157
+ {
54158
+ id: col.key,
54159
+ header: getSomeorUndefined(col.header) ?? col.key,
54160
+ enableSorting: true,
54161
+ minSize: 80,
54162
+ size: 150,
54163
+ maxSize: 400,
54164
+ meta: {
54165
+ print,
54166
+ columnKey: col.key
54167
+ }
54168
+ }
54169
+ );
54170
+ });
54171
+ }, [value.columns, columnHelper]);
54172
+ const [sorting, setSorting] = useState([]);
54173
+ const handleSortingChange = useCallback(
54174
+ (updater) => {
54175
+ setSorting((prev) => {
54176
+ const newSorting = typeof updater === "function" ? updater(prev) : updater;
54177
+ const sorts = newSorting.map((s2) => ({
54178
+ columnKey: s2.id,
54179
+ direction: s2.desc ? "desc" : "asc"
54180
+ }));
54181
+ onSortChange == null ? void 0 : onSortChange(sorts);
54182
+ return newSorting;
54183
+ });
54184
+ },
54185
+ [onSortChange]
54186
+ );
54187
+ const [columnSizing, setColumnSizing] = useState({});
54188
+ const table = useReactTable({
54189
+ data: value.rows,
54190
+ columns,
54191
+ state: {
54192
+ sorting,
54193
+ columnSizing
54194
+ },
54195
+ onSortingChange: handleSortingChange,
54196
+ onColumnSizingChange: setColumnSizing,
54197
+ getCoreRowModel: getCoreRowModel(),
54198
+ getSortedRowModel: getSortedRowModel(),
54199
+ enableMultiSort,
54200
+ isMultiSortEvent: () => enableMultiSort,
54201
+ maxMultiSortColCount: maxSortColumns,
54202
+ enableColumnResizing,
54203
+ columnResizeMode: "onChange"
54204
+ });
54205
+ const { rows } = table.getRowModel();
54206
+ const columnSizeVars = useMemo(() => {
54207
+ const headers = table.getFlatHeaders();
54208
+ const colSizes = {};
54209
+ headers.forEach((header) => {
54210
+ colSizes[`--header-${header.id}-size`] = `${header.getSize()}px`;
54211
+ colSizes[`--col-${header.column.id}-size`] = `${header.column.getSize()}px`;
54212
+ });
54213
+ return colSizes;
54214
+ }, [table.getState().columnSizingInfo, table.getState().columnSizing]);
54215
+ const virtualizer = useVirtualizer({
54216
+ count: rows.length,
54217
+ getScrollElement: () => tableContainerRef.current,
54218
+ estimateSize: () => rowHeight,
54219
+ overscan
54220
+ });
54221
+ const virtualItems = virtualizer.getVirtualItems();
54222
+ useEffect(() => {
54223
+ const currentVisible = /* @__PURE__ */ new Set();
54224
+ virtualItems.forEach((item) => {
54225
+ currentVisible.add(item.index);
54226
+ });
54227
+ const prevVisible = visibleRowsRef.current;
54228
+ const load = [];
54229
+ currentVisible.forEach((key) => {
54230
+ const rowState = rowStateManager.getRowState(key);
54231
+ if (rowState.status === "unloaded") {
54232
+ load.push(key);
54233
+ }
54234
+ });
54235
+ const unload = [];
54236
+ prevVisible.forEach((key) => {
54237
+ if (!currentVisible.has(key)) {
54238
+ unload.push(key);
54239
+ }
54240
+ });
54241
+ if (load.length > 0) {
54242
+ rowStateManager.markRowsLoading(load);
54243
+ load.forEach((key) => rowStateManager.scheduleLoaded(key, loadingDelay));
54244
+ }
54245
+ if (unload.length > 0) {
54246
+ rowStateManager.markRowsUnloaded(unload);
54247
+ }
54248
+ visibleRowsRef.current = currentVisible;
54249
+ }, [virtualItems, rowStateManager, loadingDelay]);
54250
+ const getSortIndex = useCallback(
54251
+ (columnId) => {
54252
+ const idx = sorting.findIndex((s2) => s2.id === columnId);
54253
+ return idx >= 0 ? idx + 1 : void 0;
54254
+ },
54255
+ [sorting]
54256
+ );
54257
+ const handleTableScroll = useCallback(() => {
54258
+ if (tableContainerRef.current && timelineContainerRef.current) {
54259
+ timelineContainerRef.current.scrollTop = tableContainerRef.current.scrollTop;
54260
+ }
54261
+ }, []);
54262
+ const handleTimelineScroll = useCallback(() => {
54263
+ if (tableContainerRef.current && timelineContainerRef.current) {
54264
+ tableContainerRef.current.scrollTop = timelineContainerRef.current.scrollTop;
54265
+ }
54266
+ }, []);
54267
+ const panels = useMemo(() => [
54268
+ { id: "table", minSize: 20 },
54269
+ { id: "timeline", minSize: 20 }
54270
+ ], []);
54271
+ return /* @__PURE__ */ jsxs(
54272
+ Splitter.Root,
54273
+ {
54274
+ defaultSize: [tablePanelSize, 100 - tablePanelSize],
54275
+ panels,
54276
+ width: "100%",
54277
+ height,
54278
+ children: [
54279
+ /* @__PURE__ */ jsx(Splitter.Panel, { id: "table", children: /* @__PURE__ */ jsx(
54280
+ Box,
54281
+ {
54282
+ ref: tableContainerRef,
54283
+ height: "100%",
54284
+ overflowY: "auto",
54285
+ position: "relative",
54286
+ onScroll: handleTableScroll,
54287
+ children: /* @__PURE__ */ jsxs(
54288
+ Table.Root,
54289
+ {
54290
+ ...props,
54291
+ style: {
54292
+ ...columnSizeVars,
54293
+ width: "100%",
54294
+ minWidth: table.getCenterTotalSize(),
54295
+ tableLayout: "fixed"
54296
+ },
54297
+ children: [
54298
+ /* @__PURE__ */ jsx(
54299
+ Table.Header,
54300
+ {
54301
+ style: { display: "block" },
54302
+ position: "sticky",
54303
+ top: 0,
54304
+ zIndex: 1,
54305
+ bg: "bg.panel",
54306
+ children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx(
54307
+ Table.Row,
54308
+ {
54309
+ style: { display: "flex", width: "100%", height: `${headerHeight}px` },
54310
+ children: headerGroup.headers.map((header) => {
54311
+ const sortIndex = getSortIndex(header.id);
54312
+ const isSorted = header.column.getIsSorted();
54313
+ const sortDirection = isSorted || null;
54314
+ const icon3 = !isSorted ? faAnglesDown : sortDirection === "asc" ? faChevronUp : faChevronDown;
54315
+ return /* @__PURE__ */ jsxs(
54316
+ Table.ColumnHeader,
54317
+ {
54318
+ cursor: header.column.getCanSort() ? "pointer" : "default",
54319
+ _hover: header.column.getCanSort() ? { bg: "bg.muted" } : {},
54320
+ onClick: header.column.getToggleSortingHandler(),
54321
+ transition: "background 0.2s",
54322
+ style: {
54323
+ width: `var(--header-${header.id}-size)`,
54324
+ flex: columnSizing[header.id] ? "none" : 1
54325
+ },
54326
+ position: "relative",
54327
+ children: [
54328
+ /* @__PURE__ */ jsxs(
54329
+ HStack,
54330
+ {
54331
+ justify: "space-between",
54332
+ width: "100%",
54333
+ pr: enableColumnResizing ? "8px" : "0",
54334
+ children: [
54335
+ /* @__PURE__ */ jsx(
54336
+ Text$2,
54337
+ {
54338
+ fontSize: "sm",
54339
+ fontWeight: "semibold",
54340
+ overflow: "hidden",
54341
+ textOverflow: "ellipsis",
54342
+ whiteSpace: "nowrap",
54343
+ flex: "1",
54344
+ children: header.isPlaceholder ? null : flexRender(
54345
+ header.column.columnDef.header,
54346
+ header.getContext()
54347
+ )
54348
+ }
54349
+ ),
54350
+ /* @__PURE__ */ jsx(HStack, { gap: 1, flexShrink: 0, children: header.column.getCanSort() && /* @__PURE__ */ jsxs(
54351
+ IconButton,
54352
+ {
54353
+ "aria-label": `Sort by ${header.id}`,
54354
+ size: "xs",
54355
+ variant: "ghost",
54356
+ color: isSorted ? "fg.default" : "fg.muted",
54357
+ onClick: (e3) => {
54358
+ e3.stopPropagation();
54359
+ header.column.toggleSorting(
54360
+ void 0,
54361
+ enableMultiSort
54362
+ );
54363
+ },
54364
+ _hover: {
54365
+ bg: "bg.muted",
54366
+ color: "fg.default"
54367
+ },
54368
+ position: "relative",
54369
+ children: [
54370
+ /* @__PURE__ */ jsx(
54371
+ FontAwesomeIcon,
54372
+ {
54373
+ icon: icon3,
54374
+ style: {
54375
+ width: "12px",
54376
+ height: "12px"
54377
+ }
54378
+ }
54379
+ ),
54380
+ isSorted && sortIndex && /* @__PURE__ */ jsx(
54381
+ Box,
54382
+ {
54383
+ position: "absolute",
54384
+ top: "-2px",
54385
+ right: "-2px",
54386
+ bg: "fg.muted",
54387
+ color: "bg.panel",
54388
+ borderRadius: "full",
54389
+ width: "12px",
54390
+ height: "12px",
54391
+ display: "flex",
54392
+ alignItems: "center",
54393
+ justifyContent: "center",
54394
+ fontSize: "8px",
54395
+ fontWeight: "bold",
54396
+ children: sortIndex
54397
+ }
54398
+ )
54399
+ ]
54400
+ }
54401
+ ) })
54402
+ ]
54403
+ }
54404
+ ),
54405
+ enableColumnResizing && header.column.getCanResize() && /* @__PURE__ */ jsx(
54406
+ Box,
54407
+ {
54408
+ position: "absolute",
54409
+ right: "0",
54410
+ top: "0",
54411
+ bottom: "0",
54412
+ width: "8px",
54413
+ cursor: "col-resize",
54414
+ bg: "transparent",
54415
+ _hover: {
54416
+ _before: {
54417
+ opacity: 1,
54418
+ bg: "fg.muted"
54419
+ }
54420
+ },
54421
+ transition: "all 0.2s",
54422
+ zIndex: 10,
54423
+ onMouseDown: header.getResizeHandler(),
54424
+ onTouchStart: header.getResizeHandler(),
54425
+ _before: {
54426
+ content: '""',
54427
+ position: "absolute",
54428
+ right: "2px",
54429
+ top: "50%",
54430
+ transform: "translateY(-50%)",
54431
+ width: "2px",
54432
+ height: "16px",
54433
+ bg: "gray.300",
54434
+ borderRadius: "1px",
54435
+ opacity: 0.4,
54436
+ transition: "opacity 0.2s"
54437
+ }
54438
+ }
54439
+ )
54440
+ ]
54441
+ },
54442
+ header.id
54443
+ );
54444
+ })
54445
+ },
54446
+ headerGroup.id
54447
+ ))
54448
+ }
54449
+ ),
54450
+ /* @__PURE__ */ jsx(
54451
+ Table.Body,
54452
+ {
54453
+ style: {
54454
+ display: "block",
54455
+ position: "relative",
54456
+ height: `${virtualizer.getTotalSize()}px`
54457
+ },
54458
+ children: virtualItems.map((virtualRow) => {
54459
+ const row = rows[virtualRow.index];
54460
+ if (!row) return null;
54461
+ const rowKey = virtualRow.index;
54462
+ const rowState = rowStates.get(rowKey) || { status: "unloaded" };
54463
+ const isRowLoading = !rowStateManager.isRowLoaded(rowKey) || rowState.status === "loading";
54464
+ return /* @__PURE__ */ jsx(
54465
+ Table.Row,
54466
+ {
54467
+ style: {
54468
+ display: "flex",
54469
+ position: "absolute",
54470
+ top: 0,
54471
+ left: 0,
54472
+ width: "100%",
54473
+ height: `${virtualRow.size}px`,
54474
+ transform: `translateY(${virtualRow.start}px)`
54475
+ },
54476
+ children: row.getVisibleCells().map((cell) => {
54477
+ var _a;
54478
+ const cellValue = cell.getValue();
54479
+ const meta = cell.column.columnDef.meta;
54480
+ const cellStyle = {
54481
+ width: `var(--col-${cell.column.id}-size)`,
54482
+ flex: columnSizing[cell.column.id] ? "none" : 1
54483
+ };
54484
+ if (isRowLoading) {
54485
+ return /* @__PURE__ */ jsx(Table.Cell, { style: cellStyle, children: /* @__PURE__ */ jsx(Skeleton, { height: "20px", width: "80%" }) }, cell.id);
54486
+ }
54487
+ if (cellValue == null) {
54488
+ return /* @__PURE__ */ jsx(
54489
+ Table.Cell,
54490
+ {
54491
+ style: cellStyle
54492
+ },
54493
+ cell.id
54494
+ );
54495
+ }
54496
+ if (cellValue.content != null) {
54497
+ return /* @__PURE__ */ jsx(Table.Cell, { style: cellStyle, children: /* @__PURE__ */ jsx(
54498
+ EastChakraComponent,
54499
+ {
54500
+ value: cellValue.content
54501
+ }
54502
+ ) }, cell.id);
54503
+ }
54504
+ return /* @__PURE__ */ jsx(Table.Cell, { style: cellStyle, children: /* @__PURE__ */ jsx(Text$2, { children: ((_a = meta == null ? void 0 : meta.print) == null ? void 0 : _a.call(meta, cellValue.value.value)) ?? null }) }, cell.id);
54505
+ })
54506
+ },
54507
+ row.id
54508
+ );
54509
+ })
54510
+ }
54511
+ )
54512
+ ]
54513
+ }
54514
+ )
54515
+ }
54516
+ ) }),
54517
+ /* @__PURE__ */ jsx(Splitter.ResizeTrigger, { id: "table:timeline" }),
54518
+ /* @__PURE__ */ jsx(Splitter.Panel, { id: "timeline", children: /* @__PURE__ */ jsxs(
54519
+ Box,
54520
+ {
54521
+ ref: timelineContainerRef,
54522
+ width: "100%",
54523
+ height: "100%",
54524
+ overflowY: "auto",
54525
+ overflowX: "hidden",
54526
+ position: "relative",
54527
+ onScroll: handleTimelineScroll,
54528
+ children: [
54529
+ /* @__PURE__ */ jsx(Box, { position: "sticky", top: 0, zIndex: 1, bg: "bg.panel", children: /* @__PURE__ */ jsx(
54530
+ EventAxis,
54531
+ {
54532
+ startDate: dateRange.start,
54533
+ endDate: dateRange.end,
54534
+ width: timelineWidth,
54535
+ height: headerHeight
54536
+ }
54537
+ ) }),
54538
+ /* @__PURE__ */ jsxs(Box, { position: "relative", children: [
54539
+ /* @__PURE__ */ jsx(
54540
+ Table.Root,
54541
+ {
54542
+ ...props,
54543
+ style: {
54544
+ width: "100%",
54545
+ tableLayout: "fixed",
54546
+ position: "relative"
54547
+ },
54548
+ children: /* @__PURE__ */ jsx(
54549
+ Table.Body,
54550
+ {
54551
+ style: {
54552
+ display: "block",
54553
+ position: "relative",
54554
+ height: `${virtualizer.getTotalSize()}px`
54555
+ },
54556
+ children: virtualItems.map((virtualRow) => {
54557
+ const row = rows[virtualRow.index];
54558
+ if (!row) return null;
54559
+ return /* @__PURE__ */ jsx(
54560
+ Table.Row,
54561
+ {
54562
+ style: {
54563
+ display: "flex",
54564
+ position: "absolute",
54565
+ top: 0,
54566
+ left: 0,
54567
+ width: "100%",
54568
+ height: `${virtualRow.size}px`,
54569
+ transform: `translateY(${virtualRow.start}px)`
54570
+ },
54571
+ children: /* @__PURE__ */ jsx(
54572
+ Table.Cell,
54573
+ {
54574
+ style: { width: "100%", padding: 0 },
54575
+ children: /* @__PURE__ */ jsx("svg", { width: "100%", height: virtualRow.size, children: /* @__PURE__ */ jsx(
54576
+ GanttEventRow,
54577
+ {
54578
+ events: row.original.events,
54579
+ rowIndex: virtualRow.index,
54580
+ y: 0,
54581
+ width: timelineWidth,
54582
+ height: virtualRow.size,
54583
+ startDate: dateRange.start,
54584
+ endDate: dateRange.end,
54585
+ onEventClick
54586
+ }
54587
+ ) })
54588
+ }
54589
+ )
54590
+ },
54591
+ row.id
54592
+ );
54593
+ })
54594
+ }
54595
+ )
54596
+ }
54597
+ ),
54598
+ /* @__PURE__ */ jsx(
54599
+ "svg",
54600
+ {
54601
+ width: timelineWidth,
54602
+ height: virtualizer.getTotalSize(),
54603
+ style: {
54604
+ position: "absolute",
54605
+ top: 0,
54606
+ left: 0,
54607
+ pointerEvents: "none",
54608
+ zIndex: 1
54609
+ },
54610
+ children: gridLinePositions.map((x2, index) => /* @__PURE__ */ jsx(
54611
+ "line",
54612
+ {
54613
+ x1: x2,
54614
+ y1: 0,
54615
+ x2,
54616
+ y2: virtualizer.getTotalSize(),
54617
+ stroke: gridLineColor,
54618
+ strokeWidth: 1,
54619
+ strokeDasharray: "4 4",
54620
+ opacity: 0.6
54621
+ },
54622
+ `grid-${index}`
54623
+ ))
54624
+ }
54625
+ )
54626
+ ] })
54627
+ ]
54628
+ }
54629
+ ) })
54630
+ ]
54631
+ }
54632
+ );
54633
+ }, (prev, next) => ganttRootEqual(prev.value, next.value));
53742
54634
  const badgeEqual = equalFor(Badge$1.Types.Badge);
53743
54635
  function toChakraBadge(value) {
53744
54636
  var _a, _b, _c;
@@ -53851,7 +54743,7 @@ function toChakraDateTimeInput(value) {
53851
54743
  var _a, _b;
53852
54744
  const showTime = getSomeorUndefined(value.showTime);
53853
54745
  const dateValue = value.value instanceof Date ? value.value : new Date(value.value);
53854
- const formatDate = (d2) => {
54746
+ const formatDate2 = (d2) => {
53855
54747
  if (showTime) {
53856
54748
  return d2.toISOString().slice(0, 16);
53857
54749
  }
@@ -53859,9 +54751,9 @@ function toChakraDateTimeInput(value) {
53859
54751
  };
53860
54752
  return {
53861
54753
  type: showTime ? "datetime-local" : "date",
53862
- value: formatDate(dateValue),
53863
- min: getSomeorUndefined(value.min) ? formatDate(new Date(getSomeorUndefined(value.min))) : void 0,
53864
- max: getSomeorUndefined(value.max) ? formatDate(new Date(getSomeorUndefined(value.max))) : void 0,
54754
+ value: formatDate2(dateValue),
54755
+ min: getSomeorUndefined(value.min) ? formatDate2(new Date(getSomeorUndefined(value.min))) : void 0,
54756
+ max: getSomeorUndefined(value.max) ? formatDate2(new Date(getSomeorUndefined(value.max))) : void 0,
53865
54757
  variant: (_a = getSomeorUndefined(value.variant)) == null ? void 0 : _a.type,
53866
54758
  size: (_b = getSomeorUndefined(value.size)) == null ? void 0 : _b.type,
53867
54759
  disabled: getSomeorUndefined(value.disabled)
@@ -54456,6 +55348,7 @@ const EastChakraComponent = memo$2(function EastChakraComponent2({ value }) {
54456
55348
  // Collections
54457
55349
  DataList: (v2) => /* @__PURE__ */ jsx(EastChakraDataList, { value: v2 }),
54458
55350
  Table: (v2) => /* @__PURE__ */ jsx(EastChakraTable, { value: v2 }),
55351
+ Gantt: (v2) => /* @__PURE__ */ jsx(EastChakraGantt, { value: v2 }),
54459
55352
  // Charts
54460
55353
  Sparkline: (v2) => /* @__PURE__ */ jsx(EastChakraSparkline, { value: v2 }),
54461
55354
  AreaChart: (v2) => /* @__PURE__ */ jsx(EastChakraAreaChart, { value: v2 }),
@@ -54774,7 +55667,7 @@ export {
54774
55667
  toChakraStack,
54775
55668
  toChakraStringInput,
54776
55669
  toChakraSwitch,
54777
- toChakraTableRoot,
55670
+ toChakraTableRoot$1 as toChakraTableRoot,
54778
55671
  toChakraTabsContent,
54779
55672
  toChakraTabsRoot,
54780
55673
  toChakraTabsTrigger,