ar-design 0.4.34 → 0.4.35

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.
@@ -127,7 +127,6 @@
127
127
  color: var(--white);
128
128
  font-size: 12px;
129
129
  overflow: hidden;
130
- z-index: 10;
131
130
  }
132
131
  }
133
132
  }
@@ -2,6 +2,7 @@ import React from "react";
2
2
  import { View } from "../../../libs/types";
3
3
  import { CalendarEvent } from "./IProps";
4
4
  interface IProps<T> {
5
+ trackedBy: keyof (T & CalendarEvent);
5
6
  data: (T & CalendarEvent)[];
6
7
  renderItem: (item: T, index: number) => React.JSX.Element;
7
8
  states: {
@@ -18,5 +19,5 @@ interface IProps<T> {
18
19
  locale?: Intl.LocalesArgument;
19
20
  };
20
21
  }
21
- declare const Body: <T>({ data, renderItem, states, config }: IProps<T>) => React.JSX.Element;
22
+ declare const Body: <T>({ trackedBy, data, renderItem, states, config }: IProps<T>) => React.JSX.Element;
22
23
  export default Body;
@@ -2,11 +2,11 @@ import React from "react";
2
2
  import Day from "./views/Day";
3
3
  import Week from "./views/Week";
4
4
  import Month from "./views/Month";
5
- const Body = function ({ data, renderItem, states, config }) {
5
+ const Body = function ({ trackedBy, data, renderItem, states, config }) {
6
6
  if (states.view.get === "Day")
7
7
  return React.createElement(Day, null);
8
8
  else if (states.view.get === "Week")
9
- return React.createElement(Week, { data: data, renderItem: renderItem, states: { currentDate: states.currentDate }, config: config });
9
+ return (React.createElement(Week, { trackedBy: trackedBy, data: data, renderItem: renderItem, states: { currentDate: states.currentDate }, config: config }));
10
10
  else if (states.view.get === "Month")
11
11
  return React.createElement(Month, null);
12
12
  return React.createElement(React.Fragment, null, "...");
@@ -3,6 +3,7 @@ export type CalendarEvent = {
3
3
  end: Date;
4
4
  };
5
5
  interface IProps<T> {
6
+ trackedBy: keyof (T & CalendarEvent);
6
7
  data: (T & CalendarEvent)[];
7
8
  renderItem: (item: T, index: number) => React.JSX.Element;
8
9
  config?: {
@@ -2,7 +2,7 @@ import React from "react";
2
2
  import IProps from "./IProps";
3
3
  import "../../../assets/css/components/data-display/calendar/styles.css";
4
4
  declare const Calendar: {
5
- <T>({ data, renderItem, config }: IProps<T>): React.JSX.Element;
5
+ <T>({ trackedBy, data, renderItem, config }: IProps<T>): React.JSX.Element;
6
6
  displayName: string;
7
7
  };
8
8
  export default Calendar;
@@ -3,7 +3,7 @@ import React, { useState } from "react";
3
3
  import Body from "./Body";
4
4
  import Header from "./Header";
5
5
  import "../../../assets/css/components/data-display/calendar/styles.css";
6
- const Calendar = function ({ data, renderItem, config }) {
6
+ const Calendar = function ({ trackedBy, data, renderItem, config }) {
7
7
  // states
8
8
  const [currentDate, setCurrentDate] = useState(new Date());
9
9
  const [view, setView] = useState("Week");
@@ -15,7 +15,7 @@ const Calendar = function ({ data, renderItem, config }) {
15
15
  set: setView,
16
16
  },
17
17
  }, config: config }),
18
- React.createElement(Body, { data: data, renderItem: renderItem, states: {
18
+ React.createElement(Body, { trackedBy: trackedBy, data: data, renderItem: renderItem, states: {
19
19
  currentDate: { get: currentDate, set: setCurrentDate },
20
20
  view: {
21
21
  get: view,
@@ -1,6 +1,7 @@
1
1
  import React from "react";
2
2
  import { CalendarEvent } from "../IProps";
3
3
  interface IProps<T> {
4
+ trackedBy: keyof (T & CalendarEvent);
4
5
  data: (T & CalendarEvent)[];
5
6
  renderItem: (item: T, index: number) => React.JSX.Element;
6
7
  states: {
@@ -14,5 +15,5 @@ interface IProps<T> {
14
15
  weekStartsOn?: number;
15
16
  };
16
17
  }
17
- declare const Week: <T>({ data, renderItem, states, config }: IProps<T>) => React.JSX.Element;
18
+ declare const Week: <T>({ trackedBy, data, renderItem, states, config }: IProps<T>) => React.JSX.Element;
18
19
  export default Week;
@@ -1,8 +1,6 @@
1
- import React, { useEffect, useMemo, useRef, useState } from "react";
1
+ import React, { useEffect, useMemo, useState } from "react";
2
2
  import ReactDOM from "react-dom";
3
- const Week = function ({ data, renderItem, states, config }) {
4
- // refs
5
- const _eventBox = useRef([]);
3
+ const Week = function ({ trackedBy, data, renderItem, states, config }) {
6
4
  // states
7
5
  const [mouseCoordinate, setMouseCoordinate] = useState({
8
6
  x: 0,
@@ -15,7 +13,7 @@ const Week = function ({ data, renderItem, states, config }) {
15
13
  const startHour = 0;
16
14
  const endHour = 24;
17
15
  const hours = endHour - startHour;
18
- const cellHeight = 60;
16
+ // const cellHeight = 60;
19
17
  // methods
20
18
  const weekDays = useMemo(() => getWeekDays(states.currentDate.get, config?.weekStartsOn ?? 1), [states.currentDate.get, config?.weekStartsOn]);
21
19
  // useEffects
@@ -44,46 +42,32 @@ const Week = function ({ data, renderItem, states, config }) {
44
42
  String(startHour + index).padStart(2, "0"),
45
43
  ":00"))))),
46
44
  React.createElement("div", { role: "grid", className: "grid" }, Array.from({ length: hours }).map((_, rowIndex) => (React.createElement("div", { key: rowIndex, className: "row" }, weekDays.map((_, colIndex) => (React.createElement("div", { key: colIndex, className: "cell" }))))))),
47
- React.createElement("div", { className: "events-layer" }, data.flatMap((event, eventIdx) => {
48
- const eventColor = getColor(eventIdx);
49
- // Her etkinlik için haftanın günlerini gezip, o güne düşen parçayı hesaplıyoruz
50
- return weekDays.map((day, dayIndex) => {
51
- const dayStart = new Date(day);
52
- dayStart.setHours(0, 0, 0, 0);
53
- const dayEnd = new Date(day);
54
- dayEnd.setHours(23, 59, 59, 999);
55
- // Etkinlik bu günle kesişiyor mu?
56
- const overlapStart = new Date(Math.max(event.start.getTime(), dayStart.getTime()));
57
- const overlapEnd = new Date(Math.min(event.end.getTime(), dayEnd.getTime()));
58
- if (overlapStart < overlapEnd) {
59
- // Bu güne düşen kısmın yükseklik ve top değerleri
60
- const startMinutes = overlapStart.getHours() * 60 + overlapStart.getMinutes();
61
- const durationMinutes = (overlapEnd.getTime() - overlapStart.getTime()) / 60000;
62
- const top = (startMinutes / 60) * cellHeight;
63
- const height = (durationMinutes / 60) * cellHeight;
64
- // Durum Kontrolleri
65
- const isContinuedFromYesterday = event.start < dayStart;
66
- const isContinuingTomorrow = event.end > dayEnd;
67
- return (React.createElement("div", { ref: (element) => {
68
- if (!element)
69
- return;
70
- _eventBox.current[dayIndex] = element;
71
- }, key: `${eventIdx}-${dayIndex}`, onMouseEnter: () => setActiveTooltip({ content: renderItem(event, eventIdx), id: eventIdx }), onMouseLeave: () => setActiveTooltip(null), className: "event-box", style: {
72
- backgroundColor: eventColor.bg,
73
- top: `${top}px`,
74
- height: `${height}px`,
75
- left: `${(100 / 7) * dayIndex}%`,
76
- width: `${100 / 7}%`,
77
- borderTop: isContinuedFromYesterday ? "none" : `1px solid ${eventColor.border}`,
78
- borderBottom: isContinuingTomorrow ? "none" : `1px solid ${eventColor.border}`,
79
- borderRadius: isContinuedFromYesterday
80
- ? "0 0 var(--border-radius-sm) var(--border-radius-sm)"
81
- : isContinuingTomorrow
82
- ? "var(--border-radius-sm) var(--border-radius-sm) 0 0"
83
- : "var(--border-radius-sm)",
84
- } }, !isContinuedFromYesterday && renderItem(event, eventIdx)));
85
- }
86
- return null;
45
+ React.createElement("div", { className: "events-layer" }, weekDays.map((day, dayIndex) => {
46
+ const dayStart = new Date(day).setHours(0, 0, 0, 0);
47
+ const dayEnd = new Date(day).setHours(23, 59, 59, 999);
48
+ // 1. Bu güne ait etkinlikleri filtrele ve sırala.
49
+ const dayEvents = data
50
+ .filter((event) => {
51
+ return event.start.getTime() <= dayEnd && event.end.getTime() >= dayStart;
52
+ })
53
+ .sort((a, b) => a.start.getTime() - b.start.getTime());
54
+ // 2. Çakışmaları hesapla (Görsel yerleşim için kritik adım).
55
+ const positionedEvents = computeEventLayout(dayEvents, dayStart, dayEnd);
56
+ return positionedEvents.map(({ event, layout, originalIndex }) => {
57
+ const uniqueValue = event[trackedBy];
58
+ const eventColor = getColor(uniqueValue);
59
+ return (React.createElement("div", { key: `${originalIndex}-${dayIndex}`, onMouseEnter: () => setActiveTooltip({ content: renderItem(event, originalIndex), id: originalIndex }), onMouseLeave: () => setActiveTooltip(null), className: "event-box", style: {
60
+ backgroundColor: eventColor.bg,
61
+ position: "absolute",
62
+ top: `${layout.top}px`,
63
+ height: `${layout.height}px`,
64
+ // Dinamik genişlik ve sol mesafe hesaplama.
65
+ left: `calc(${(100 / 7) * dayIndex}% + ${(layout.column * (100 / 7)) / layout.totalColumns}%)`,
66
+ width: `${100 / 7 / layout.totalColumns}%`,
67
+ border: `1px solid ${eventColor.border}`,
68
+ borderRadius: "var(--border-radius-sm)",
69
+ zIndex: 10,
70
+ } }, layout.height > 20 && renderItem(event, originalIndex)));
87
71
  });
88
72
  })))),
89
73
  activeTooltip &&
@@ -93,7 +77,62 @@ const Week = function ({ data, renderItem, states, config }) {
93
77
  transform: `translate(${mouseCoordinate.isRightHalf ? "-110%" : "10%"}, ${mouseCoordinate.isBottomHalf ? "-110%" : "10%"})`,
94
78
  } }, activeTooltip.content), document.body)));
95
79
  };
96
- // Yardımcı Fonksiyonlar aynı kalıyor
80
+ /**
81
+ * Etkinliklerin çakışma durumuna göre konumlarını hesaplayan yardımcı fonksiyon
82
+ */
83
+ function computeEventLayout(events, dayStart, dayEnd) {
84
+ const cellHeight = 60;
85
+ const results = [];
86
+ // Gruplandırma (Aynı anda çakışan etkinlik kümeleri)
87
+ let clusters = [];
88
+ let lastEventEnd = 0;
89
+ events.forEach((event, idx) => {
90
+ const start = Math.max(event.start.getTime(), dayStart);
91
+ const end = Math.min(event.end.getTime(), dayEnd);
92
+ if (start >= lastEventEnd) {
93
+ clusters.push([]); // Yeni bir küme başlat
94
+ }
95
+ const lastCluster = clusters[clusters.length - 1];
96
+ lastCluster.push({ event, idx, start, end });
97
+ lastEventEnd = Math.max(lastEventEnd, end);
98
+ });
99
+ // Her küme içindeki kolonları hesapla
100
+ clusters.forEach((cluster) => {
101
+ const columns = [];
102
+ cluster.forEach((item) => {
103
+ let placed = false;
104
+ for (let i = 0; i < columns.length; i++) {
105
+ // Eğer bu kolondaki son etkinlikle çakışmıyorsa buraya koy
106
+ const lastInColumn = columns[i][columns[i].length - 1];
107
+ if (item.start >= lastInColumn.end) {
108
+ columns[i].push(item);
109
+ placed = true;
110
+ break;
111
+ }
112
+ }
113
+ if (!placed) {
114
+ columns.push([item]); // Yeni kolon aç
115
+ }
116
+ });
117
+ // Sonuçları formatla
118
+ cluster.forEach((item) => {
119
+ const colIndex = columns.findIndex((col) => col.includes(item));
120
+ const startMinutes = new Date(item.start).getHours() * 60 + new Date(item.start).getMinutes();
121
+ const duration = (item.end - item.start) / 60000;
122
+ results.push({
123
+ event: item.event,
124
+ originalIndex: item.idx,
125
+ layout: {
126
+ top: (startMinutes / 60) * cellHeight,
127
+ height: (duration / 60) * cellHeight,
128
+ column: colIndex,
129
+ totalColumns: columns.length,
130
+ },
131
+ });
132
+ });
133
+ });
134
+ return results;
135
+ }
97
136
  const getWeekRange = (date, weekStartsOn = 1) => {
98
137
  const current = new Date(date);
99
138
  const currentDay = current.getDay();
@@ -122,7 +161,13 @@ const getColor = (id) => {
122
161
  { bg: "#e91e63", border: "#c2185b" }, // Pembe
123
162
  { bg: "#00bcd4", border: "#0097a7" }, // Turkuaz
124
163
  ];
125
- const index = typeof id === "number" ? id : id.length;
164
+ // Eğer id string ise karakter kodlarının toplamını alarak tutarlı bir index üretiriz
165
+ let hash = 0;
166
+ const identifier = String(id);
167
+ for (let i = 0; i < identifier.length; i++) {
168
+ hash = identifier.charCodeAt(i) + ((hash << 5) - hash);
169
+ }
170
+ const index = Math.abs(hash);
126
171
  return colors[index % colors.length];
127
172
  };
128
173
  export default Week;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ar-design",
3
- "version": "0.4.34",
3
+ "version": "0.4.35",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",