@esic-lab/data-core-ui 0.0.64 → 0.0.66

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.mjs CHANGED
@@ -555,9 +555,9 @@ function Checkbox({ label, checked, onChange, disabled }) {
555
555
  /* @__PURE__ */ jsx7(
556
556
  "div",
557
557
  {
558
- className: `flex justify-center items-center border-[1px] border-black w-[24px] h-[24px] rounded-[8px] transition-colors duration-100
559
- ${checked ? "bg-black text-white" : "bg-white text-black"}
560
- ${disabled ? "pointer-events-none" : ""}`,
558
+ className: `flex justify-center items-center border-[1px] border-gray-400 w-[24px] h-[24px] rounded-[8px] transition-colors duration-100
559
+ ${checked ? "bg-primary-500 text-white border-primary-500" : "bg-white text-black"}
560
+ ${disabled ? "pointer-events-none !bg-gray-300" : ""}`,
561
561
  children: /* @__PURE__ */ jsx7(
562
562
  "span",
563
563
  {
@@ -3823,7 +3823,7 @@ function AntDModal({ children, isOpen, width, onCancel }) {
3823
3823
  }
3824
3824
 
3825
3825
  // src/Indicator/Indicator/Indicator.tsx
3826
- import { IconCheck as IconCheck3, IconCirclePlus as IconCirclePlus2, IconPencil as IconPencil2, IconTrash as IconTrash4, IconX as IconX3 } from "@tabler/icons-react";
3826
+ import { IconCheck as IconCheck3, IconCirclePlus as IconCirclePlus2, IconTrash as IconTrash4, IconX as IconX3 } from "@tabler/icons-react";
3827
3827
  import { useState as useState16 } from "react";
3828
3828
  import { Input as Input4 } from "antd";
3829
3829
  import { Fragment as Fragment7, jsx as jsx41, jsxs as jsxs32 } from "react/jsx-runtime";
@@ -4077,7 +4077,7 @@ function Indicator({
4077
4077
  }
4078
4078
  ),
4079
4079
  /* @__PURE__ */ jsx41(IconX3, { className: "cursor-pointer text-red-600", onClick: handleCancelEditIndicator })
4080
- ] }) : void 0 : canEdit && /* @__PURE__ */ jsx41(IconPencil2, { className: "cursor-pointer", onClick: () => handleEditIndicator(index) }) }),
4080
+ ] }) : void 0 : false }),
4081
4081
  /* @__PURE__ */ jsx41("div", { className: "body-1 mt-2 cursor-pointer", children: /* @__PURE__ */ jsx41(
4082
4082
  IconTrash4,
4083
4083
  {
@@ -4733,14 +4733,21 @@ import { useEffect as useEffect11, useRef as useRef10, useState as useState20 }
4733
4733
  import * as d33 from "d3";
4734
4734
  import {
4735
4735
  format as format4,
4736
- getWeek,
4737
4736
  eachWeekOfInterval,
4738
4737
  startOfYear,
4739
4738
  endOfYear,
4740
4739
  startOfDay,
4741
4740
  addDays,
4742
- eachHourOfInterval
4741
+ eachHourOfInterval,
4742
+ getQuarter
4743
4743
  } from "date-fns";
4744
+ import { th } from "date-fns/locale";
4745
+ import {
4746
+ IconCircleX,
4747
+ IconClockExclamation,
4748
+ IconHourglassEmpty,
4749
+ IconRosetteDiscountCheck
4750
+ } from "@tabler/icons-react";
4744
4751
  import { jsx as jsx48, jsxs as jsxs39 } from "react/jsx-runtime";
4745
4752
  var LAYOUT = {
4746
4753
  barHeight: 40,
@@ -4758,31 +4765,33 @@ var VIEW_MODE_SCALE = {
4758
4765
  week: 10
4759
4766
  };
4760
4767
  var STATUS_META = {
4761
- pending: { color: "#F16965", label: "\u0E23\u0E2D\u0E14\u0E33\u0E40\u0E19\u0E34\u0E19\u0E01\u0E32\u0E23" },
4762
- "in-progress": { color: "#FFBB33", label: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E14\u0E33\u0E40\u0E19\u0E34\u0E19\u0E01\u0E32\u0E23" },
4763
- completed: { color: "#69C57D", label: "\u0E40\u0E2A\u0E23\u0E47\u0E08\u0E2A\u0E34\u0E49\u0E19" }
4764
- };
4765
- var THAI_MONTHS = {
4766
- January: "\u0E21.\u0E04.",
4767
- February: "\u0E01.\u0E1E.",
4768
- March: "\u0E21\u0E35.\u0E04.",
4769
- April: "\u0E40\u0E21.\u0E22.",
4770
- May: "\u0E1E.\u0E04.",
4771
- June: "\u0E21\u0E34.\u0E22.",
4772
- July: "\u0E01.\u0E04.",
4773
- August: "\u0E2A.\u0E04.",
4774
- September: "\u0E01.\u0E22.",
4775
- October: "\u0E15.\u0E04.",
4776
- November: "\u0E1E.\u0E22.",
4777
- December: "\u0E18.\u0E04."
4768
+ IN_PROGRESS: {
4769
+ color: "#FFC654",
4770
+ label: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E14\u0E33\u0E40\u0E19\u0E34\u0E19\u0E01\u0E32\u0E23",
4771
+ icon: /* @__PURE__ */ jsx48(IconHourglassEmpty, { className: "text-[#FFC654]" })
4772
+ },
4773
+ CANCEL: {
4774
+ color: "#D2D5DB",
4775
+ label: "\u0E22\u0E01\u0E40\u0E25\u0E34\u0E01",
4776
+ icon: /* @__PURE__ */ jsx48(IconCircleX, { className: "text-[#D2D5DB]" })
4777
+ },
4778
+ SUCCESS: {
4779
+ color: "#81CF92",
4780
+ label: "\u0E14\u0E33\u0E40\u0E19\u0E34\u0E19\u0E01\u0E32\u0E23\u0E41\u0E25\u0E49\u0E27\u0E40\u0E2A\u0E23\u0E47\u0E08",
4781
+ icon: /* @__PURE__ */ jsx48(IconRosetteDiscountCheck, { className: "text-[#81CF92]" })
4782
+ },
4783
+ COMPLETE: {
4784
+ color: "#81CF92",
4785
+ label: "\u0E40\u0E2A\u0E23\u0E47\u0E08\u0E2A\u0E34\u0E49\u0E19",
4786
+ icon: /* @__PURE__ */ jsx48(IconRosetteDiscountCheck, { className: "text-[#81CF92]" })
4787
+ },
4788
+ DELAY: {
4789
+ color: "#F4827E",
4790
+ label: "\u0E25\u0E48\u0E32\u0E0A\u0E49\u0E32",
4791
+ icon: /* @__PURE__ */ jsx48(IconClockExclamation, { className: "text-[#F4827E]" })
4792
+ }
4778
4793
  };
4779
- var THAI_DAYS = ["\u0E2D\u0E32.", "\u0E08.", "\u0E2D.", "\u0E1E.", "\u0E1E\u0E24.", "\u0E28.", "\u0E2A."];
4780
4794
  var roundedRectPath = (x, y, width, height, radius) => `M${x + radius},${y} H${x + width} V${y + height} H${x + radius} A${radius},${radius},0,0,1,${x},${y + height - radius} V${y + radius} A${radius},${radius},0,0,1,${x + radius},${y}`;
4781
- var formatThaiMonth = (date) => {
4782
- const monthName = format4(date, "MMMM");
4783
- return THAI_MONTHS[monthName] || monthName;
4784
- };
4785
- var formatThaiDate = (date) => date ? date.toLocaleDateString("th-TH", { day: "numeric", month: "short" }) : "-";
4786
4795
  var isDateOnlyValue = (dt) => {
4787
4796
  const localZero = dt.getHours() === 0 && dt.getMinutes() === 0 && dt.getSeconds() === 0 && dt.getMilliseconds() === 0;
4788
4797
  const utcZero = dt.getUTCHours() === 0 && dt.getUTCMinutes() === 0 && dt.getUTCSeconds() === 0 && dt.getUTCMilliseconds() === 0;
@@ -4812,60 +4821,46 @@ var getAdjustedEnd = (d) => {
4812
4821
  }
4813
4822
  return startOfDay(/* @__PURE__ */ new Date());
4814
4823
  };
4815
- var getStatusColor = (status2) => STATUS_META[status2]?.color ?? STATUS_META.pending.color;
4816
- var getStatusLabel = (status2) => STATUS_META[status2]?.label ?? STATUS_META.pending.label;
4817
- var ProjectRow = ({ element, barHeight, barSpacing }) => {
4824
+ var getStatusColor = (status2) => STATUS_META[status2]?.color ?? STATUS_META.IN_PROGRESS.color;
4825
+ var getStatusLabel = (status2) => STATUS_META[status2]?.label ?? STATUS_META.IN_PROGRESS.label;
4826
+ var ProjectRow = ({ element, barHeight, barSpacing, mode }) => {
4818
4827
  const safeStartDate = element.startDate instanceof Date ? element.startDate : null;
4819
4828
  const safeEndDate = element.endDate instanceof Date ? element.endDate : null;
4820
4829
  const safeStatus = element.status || "pending";
4821
4830
  const statusColor = getStatusColor(safeStatus);
4822
4831
  const statusLabel = getStatusLabel(safeStatus);
4832
+ const statusIcon = STATUS_META[safeStatus]?.icon;
4833
+ const toBuddhistDate = (d) => new Date(d.getFullYear() + 543, d.getMonth(), d.getDate());
4823
4834
  return /* @__PURE__ */ jsxs39(
4824
4835
  "div",
4825
4836
  {
4826
4837
  style: {
4827
- display: "grid",
4828
- gridTemplateColumns: "200px 100px 100px 100px",
4829
4838
  alignItems: "center",
4830
4839
  height: `${barHeight}px`,
4831
- fontSize: "12px",
4832
- marginBottom: `${barSpacing}px`
4840
+ marginBottom: `${barSpacing}px`,
4841
+ fontSize: "12px"
4833
4842
  },
4843
+ className: "body-1 grid grid-cols-[1fr_100px_130px] px-8 gap-2",
4834
4844
  children: [
4835
- /* @__PURE__ */ jsxs39("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
4836
- /* @__PURE__ */ jsx48(
4837
- "span",
4845
+ /* @__PURE__ */ jsxs39("div", { className: `grid ${mode === "project" ? "grid-cols-[10px_1fr]" : "grid-cols-[1fr]"} items-center gap-2`, children: [
4846
+ mode === "project" && /* @__PURE__ */ jsx48(
4847
+ "div",
4838
4848
  {
4839
4849
  style: {
4840
- display: "inline-block",
4841
- width: "10px",
4842
- height: "10px",
4843
- borderRadius: "50%",
4844
- backgroundColor: element.color || "#999"
4845
- }
4850
+ backgroundColor: element.color || "#E9E9E9"
4851
+ },
4852
+ className: "w-[10px] h-[10px] rounded-full"
4846
4853
  }
4847
4854
  ),
4848
- /* @__PURE__ */ jsx48("span", { style: { color: "#333" }, children: element.label })
4855
+ /* @__PURE__ */ jsx48("div", { className: "line-clamp-1 break-words text-[#333]", title: element.label, children: element.label })
4849
4856
  ] }),
4850
- /* @__PURE__ */ jsx48("div", { style: { color: "#666" }, children: formatThaiDate(safeStartDate) }),
4851
- /* @__PURE__ */ jsx48("div", { style: { color: "#666" }, children: formatThaiDate(safeEndDate) }),
4852
- /* @__PURE__ */ jsx48(
4853
- "button",
4854
- {
4855
- style: {
4856
- height: `${barHeight}px`,
4857
- minWidth: "100%",
4858
- padding: "4px 8px",
4859
- borderRadius: "4px",
4860
- fontSize: "11px",
4861
- backgroundColor: statusColor,
4862
- color: "#000",
4863
- border: "none",
4864
- cursor: "pointer"
4865
- },
4866
- children: statusLabel
4867
- }
4868
- )
4857
+ mode === "project" ? /* @__PURE__ */ jsx48("div", { children: safeEndDate ? format4(toBuddhistDate(safeEndDate), "dd MMM yyyy", { locale: th }) : "-" }) : /* @__PURE__ */ jsx48("div", { children: `Q${getQuarter(
4858
+ safeEndDate ?? /* @__PURE__ */ new Date()
4859
+ )}/${(safeEndDate?.getFullYear() ?? 0) + 543}` }),
4860
+ /* @__PURE__ */ jsxs39("button", { className: "rounded-md subtitile-1 flex gap-2 align-start", children: [
4861
+ statusIcon,
4862
+ statusLabel
4863
+ ] })
4869
4864
  ]
4870
4865
  },
4871
4866
  element.id
@@ -4880,42 +4875,52 @@ var RowOverlay = ({ data, barHeight, barSpacing, totalHeaderHeight }) => /* @__P
4880
4875
  left: 0,
4881
4876
  right: 0,
4882
4877
  height: `${data.length * (barHeight + barSpacing)}px`,
4883
- pointerEvents: "none",
4884
- zIndex: 5
4878
+ pointerEvents: "none"
4885
4879
  },
4886
- children: data.map((d, i) => {
4880
+ children: data.map((_, i) => {
4887
4881
  if (i === 0) return null;
4882
+ console.log("rendering row line", i);
4888
4883
  const yPos = i * (barHeight + barSpacing) - barSpacing / 2;
4889
4884
  return /* @__PURE__ */ jsx48(
4890
4885
  "div",
4891
4886
  {
4887
+ className: "",
4892
4888
  style: {
4893
4889
  position: "absolute",
4894
4890
  top: `${yPos}px`,
4895
4891
  left: 0,
4896
4892
  right: 0,
4897
4893
  height: "1px",
4898
- backgroundColor: "#d0d0d0"
4894
+ backgroundColor: "#E9E9E9"
4899
4895
  }
4900
4896
  },
4901
- `row-line-${d.id}`
4897
+ `row-line-${i}`
4902
4898
  );
4903
4899
  })
4904
4900
  }
4905
4901
  );
4906
- var GanttChart = ({ data, width, height }) => {
4902
+ var GanttChart = ({
4903
+ data,
4904
+ width,
4905
+ mode
4906
+ }) => {
4907
4907
  const svgRef = useRef10(null);
4908
4908
  const leftPanelRef = useRef10(null);
4909
4909
  const dataContainerRef = useRef10(null);
4910
4910
  const [viewMode] = useState20("year");
4911
- const { barHeight, barSpacing, headersGroupLayer1Height, headersGroupLayer2Height } = LAYOUT;
4911
+ const {
4912
+ barHeight,
4913
+ barSpacing,
4914
+ headersGroupLayer1Height,
4915
+ headersGroupLayer2Height
4916
+ } = LAYOUT;
4912
4917
  const totalHeaderHeight = headersGroupLayer1Height + headersGroupLayer2Height;
4913
4918
  useEffect11(() => {
4914
4919
  if (!data || !svgRef.current) return;
4915
4920
  const margin = { top: 0, right: 20, bottom: 20, left: 20 };
4916
4921
  const chartHeight = data.length * (barHeight + barSpacing) + margin.top + margin.bottom;
4917
4922
  const containerWidth = width * 2;
4918
- const containerHeight = totalHeaderHeight + chartHeight;
4923
+ const containerHeight = totalHeaderHeight + chartHeight > 585 ? totalHeaderHeight + chartHeight : 585;
4919
4924
  const borderRadius = 5;
4920
4925
  if (leftPanelRef.current) {
4921
4926
  leftPanelRef.current.style.height = `${containerHeight}px`;
@@ -4928,23 +4933,31 @@ var GanttChart = ({ data, width, height }) => {
4928
4933
  const chartGroup = svg.append("g").attr("transform", `translate(${margin.left}, ${totalHeaderHeight})`);
4929
4934
  const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
4930
4935
  const domainStart = startOfDay(startOfYear(new Date(currentYear, 0, 1)));
4931
- const domainEnd = startOfDay(addDays(endOfYear(new Date(currentYear, 0, 1)), 1));
4936
+ const domainEnd = startOfDay(
4937
+ addDays(endOfYear(new Date(currentYear, 0, 1)), 1)
4938
+ );
4932
4939
  const xScale = d33.scaleTime().domain([domainStart, domainEnd]).range([0, containerWidth - margin.left - margin.right]);
4933
4940
  const buildTimeBuckets = (domain) => ({
4934
4941
  uniqueYears: d33.timeYear.every(1)?.range(domain[0], domain[1]) || [],
4935
4942
  uniqueMonths: d33.timeMonth.every(1)?.range(domain[0], domain[1]) || [],
4936
- uniqueWeeks: eachWeekOfInterval({ start: domain[0], end: domain[1] }, { weekStartsOn: 1 }),
4937
- uniqueDays: d33.timeDay.range(startOfDay(domain[0]), startOfDay(addDays(domain[1], 1))) || []
4943
+ uniqueWeeks: eachWeekOfInterval(
4944
+ { start: domain[0], end: domain[1] },
4945
+ { weekStartsOn: 1 }
4946
+ ),
4947
+ uniqueDays: d33.timeDay.range(
4948
+ startOfDay(domain[0]),
4949
+ startOfDay(addDays(domain[1], 1))
4950
+ ) || []
4938
4951
  });
4939
4952
  const renderYearHeaders = (layer1, layer2, newXScale, buckets) => {
4940
4953
  layer1.selectAll(".year-bg").data(buckets.uniqueYears).enter().append("rect").attr("class", "year-bg").attr("x", (d) => newXScale(d)).attr("y", -totalHeaderHeight).attr("width", (d) => {
4941
4954
  const nextYearStart = startOfDay(new Date(d.getFullYear() + 1, 0, 1));
4942
4955
  return newXScale(nextYearStart) - newXScale(d);
4943
- }).attr("height", headersGroupLayer1Height).style("fill", "#fff").style("stroke", "#999").style("stroke-width", 1);
4956
+ }).attr("height", headersGroupLayer1Height).style("fill", "#fff").style("stroke", "#E9E9E9").style("stroke-width", 1);
4944
4957
  layer1.selectAll(".year-label").data(buckets.uniqueYears).enter().append("text").attr("class", "year-label").attr("x", (d) => {
4945
4958
  const nextYear = new Date(d.getFullYear() + 1, 0, 1);
4946
4959
  return newXScale(d) + (newXScale(nextYear) - newXScale(d)) / 2;
4947
- }).attr("y", -totalHeaderHeight + headersGroupLayer1Height / 2).attr("dy", "0.35em").attr("text-anchor", "middle").style("font-size", `${HEADER_FONTS.layer1}px`).style("font-weight", "bold").style("fill", "#0066cc").text((d) => `${d.getFullYear() + 543}`);
4960
+ }).attr("y", -totalHeaderHeight + headersGroupLayer1Height / 2).attr("dy", "0.35em").attr("text-anchor", "middle").style("font-size", `${HEADER_FONTS.layer1 + 2}px`).style("font-weight", "regular").style("fill", "#000").text((d) => `${d.getFullYear() + 543}`);
4948
4961
  const quarters2 = [];
4949
4962
  buckets.uniqueYears.forEach((year) => {
4950
4963
  for (let q = 0; q < 4; q++) {
@@ -4952,75 +4965,36 @@ var GanttChart = ({ data, width, height }) => {
4952
4965
  }
4953
4966
  });
4954
4967
  layer2.selectAll(".quarter-bg").data(quarters2).enter().append("rect").attr("class", "quarter-bg").attr("x", (d) => newXScale(d)).attr("y", -headersGroupLayer2Height).attr("width", (d) => {
4955
- const nextQuarter = startOfDay(new Date(d.getFullYear(), d.getMonth() + 3, 1));
4968
+ const nextQuarter = startOfDay(
4969
+ new Date(d.getFullYear(), d.getMonth() + 3, 1)
4970
+ );
4956
4971
  return newXScale(nextQuarter) - newXScale(d);
4957
- }).attr("height", headersGroupLayer2Height).style("fill", "#fff").style("stroke", "#999").style("stroke-width", 1);
4972
+ }).attr("height", headersGroupLayer2Height).style("fill", "#fff").style("stroke", "#E9E9E9").style("stroke-width", 1);
4958
4973
  layer2.selectAll(".quarter-label").data(quarters2).enter().append("text").attr("class", "quarter-label").attr("x", (d) => {
4959
- const nextQuarter = startOfDay(new Date(d.getFullYear(), d.getMonth() + 3, 1));
4974
+ const nextQuarter = startOfDay(
4975
+ new Date(d.getFullYear(), d.getMonth() + 3, 1)
4976
+ );
4960
4977
  return newXScale(d) + (newXScale(nextQuarter) - newXScale(d)) / 2;
4961
- }).attr("y", -headersGroupLayer2Height / 2).attr("dy", "0.35em").attr("text-anchor", "middle").style("font-size", `${HEADER_FONTS.layer2}px`).style("font-weight", "bold").style("fill", "#0088cc").text((d) => `\u0E44\u0E15\u0E23\u0E21\u0E32\u0E2A ${Math.floor(d.getMonth() / 3) + 1}`);
4962
- };
4963
- const renderMonthHeaders = (layer1, layer2, newXScale, buckets) => {
4964
- layer1.selectAll(".month-bg").data(buckets.uniqueMonths).enter().append("rect").attr("class", "month-bg").attr("x", (d) => newXScale(d)).attr("y", -totalHeaderHeight).attr("width", (d) => {
4965
- const nextMonth = startOfDay(new Date(d.getFullYear(), d.getMonth() + 1, 1));
4966
- return newXScale(nextMonth) - newXScale(d) + 11;
4967
- }).attr("height", headersGroupLayer1Height).style("fill", "#fff").style("stroke", "#999").style("stroke-width", 1);
4968
- layer1.selectAll(".month-label").data(buckets.uniqueMonths).enter().append("text").attr("class", "month-label").attr("x", (d) => {
4969
- const nextMonth = startOfDay(new Date(d.getFullYear(), d.getMonth() + 1, 1));
4970
- return newXScale(d) + (newXScale(nextMonth) - newXScale(d)) / 2;
4971
- }).attr("y", -totalHeaderHeight + headersGroupLayer1Height / 2).attr("dy", "0.35em").attr("text-anchor", "middle").style("font-size", `${HEADER_FONTS.layer1}px`).style("font-weight", "bold").style("fill", "#0066cc").text((d) => `${formatThaiMonth(d)} ${d.getFullYear() + 543}`);
4972
- layer2.selectAll(".week-bg").data(buckets.uniqueWeeks).enter().append("rect").attr("class", "week-bg").attr("x", (d) => newXScale(d)).attr("y", -headersGroupLayer2Height).attr("width", (d) => {
4973
- const weekEnd = startOfDay(addDays(d, 7));
4974
- return newXScale(weekEnd) - newXScale(d) + 1;
4975
- }).attr("height", headersGroupLayer2Height).style("fill", "#fff").style("stroke", "#999").style("stroke-width", 1);
4976
- layer2.selectAll(".week-label").data(buckets.uniqueWeeks).enter().append("text").attr("class", "week-label").attr("x", (d) => {
4977
- const weekEnd = startOfDay(addDays(d, 7));
4978
- return newXScale(d) + (newXScale(weekEnd) - newXScale(d)) / 2;
4979
- }).attr("y", -headersGroupLayer2Height / 2).attr("dy", "0.35em").attr("text-anchor", "middle").style("font-size", `${HEADER_FONTS.layer2}px`).style("font-weight", "bold").style("fill", "#0088cc").text((d) => `\u0E2A\u0E31\u0E1B\u0E14\u0E32\u0E2B\u0E4C\u0E17\u0E35\u0E48 ${getWeek(d, { weekStartsOn: 1 })}`);
4980
- };
4981
- const renderWeekHeaders = (layer1, layer2, newXScale, buckets) => {
4982
- layer1.selectAll(".week-bg").data(buckets.uniqueWeeks).enter().append("rect").attr("class", "week-bg").attr("x", (d) => newXScale(d)).attr("y", -totalHeaderHeight).attr("width", (d) => {
4983
- const weekEnd = startOfDay(addDays(d, 7));
4984
- return newXScale(weekEnd) - newXScale(d);
4985
- }).attr("height", headersGroupLayer1Height).style("fill", "#fff").style("stroke", "#999").style("stroke-width", 1);
4986
- layer1.selectAll(".week-label").data(buckets.uniqueWeeks).enter().append("text").attr("class", "week-label").attr("x", (d) => {
4987
- const weekEnd = startOfDay(addDays(d, 7));
4988
- return newXScale(d) + (newXScale(weekEnd) - newXScale(d)) / 2;
4989
- }).attr("y", -totalHeaderHeight + headersGroupLayer1Height / 2).attr("dy", "0.35em").attr("text-anchor", "middle").style("font-size", `${HEADER_FONTS.layer1}px`).style("font-weight", "bold").style("fill", "#0066cc").text((d) => `\u0E2A\u0E31\u0E1B\u0E14\u0E32\u0E2B\u0E4C\u0E17\u0E35\u0E48 ${getWeek(d, { weekStartsOn: 1 })}`);
4990
- layer2.selectAll(".day-bg").data(buckets.uniqueDays).enter().append("rect").attr("class", "day-bg").attr("x", (d) => newXScale(d)).attr("y", -headersGroupLayer2Height).attr("width", (d) => {
4991
- const nextDay = startOfDay(addDays(d, 1));
4992
- return newXScale(nextDay) - newXScale(d);
4993
- }).attr("height", headersGroupLayer2Height).style("fill", "#fff").style("stroke", "#999").style("stroke-width", 1);
4994
- layer2.selectAll(".day-of-week").data(buckets.uniqueDays).enter().append("text").attr("class", "day-of-week").attr("x", (d) => {
4995
- const nextDay = startOfDay(addDays(d, 1));
4996
- return newXScale(d) + (newXScale(nextDay) - newXScale(d)) / 2;
4997
- }).attr("y", -headersGroupLayer2Height / 2).attr("text-anchor", "middle").style("font-size", `${HEADER_FONTS.layer2}px`).style("font-weight", "bold").style("fill", "#0088cc").each(function(d) {
4998
- const textElement = d33.select(this);
4999
- textElement.text("");
5000
- textElement.append("tspan").text(THAI_DAYS[d.getDay()]).attr("x", textElement.attr("x")).attr("dy", "-0.3em");
5001
- textElement.append("tspan").text(format4(d, "d")).attr("x", textElement.attr("x")).attr("dy", "1.2em");
5002
- });
4978
+ }).attr("y", -headersGroupLayer2Height / 2).attr("dy", "0.35em").attr("text-anchor", "middle").style("font-size", `${HEADER_FONTS.layer2 + 3}px`).style("font-weight", "regular").style("fill", "#000").text((d) => `\u0E44\u0E15\u0E23\u0E21\u0E32\u0E2A ${Math.floor(d.getMonth() / 3) + 1}`);
5003
4979
  };
5004
4980
  const drawHeaders = (layer1, layer2, newXScale, buckets) => {
5005
- if (viewMode === "year") return renderYearHeaders(layer1, layer2, newXScale, buckets);
5006
- if (viewMode === "month") return renderMonthHeaders(layer1, layer2, newXScale, buckets);
5007
- return renderWeekHeaders(layer1, layer2, newXScale, buckets);
4981
+ return renderYearHeaders(layer1, layer2, newXScale, buckets);
5008
4982
  };
5009
- const getGridlineData = (mode, buckets, domain) => {
5010
- if (mode === "year") return buckets.uniqueMonths;
5011
- if (mode === "month") return buckets.uniqueWeeks;
5012
- if (mode === "week") return buckets.uniqueDays;
4983
+ const getGridlineData = (mode2, buckets, domain) => {
4984
+ if (mode2 === "year") return buckets.uniqueMonths;
4985
+ if (mode2 === "month") return buckets.uniqueWeeks;
4986
+ if (mode2 === "week") return buckets.uniqueDays;
5013
4987
  return eachHourOfInterval({ start: domain[0], end: domain[1] });
5014
4988
  };
5015
4989
  const drawGridlines = (group, gridlineData, newXScale) => {
5016
- group.selectAll(".gridline").data(gridlineData).enter().append("line").attr("class", "gridline").attr("x1", (d) => newXScale(d)).attr("x2", (d) => newXScale(d)).attr("y1", 0).attr("y2", chartHeight - margin.top - margin.bottom).attr("stroke", "#000").attr("stroke-width", 1).style("opacity", 0.3);
4990
+ group.selectAll(".gridline").data(gridlineData).enter().append("line").attr("class", "gridline").attr("x1", (d) => newXScale(d)).attr("x2", (d) => newXScale(d)).attr("y1", 0).attr("y2", containerHeight).attr("stroke", "#E9E9E9").attr("stroke-width", 1);
5017
4991
  };
5018
4992
  const drawRowSeparators = (group, getYPosition) => {
5019
4993
  const rowSeparatorGroup = group.append("g").attr("class", "row-separators");
5020
4994
  data.forEach((_d, i) => {
5021
4995
  if (i === 0) return;
5022
4996
  const y = getYPosition(i) - barSpacing / 2;
5023
- rowSeparatorGroup.append("line").attr("x1", 0).attr("x2", containerWidth - margin.left - margin.right).attr("y1", y).attr("y2", y).attr("stroke", "#d0d0d0").attr("stroke-width", 1).style("pointer-events", "none");
4997
+ rowSeparatorGroup.append("line").attr("x1", 0).attr("x2", containerWidth - margin.left - margin.right).attr("y1", y).attr("y2", y).attr("stroke", "#E9E9E9").attr("stroke-width", 1).style("pointer-events", "none");
5024
4998
  });
5025
4999
  rowSeparatorGroup.lower();
5026
5000
  };
@@ -5028,16 +5002,27 @@ var GanttChart = ({ data, width, height }) => {
5028
5002
  const barsGroup = group.append("g").attr("class", "bars-group");
5029
5003
  const renderBarHeight = barHeight;
5030
5004
  const labelPadding = 10;
5031
- barsGroup.selectAll(".bar-background").data(data).enter().append("rect").attr("class", "bar-background").attr("x", (d) => newXScale(getAdjustedStart(d))).attr("y", (_d, i) => getYPosition(i)).attr("height", renderBarHeight).attr("width", (d) => newXScale(getAdjustedEnd(d)) - newXScale(getAdjustedStart(d))).attr("fill", (d) => getStatusColor(d.status)).attr("rx", borderRadius).attr("ry", borderRadius);
5032
- barsGroup.selectAll(".bar-head").data(data).enter().append("path").attr("class", "bar-head").attr("fill", (d) => d.color).attr("d", (d, i) => {
5033
- const x = newXScale(getAdjustedStart(d));
5034
- const y = getYPosition(i);
5035
- const barWidth = newXScale(getAdjustedEnd(d)) - newXScale(getAdjustedStart(d));
5036
- const headWidth = Math.min(barWidth * 0.5, 20);
5037
- return roundedRectPath(x, y, headWidth, renderBarHeight, borderRadius);
5038
- });
5005
+ barsGroup.selectAll(".bar-background").data(data).enter().append("rect").attr("class", "bar-background").attr("x", (d) => newXScale(getAdjustedStart(d))).attr("y", (_d, i) => getYPosition(i)).attr("height", renderBarHeight).attr(
5006
+ "width",
5007
+ (d) => newXScale(getAdjustedEnd(d)) - newXScale(getAdjustedStart(d))
5008
+ ).attr("fill", (d) => getStatusColor(d.status)).attr("rx", borderRadius).attr("ry", borderRadius);
5009
+ {
5010
+ mode === "project" && barsGroup.selectAll(".bar-head").data(data).enter().append("path").attr("class", "bar-head").attr("fill", (d) => d.color).attr("d", (d, i) => {
5011
+ const x = newXScale(getAdjustedStart(d));
5012
+ const y = getYPosition(i);
5013
+ const barWidth = newXScale(getAdjustedEnd(d)) - newXScale(getAdjustedStart(d));
5014
+ const headWidth = Math.min(barWidth * 0.5, 20);
5015
+ return roundedRectPath(
5016
+ x,
5017
+ y,
5018
+ headWidth,
5019
+ renderBarHeight,
5020
+ borderRadius
5021
+ );
5022
+ });
5023
+ }
5039
5024
  const labels = group.append("g").attr("class", "labels");
5040
- const labelSelection = labels.selectAll(".label").data(data).enter().append("text").attr("class", "label").attr("y", (_d, i) => getYPosition(i) + renderBarHeight / 2).attr("dy", "0.35em").text((d) => d.label).style("fill", "black").style("font-size", "12px").style("pointer-events", "none");
5025
+ const labelSelection = labels.selectAll(".label").data(data).enter().append("text").attr("class", "label").attr("y", (_d, i) => getYPosition(i) + renderBarHeight / 2).attr("dy", "0.35em").text((d) => d.label).style("fill", "black").style("font-weight", "400").style("pointer-events", "none");
5041
5026
  labelSelection.each(function(d) {
5042
5027
  const barWidth = newXScale(getAdjustedEnd(d)) - newXScale(getAdjustedStart(d));
5043
5028
  const headWidth = Math.min(barWidth * 0.5, 20);
@@ -5060,8 +5045,17 @@ var GanttChart = ({ data, width, height }) => {
5060
5045
  const timeBuckets = buildTimeBuckets(newXScale.domain());
5061
5046
  const headersGroupLayer1 = chartGroup.append("g");
5062
5047
  const headersGroupLayer2 = chartGroup.append("g");
5063
- drawHeaders(headersGroupLayer1, headersGroupLayer2, newXScale, timeBuckets);
5064
- const gridlineData = getGridlineData(viewMode, timeBuckets, newXScale.domain());
5048
+ drawHeaders(
5049
+ headersGroupLayer1,
5050
+ headersGroupLayer2,
5051
+ newXScale,
5052
+ timeBuckets
5053
+ );
5054
+ const gridlineData = getGridlineData(
5055
+ viewMode,
5056
+ timeBuckets,
5057
+ newXScale.domain()
5058
+ );
5065
5059
  drawGridlines(headersGroupLayer2, gridlineData, newXScale);
5066
5060
  drawRowSeparators(chartGroup, getYPosition);
5067
5061
  drawBarsAndLabels(chartGroup, newXScale, getYPosition);
@@ -5079,7 +5073,6 @@ var GanttChart = ({ data, width, height }) => {
5079
5073
  }, [
5080
5074
  data,
5081
5075
  width,
5082
- height,
5083
5076
  viewMode,
5084
5077
  barHeight,
5085
5078
  barSpacing,
@@ -5090,13 +5083,13 @@ var GanttChart = ({ data, width, height }) => {
5090
5083
  return /* @__PURE__ */ jsx48(
5091
5084
  "div",
5092
5085
  {
5086
+ className: "body-1",
5093
5087
  style: {
5094
5088
  display: "flex",
5095
5089
  flexDirection: "column",
5096
- padding: "20px",
5097
5090
  width: `${width}px`,
5098
- height: `${height}px`,
5099
- border: "1px solid #ccc",
5091
+ height: `587px`,
5092
+ border: "1px solid #E9E9E9",
5100
5093
  borderRadius: "10px",
5101
5094
  backgroundColor: "#fff",
5102
5095
  overflow: "hidden"
@@ -5112,49 +5105,69 @@ var GanttChart = ({ data, width, height }) => {
5112
5105
  position: "relative"
5113
5106
  },
5114
5107
  children: [
5115
- /* @__PURE__ */ jsx48(RowOverlay, { data, barHeight, barSpacing, totalHeaderHeight }),
5108
+ /* @__PURE__ */ jsx48("div", { className: "z-2", children: /* @__PURE__ */ jsx48(
5109
+ RowOverlay,
5110
+ {
5111
+ data: data.length > 10 ? data : ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
5112
+ barHeight,
5113
+ barSpacing,
5114
+ totalHeaderHeight
5115
+ }
5116
+ ) }),
5116
5117
  /* @__PURE__ */ jsxs39(
5117
5118
  "div",
5118
5119
  {
5119
5120
  ref: leftPanelRef,
5121
+ className: "border-r",
5120
5122
  style: {
5121
5123
  width: "520px",
5122
5124
  minWidth: "500px",
5123
5125
  display: "flex",
5124
5126
  flexDirection: "column",
5125
5127
  backgroundColor: "#fff",
5126
- borderRight: "1px solid #ddd",
5127
5128
  zIndex: 2
5128
5129
  },
5129
5130
  children: [
5130
- /* @__PURE__ */ jsxs39(
5131
- "div",
5132
- {
5133
- style: {
5134
- display: "grid",
5135
- gridTemplateColumns: "200px 100px 100px 100px",
5136
- fontSize: "12px",
5137
- fontWeight: "bold",
5138
- color: "#666",
5139
- backgroundColor: "#fafafa",
5140
- borderBottom: "2px solid #ddd",
5141
- padding: "0 8px",
5142
- height: `${totalHeaderHeight}px`,
5143
- marginBottom: "10px",
5144
- position: "sticky",
5145
- top: 0,
5146
- alignItems: "center",
5147
- boxSizing: "border-box"
5131
+ /* @__PURE__ */ jsxs39("div", { ref: dataContainerRef, children: [
5132
+ /* @__PURE__ */ jsxs39(
5133
+ "div",
5134
+ {
5135
+ className: "grid body-2 grid-cols-[1fr_100px_130px] gap-2 px-8 border-b bg-white",
5136
+ style: {
5137
+ height: `${totalHeaderHeight}px`,
5138
+ marginBottom: "10px",
5139
+ position: "sticky",
5140
+ top: 0,
5141
+ alignItems: "center",
5142
+ zIndex: 5
5143
+ },
5144
+ children: [
5145
+ /* @__PURE__ */ jsx48("div", { children: "\u0E42\u0E04\u0E23\u0E07\u0E01\u0E32\u0E23" }),
5146
+ /* @__PURE__ */ jsx48("div", { children: "\u0E01\u0E33\u0E2B\u0E19\u0E14\u0E2A\u0E48\u0E07" }),
5147
+ /* @__PURE__ */ jsx48("div", { children: "\u0E2A\u0E16\u0E32\u0E19\u0E30" })
5148
+ ]
5149
+ }
5150
+ ),
5151
+ data.map((element) => /* @__PURE__ */ jsx48(
5152
+ ProjectRow,
5153
+ {
5154
+ mode,
5155
+ element,
5156
+ barHeight,
5157
+ barSpacing
5148
5158
  },
5149
- children: [
5150
- /* @__PURE__ */ jsx48("div", { children: "\u0E42\u0E04\u0E23\u0E07\u0E01\u0E32\u0E23" }),
5151
- /* @__PURE__ */ jsx48("div", { children: "\u0E27\u0E31\u0E19\u0E40\u0E23\u0E34\u0E48\u0E21" }),
5152
- /* @__PURE__ */ jsx48("div", { children: "\u0E01\u0E33\u0E2B\u0E19\u0E14\u0E2A\u0E48\u0E07" }),
5153
- /* @__PURE__ */ jsx48("div", { children: "\u0E2A\u0E16\u0E32\u0E19\u0E30" })
5154
- ]
5159
+ element.id
5160
+ ))
5161
+ ] }),
5162
+ /* @__PURE__ */ jsx48("div", { className: "z-3", children: /* @__PURE__ */ jsx48(
5163
+ RowOverlay,
5164
+ {
5165
+ data,
5166
+ barHeight,
5167
+ barSpacing,
5168
+ totalHeaderHeight
5155
5169
  }
5156
- ),
5157
- /* @__PURE__ */ jsx48("div", { ref: dataContainerRef, children: data.map((element) => /* @__PURE__ */ jsx48(ProjectRow, { element, barHeight, barSpacing }, element.id)) })
5170
+ ) })
5158
5171
  ]
5159
5172
  }
5160
5173
  ),
@@ -5236,7 +5249,7 @@ function CardKPI({
5236
5249
  /* @__PURE__ */ jsx49(ProgressBar, { percent: overallPercent, type: "line", checkpoints: [0] })
5237
5250
  ] }),
5238
5251
  /* @__PURE__ */ jsxs40("div", { className: "border-b", children: [
5239
- /* @__PURE__ */ jsx49("span", { className: "body-2 ", children: "\u0E15\u0E31\u0E27\u0E0A\u0E35\u0E49\u0E27\u0E31\u0E14\u0E1C\u0E25\u0E25\u0E31\u0E1E\u0E18\u0E4C" }),
5252
+ /* @__PURE__ */ jsx49("span", { className: "body-2 ", children: "\u0E01\u0E25\u0E38\u0E48\u0E21\u0E40\u0E1B\u0E49\u0E32\u0E2B\u0E21\u0E32\u0E22" }),
5240
5253
  indicator.filter((ind) => ind.indicatorType === "TARGET").map((item, index) => {
5241
5254
  if (index === 2) return;
5242
5255
  return /* @__PURE__ */ jsx49(KPIRow, { item });
@@ -5249,7 +5262,6 @@ function CardKPI({
5249
5262
  return /* @__PURE__ */ jsx49(KPIRow, { item });
5250
5263
  })
5251
5264
  ] }),
5252
- indicator.length === 0 && /* @__PURE__ */ jsx49("div", { className: "text-sm text-gray-500 italic", children: "\u0E44\u0E21\u0E48\u0E21\u0E35\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E42\u0E04\u0E23\u0E07\u0E01\u0E32\u0E23" }),
5253
5265
  indicator.filter((item) => item.indicatorType === "TARGET").length > 2 || indicator.filter((item) => item.indicatorType === "OUTPUT").length > 2 ? /* @__PURE__ */ jsx49("div", { className: "bottom-0 right-1/2 absolute text-gray-300", children: /* @__PURE__ */ jsx49(
5254
5266
  IconDots,
5255
5267
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@esic-lab/data-core-ui",
3
- "version": "0.0.64",
3
+ "version": "0.0.66",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",