funda-ui 4.3.555 → 4.4.15

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.
Files changed (63) hide show
  1. package/Date/index.js +104 -0
  2. package/EventCalendar/index.css +7 -0
  3. package/EventCalendar/index.d.ts +2 -0
  4. package/EventCalendar/index.js +228 -89
  5. package/EventCalendarTimeline/index.css +29 -1
  6. package/EventCalendarTimeline/index.d.ts +11 -1
  7. package/EventCalendarTimeline/index.js +796 -298
  8. package/MultipleSelect/index.js +1 -1
  9. package/NativeSelect/index.js +1 -1
  10. package/Select/index.css +17 -0
  11. package/Select/index.d.ts +1 -0
  12. package/Select/index.js +83 -38
  13. package/Table/index.d.ts +4 -4
  14. package/Table/index.js +17 -17
  15. package/Tree/index.js +1 -1
  16. package/Utils/date.d.ts +27 -1
  17. package/Utils/date.js +92 -0
  18. package/lib/cjs/Date/index.js +104 -0
  19. package/lib/cjs/EventCalendar/index.d.ts +2 -0
  20. package/lib/cjs/EventCalendar/index.js +228 -89
  21. package/lib/cjs/EventCalendarTimeline/index.d.ts +11 -1
  22. package/lib/cjs/EventCalendarTimeline/index.js +796 -298
  23. package/lib/cjs/MultipleSelect/index.js +1 -1
  24. package/lib/cjs/NativeSelect/index.js +1 -1
  25. package/lib/cjs/Select/index.d.ts +1 -0
  26. package/lib/cjs/Select/index.js +83 -38
  27. package/lib/cjs/Table/index.d.ts +4 -4
  28. package/lib/cjs/Table/index.js +17 -17
  29. package/lib/cjs/Tree/index.js +1 -1
  30. package/lib/cjs/Utils/date.d.ts +27 -1
  31. package/lib/cjs/Utils/date.js +92 -0
  32. package/lib/css/EventCalendar/index.css +7 -0
  33. package/lib/css/EventCalendarTimeline/index.css +29 -1
  34. package/lib/css/Select/index.css +17 -0
  35. package/lib/esm/EventCalendar/index.scss +9 -0
  36. package/lib/esm/EventCalendar/index.tsx +203 -156
  37. package/lib/esm/EventCalendarTimeline/index.scss +46 -1
  38. package/lib/esm/EventCalendarTimeline/index.tsx +815 -358
  39. package/lib/esm/MultipleSelect/ItemList.tsx +1 -1
  40. package/lib/esm/MultipleSelect/index.tsx +1 -1
  41. package/lib/esm/NativeSelect/index.tsx +1 -1
  42. package/lib/esm/Select/index.scss +36 -1
  43. package/lib/esm/Select/index.tsx +179 -30
  44. package/lib/esm/Table/Table.tsx +2 -2
  45. package/lib/esm/Table/TableCell.tsx +2 -2
  46. package/lib/esm/Table/TableRow.tsx +1 -1
  47. package/lib/esm/Table/index.tsx +4 -4
  48. package/lib/esm/Tree/TreeList.tsx +1 -1
  49. package/lib/esm/Utils/libs/date.ts +101 -1
  50. package/package.json +1 -1
  51. /package/lib/esm/MultipleSelect/{multiple-select-utils → utils}/func.ts +0 -0
  52. /package/lib/esm/NativeSelect/{native-select-utils → utils}/func.ts +0 -0
  53. /package/lib/esm/Select/{select-utils → utils}/func.ts +0 -0
  54. /package/lib/esm/Table/{table-utils → utils}/DragHandleSprite.tsx +0 -0
  55. /package/lib/esm/Table/{table-utils → utils}/SortSprite.tsx +0 -0
  56. /package/lib/esm/Table/{table-utils → utils}/TableFilter.tsx +0 -0
  57. /package/lib/esm/Table/{table-utils → utils}/ToggleSelection.tsx +0 -0
  58. /package/lib/esm/Table/{table-utils → utils}/func.ts +0 -0
  59. /package/lib/esm/Table/{table-utils → utils}/hooks/useTableDraggable.tsx +0 -0
  60. /package/lib/esm/Table/{table-utils → utils}/hooks/useTableKeyPress.tsx +0 -0
  61. /package/lib/esm/Table/{table-utils → utils}/hooks/useTableResponsive.tsx +0 -0
  62. /package/lib/esm/Table/{table-utils → utils}/hooks/useTableSort.tsx +0 -0
  63. /package/lib/esm/Tree/{tree-utils.ts → utils/func.ts} +0 -0
@@ -9,11 +9,12 @@ import useClickOutside from 'funda-utils/dist/cjs/useClickOutside';
9
9
  import {
10
10
  getAbsolutePositionOfStage
11
11
  } from 'funda-utils/dist/cjs/getElementProperty';
12
- import { getTodayDate, getCalendarDate, isValidDate, padZero } from 'funda-utils/dist/cjs/date';
12
+ import { getTodayDate, getCalendarDate, isValidDate, padZero, getDateDetails, getMonthDates, getWeekDatesFromMon } from 'funda-utils/dist/cjs/date';
13
13
  import { clsWrite, combinedCls } from 'funda-utils/dist/cjs/cls';
14
14
 
15
15
 
16
16
 
17
+
17
18
  export interface EventsValueConfig {
18
19
  id: string | number;
19
20
  date: string,
@@ -50,12 +51,18 @@ export type EventCalendarTimelineProps = {
50
51
  tableListEndClassName?: string;
51
52
  tableListDividerClassName?: string;
52
53
  customTodayDate?: string;
54
+ multipleCells?: boolean;
55
+ appearance?: 'week' | 'month';
56
+ appearanceToggle?: boolean;
57
+ appearanceWeekTmpl?: (startDate: string, endDate: string) => void;
53
58
  eventsValue?: TimelineRowListConfig[];
54
59
  langWeek?: string[];
55
60
  langWeekFull?: string[];
56
61
  langMonths?: string[];
57
62
  langMonthsFull?: string[];
58
63
  langToday?: string;
64
+ langAppearanceLabelMonth?: string;
65
+ langAppearanceLabelWeek?: string
59
66
  iconRemove?: React.ReactNode | string;
60
67
  iconAdd?: React.ReactNode | string;
61
68
  cellCloseBtnClassName?: string;
@@ -70,7 +77,9 @@ export type EventCalendarTimelineProps = {
70
77
  onChangeMonth?: (currentData: any) => void;
71
78
  onChangeYear?: (currentData: any) => void;
72
79
  onChangeToday?: (currentData: any) => void;
80
+ onChangeWeek?: (startDate: string, endDate: string) => void;
73
81
  onListRenderComplete?: () => void;
82
+ onChangeAppearanceMode?: (mode: string) => void;
74
83
 
75
84
 
76
85
 
@@ -97,8 +106,10 @@ export type EventCalendarTimelineProps = {
97
106
  //
98
107
  onCellMouseEnter?: (el: any) => void;
99
108
  onCellMouseLeave?: (el: any) => void;
100
- onCellClick?: (el: any) => void;
101
-
109
+ onCellMouseUp?: (el: any, selectedCellsData: any[]) => void;
110
+ onCellClick?: (el: any, cellData: any) => void;
111
+ onKeyPressed?: (el: any, selectedCellsData: any[]) => void;
112
+
102
113
 
103
114
  // table
104
115
  tableListSectionTitle?: string | React.ReactNode;
@@ -127,13 +138,19 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
127
138
  tableListStartClassName,
128
139
  tableListEndClassName,
129
140
  tableListDividerClassName,
141
+ multipleCells = false,
130
142
  customTodayDate,
143
+ appearance = 'month',
144
+ appearanceToggle = true,
145
+ appearanceWeekTmpl,
131
146
  eventsValue,
132
147
  langWeek,
133
148
  langWeekFull,
134
149
  langMonths,
135
150
  langMonthsFull,
136
151
  langToday,
152
+ langAppearanceLabelMonth,
153
+ langAppearanceLabelWeek,
137
154
  iconRemove,
138
155
  iconAdd,
139
156
  cellCloseBtnClassName,
@@ -148,7 +165,9 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
148
165
  onChangeMonth,
149
166
  onChangeYear,
150
167
  onChangeToday,
168
+ onChangeWeek,
151
169
  onListRenderComplete,
170
+ onChangeAppearanceMode,
152
171
 
153
172
  //
154
173
  modalMaskOpacity,
@@ -173,7 +192,9 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
173
192
  //
174
193
  onCellMouseEnter,
175
194
  onCellMouseLeave,
195
+ onCellMouseUp,
176
196
  onCellClick,
197
+ onKeyPressed,
177
198
 
178
199
  //
179
200
  tableListSectionTitle,
@@ -190,6 +211,10 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
190
211
  id
191
212
  } = props;
192
213
 
214
+
215
+ //================================================================
216
+ // General
217
+ //================================================================
193
218
  const uniqueID = useComId();
194
219
  const idRes = id || uniqueID;
195
220
  const DAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
@@ -198,6 +223,12 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
198
223
  const WEEK_FULL = langWeekFull || ['MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 'SATURDAY', 'SUNDAY'];
199
224
  const MONTHS = langMonths || ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'];
200
225
  const MONTHS_FULL = langMonthsFull || ['January', 'Febuary', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
226
+ const formatToEnglishMonthDay = (inputDate: string) => {
227
+ const date = new Date(inputDate);
228
+ const month = MONTHS[date.getMonth()];
229
+ const day = date.getDate();
230
+ return month + ' ' + day;
231
+ };
201
232
 
202
233
  // orginal data
203
234
  const [val, setVal] = useState<TimelineRowListConfig[]>([]);
@@ -253,6 +284,10 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
253
284
  const [tableTooltipContent, setTableTooltipContent] = useState<any>(null);
254
285
 
255
286
 
287
+ // appearance mode
288
+ const [appearanceMode, setAppearanceMode] = useState<string>(appearance);
289
+
290
+
256
291
  // exposes the following methods
257
292
  useImperativeHandle(
258
293
  contentRef,
@@ -260,13 +295,125 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
260
295
  gridInit: () => {
261
296
  tableGridInit();
262
297
  },
298
+ gridInitHeadertitle: () => {
299
+ tableGridInitHeadertitle();
300
+ },
263
301
  gridReset: (cb?: any) => {
264
302
  tableGridReset();
303
+ },
304
+ resetSelectedCells: () => {
305
+ // reset selection area
306
+ setSelectedCells([]);
265
307
  }
266
308
  }),
267
309
  [contentRef],
268
310
  );
269
311
 
312
+
313
+
314
+ //================================================================
315
+ // Monthly calendar
316
+ //================================================================
317
+ //
318
+
319
+
320
+ //================================================================
321
+ // Weekly calendar
322
+ //================================================================
323
+ const [weekOffset, setWeekOffset] = useState<number>(0);
324
+ const handleNextWeek = () => {
325
+ setWeekOffset(weekOffset + 1);
326
+ return weekOffset + 1;
327
+ };
328
+ const handlePreviousWeek = () => {
329
+ setWeekOffset(weekOffset - 1)
330
+ return weekOffset - 1;
331
+ };
332
+ const weekDates = getWeekDatesFromMon(weekOffset);
333
+ const [displayWeekForHeader, setDisplayWeekForHeader] = useState<string[]>([]);
334
+
335
+
336
+
337
+
338
+
339
+ //================================================================
340
+ // Drag to activate the selection area
341
+ //================================================================
342
+ const [isSelecting, setIsSelecting] = useState<boolean>(false);
343
+ const [selectedCells, setSelectedCells] = useState<any[]>([]);
344
+ const [startCell, setStartCell] = useState<any>(null);
345
+ function handleTableMainMouseUp(e: React.MouseEvent) {
346
+ setIsSelecting(false);
347
+ }
348
+
349
+
350
+ // Determine whether it is a selected cell
351
+ const isCellSelected = (row: number, col: number) => {
352
+ return selectedCells.map((item: any) => [item.row, item.col]).some(([r, c]) => r === row && c === col);
353
+ };
354
+
355
+
356
+ // Selecting now
357
+ function handleTableMainCellMouseEnter(e: React.MouseEvent, row: number, col: number) {
358
+ const _el: any = e.currentTarget;
359
+
360
+ if (isSelecting && startCell) {
361
+
362
+ //########## MODE: WEEK #############
363
+ let curDateList: any[] = [];
364
+ if (appearanceMode === 'week') {
365
+ curDateList = weekDates.map((v: Date) => getCalendarDate(v));
366
+ }
367
+ //########## /MODE: WEEK #############
368
+
369
+ //########## MODE: MONTH #############
370
+ if (appearanceMode === 'month') {
371
+ curDateList = getMonthDates(year, month + 1);
372
+ }
373
+ //########## /MODE: MONTH #############
374
+
375
+
376
+ const newSelectedCells: any[] = [];
377
+ const [minRow, maxRow] = [startCell.row, row].sort((a, b) => a - b);
378
+ const [minCol, maxCol] = [startCell.col, col].sort((a, b) => a - b);
379
+
380
+ for (let r = minRow; r <= maxRow; r++) {
381
+ for (let c = minCol; c <= maxCol; c++) {
382
+
383
+ // query date and row data
384
+ const curRowData: any = val[r];
385
+ newSelectedCells.push({
386
+ rowData: curRowData?.listSection,
387
+ date: curDateList[c],
388
+ row: r,
389
+ col: c
390
+ });
391
+ }
392
+ }
393
+ setSelectedCells(newSelectedCells);
394
+ }
395
+ }
396
+
397
+ // Stop selecting
398
+ function handleTableMainCellMouseDown(e: React.MouseEvent, row: number, col: number) {
399
+ const _el: any = e.currentTarget;
400
+
401
+ setIsSelecting(true);
402
+ setStartCell({ row, col });
403
+ setSelectedCells([{
404
+ rowData: JSON.parse(_el.dataset.rowinfo),
405
+ date: _el.dataset.date,
406
+ row: row,
407
+ col: col
408
+ }]);
409
+ }
410
+
411
+
412
+
413
+
414
+ //================================================================
415
+ // Other
416
+ //================================================================
270
417
 
271
418
  // helper buttons
272
419
  const _delBtn = () => <>
@@ -301,80 +448,184 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
301
448
 
302
449
  // cell
303
450
  const getCells = (type: 'none' | 'forward' | 'back' = 'none') => {
451
+
452
+
453
+ //########## MODE: WEEK #############
454
+ if (appearanceMode === 'week') {
455
+ const curWeek: any[] = [];
456
+ weekDates.forEach((date: Date, dayIndex: number) => {
457
+ const _dayOfWeek = new Date(date).getDay();
458
+ // ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
459
+ const _daysIndicator = [7, 1, 2, 3, 4, 5, 6];
460
+ const _detail = getDateDetails(date);
461
+ const {
462
+ year: _temp_year,
463
+ month: _temp_month,
464
+ day: _temp_day
465
+ } = _detail;
466
+
467
+ curWeek.push({
468
+ month: Number(_temp_month) - 1,
469
+ startDay: _daysIndicator[_dayOfWeek],
470
+ row: 0,
471
+ col: [
472
+ dayIndex
473
+ ],
474
+ dateInfo: [
475
+ {
476
+ date: getCalendarDate(date),
477
+ firstGroup: false,
478
+ lastGroup: false,
479
+ validDisplayDate: true
480
+ }
481
+ ],
482
+ weekDisplay: [
483
+ WEEK[_daysIndicator[_dayOfWeek]-1]
484
+ ],
485
+ week: [
486
+ _daysIndicator[_dayOfWeek]-1
487
+ ]
488
+ });
489
+
490
+ });
304
491
 
305
- let currentMonth: any = month;
306
- let currentStartDay: any = startDay;
307
-
308
- // previous month
309
- if (type === 'forward') {
310
- const _date = new Date(year, currentMonth - 1, day);
311
- currentMonth = _date.getMonth();
312
- currentStartDay = getStartDayOfMonth(_date);
313
- }
314
-
315
- // next month
316
- if (type === 'back') {
317
- const _date = new Date(year, currentMonth + 1, day);
318
- currentMonth = _date.getMonth();
319
- currentStartDay = getStartDayOfMonth(_date);
492
+ return curWeek;
493
+
320
494
  }
321
-
322
-
323
- //
324
- const allDays = Array(days[currentMonth] + (currentStartDay - 1)).fill(null).map((_: any, i: number) => i); // [0,1,..,30,31]
325
- const rows = Math.ceil(allDays.length / 7); // 5
326
-
327
- return Array.from({ length: rows }).fill(null).map((_: any, i: number) => {
328
- const _col = allDays.slice(i * 7, (i + 1) * 7);
329
-
330
- // back fill
331
- const backFillArr: null[] = [];
332
- for (let k = 0; k < 7 - _col.length; k++) {
333
- backFillArr.push(null);
495
+ //########## /MODE: WEEK #############
496
+
497
+
498
+
499
+ //########## MODE: MONTH #############
500
+ if (appearanceMode === 'month') {
501
+ let currentMonth: any = month;
502
+ let currentStartDay: any = startDay;
503
+
504
+ // previous month
505
+ if (type === 'forward') {
506
+ const _date = new Date(year, currentMonth - 1, day);
507
+ currentMonth = _date.getMonth();
508
+ currentStartDay = getStartDayOfMonth(_date);
334
509
  }
335
- _col.splice(_col.length, 0, ...backFillArr as any);
336
-
337
- return {
338
- month: currentMonth,
339
- startDay: currentStartDay,
340
- row: i,
341
- col: _col
510
+
511
+ // next month
512
+ if (type === 'back') {
513
+ const _date = new Date(year, currentMonth + 1, day);
514
+ currentMonth = _date.getMonth();
515
+ currentStartDay = getStartDayOfMonth(_date);
342
516
  }
343
- });
344
- };
345
-
346
- const getForwardFill = () => {
347
- const prevMonthStartDay = getCells('forward').at(-1)?.startDay;
348
- const prevMonthLastRowNums: any = getCells('forward').at(-1)?.col.filter(Boolean);
349
-
350
- if (prevMonthLastRowNums) {
351
- if (prevMonthLastRowNums.length === 7) return []; // no remaining
352
-
353
- return prevMonthLastRowNums.map((dayIndex: number) => {
354
- const d = typeof dayIndex === 'number' ? dayIndex - (prevMonthStartDay - 2) : 0;
355
- return d;
517
+
518
+
519
+ //
520
+ const allDays = Array(days[currentMonth] + (currentStartDay - 1)).fill(null).map((_: any, i: number) => i); // [0,1,..,30,31]
521
+ const rows = Math.ceil(allDays.length / 7); // 5
522
+
523
+ //
524
+ const _tempCells: any[] = Array.from({ length: rows }).fill(null);
525
+
526
+ const _getForwardFill = (_year: number, _month: number) => {
527
+ // Get the last day of the previous month
528
+ const lastDayOfLastMonth = new Date(_year, _month - 1, 0);
529
+ const last7Days: Date[] = [];
530
+
531
+ // Rewind 7 days forward from the last day
532
+ for (let i = 0; i < 7; i++) {
533
+ last7Days.unshift(new Date(lastDayOfLastMonth));
534
+ lastDayOfLastMonth.setDate(lastDayOfLastMonth.getDate() - 1);
535
+ }
536
+ return last7Days.map((v: Date) => getCalendarDate(v));
537
+ };
538
+
539
+ const _getBackFill = (_year: number, _month: number) => {
540
+ // Get the first day of the next month
541
+ const firstDayOfNextMonth = new Date(_year, _month, 1);
542
+ const first7Days: Date[] = [];
543
+
544
+ // Rewind 7 days forward from the first day of the next month
545
+ for (let i = 0; i < 7; i++) {
546
+ first7Days.push(new Date(firstDayOfNextMonth));
547
+ firstDayOfNextMonth.setDate(firstDayOfNextMonth.getDate() + 1);
548
+ }
549
+
550
+ return first7Days.map((v: Date) => getCalendarDate(v));
551
+ };
552
+
553
+
554
+ return _tempCells.map((_: any, j: number) => {
555
+ const _col = allDays.slice(j * 7, (j + 1) * 7);
556
+
557
+ // back fill
558
+ const backFillArr: null[] = [];
559
+ for (let k = 0; k < 7 - _col.length; k++) {
560
+ backFillArr.push(null);
561
+ }
562
+ _col.splice(_col.length, 0, ...backFillArr as any);
563
+
564
+
565
+ //
566
+ const isFirstGroup = j === 0;
567
+ const isLastGroup = j === _tempCells.length - 1;
568
+
569
+
570
+ // forward fill
571
+ const __forwardFillDate: string[] = _getForwardFill(year, month+1);
572
+
573
+ // back fill
574
+ const __backFillDate: string[] = _getBackFill(year, month+1);
575
+
576
+
577
+ const _getDateShow = (_dayIndex: number, _m: number, _startDay: number, _month: number) => {
578
+ const currentDay = typeof _dayIndex === 'number' ? _dayIndex - (_startDay - 2) : 0; // ..., -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, ...
579
+
580
+ // date
581
+ let _dateShow: any = currentDay > 0 ? `${year}-${_month + 1}-${currentDay}` : '';
582
+
583
+ // forward & back
584
+ if (isFirstGroup && _dateShow === '') {
585
+ _dateShow = __forwardFillDate.at(currentDay-1);
586
+ }
587
+
588
+ if (isLastGroup && _dateShow === '') {
589
+ _dateShow = __backFillDate.at(_m);
590
+ }
591
+
592
+
593
+ return {
594
+ date: getCalendarDate(_dateShow),
595
+ firstGroup: isFirstGroup,
596
+ lastGroup: isLastGroup,
597
+ validDisplayDate: currentDay > 0 && currentDay <= days[month]
598
+ };
599
+
600
+ }
601
+
602
+ //
603
+ return {
604
+ month: currentMonth,
605
+ startDay: currentStartDay,
606
+ row: j,
607
+ col: _col,
608
+ dateInfo: _col.map((k: number, m: number) => {
609
+ const _lastWeekDays: number = _col.filter(Boolean).length;
610
+ return _getDateShow(k, m - _lastWeekDays, currentStartDay, currentMonth);
611
+ }),
612
+ weekDisplay: _col.map((k: number, m: number) => {
613
+ return WEEK[m]
614
+ }),
615
+ week: _col.map((k: number, m: number) => {
616
+ return m
617
+ }),
618
+
619
+ }
356
620
  });
357
- } else {
358
- return [];
359
621
  }
360
- };
622
+ //########## /MODE: MONTH #############
361
623
 
362
- const getBackFill = () => {
363
- const prevMonthStartDay = getCells('back').at(0)?.startDay;
364
- const prevMonthLastRowNums: any = getCells('back').at(0)?.col.filter(Boolean);
365
624
 
366
- if (prevMonthLastRowNums) {
367
- if (prevMonthLastRowNums.length === 7) return []; // no remaining
625
+ return [];
368
626
 
369
- return prevMonthLastRowNums.map((dayIndex: number) => {
370
- const d = typeof dayIndex === 'number' ? dayIndex - (prevMonthStartDay - 2) : 0;
371
- return d;
372
- }).filter((n: number) => n > 0);
373
- } else {
374
- return [];
375
- }
376
- };
377
627
 
628
+ };
378
629
 
379
630
  const queryItemObj = () => {
380
631
  const curRowData: any = val[tableRowNum];
@@ -571,53 +822,85 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
571
822
 
572
823
 
573
824
  function handlePrevChange() {
574
- setDate((prevState) => {
575
- const _date = new Date(year, month - 1, day);
576
825
 
577
- // update
578
- setSelectedMonth(_date.getMonth());
579
- setSelectedYear(_date.getFullYear());
826
+ //########## MODE: WEEK #############
827
+ if (appearanceMode === 'week') {
828
+ const _latestWeekOffset = handlePreviousWeek();
829
+ const weekDates: Date[] = getWeekDatesFromMon(_latestWeekOffset);
830
+ onChangeWeek?.(getCalendarDate(weekDates.at(0) as Date), getCalendarDate(weekDates.at(-1) as Date));
831
+ }
832
+ //########## /MODE: WEEK #############
580
833
 
581
- //
582
- onChangeMonth?.({
583
- day: padZero(day),
584
- month: padZero(_date.getMonth() + 1),
585
- year: _date.getFullYear().toString()
586
- });
587
834
 
588
- // restore table grid init status
589
- restoreTableGridInitStatus();
835
+ //########## MODE: MONTH #############
836
+ if (appearanceMode === 'month') {
837
+ setDate((prevState) => {
838
+ const _date = new Date(year, month - 1, day);
590
839
 
840
+ // update
841
+ setSelectedMonth(_date.getMonth());
842
+ setSelectedYear(_date.getFullYear());
843
+
844
+ //
845
+ onChangeMonth?.({
846
+ day: padZero(day),
847
+ month: padZero(_date.getMonth() + 1),
848
+ year: _date.getFullYear().toString()
849
+ });
850
+
851
+ // restore table grid init status
852
+ restoreTableGridInitStatus();
591
853
 
592
854
 
593
- return _date;
594
- });
595
855
 
856
+ return _date;
857
+ });
858
+
859
+ }
860
+ //########## /MODE: MONTH #############
861
+
596
862
 
597
863
  }
598
864
 
599
865
  function handleNextChange() {
600
- setDate((prevState) => {
601
- const _date = new Date(year, month + 1, day);
602
866
 
603
- // update
604
- setSelectedMonth(_date.getMonth());
605
- setSelectedYear(_date.getFullYear());
606
867
 
607
- //
608
- onChangeMonth?.({
609
- day: padZero(day),
610
- month: padZero(_date.getMonth() + 1),
611
- year: _date.getFullYear().toString()
612
- });
868
+ //########## MODE: WEEK #############
869
+ if (appearanceMode === 'week') {
870
+ const _latestWeekOffset = handleNextWeek();
871
+ const weekDates: Date[] = getWeekDatesFromMon(_latestWeekOffset);
872
+ onChangeWeek?.(getCalendarDate(weekDates.at(0) as Date), getCalendarDate(weekDates.at(-1) as Date));
873
+ }
874
+ //########## /MODE: WEEK #############
613
875
 
614
876
 
615
- // restore table grid init status
616
- restoreTableGridInitStatus();
877
+ //########## MODE: MONTH #############
878
+ if (appearanceMode === 'month') {
879
+ setDate((prevState) => {
880
+ const _date = new Date(year, month + 1, day);
617
881
 
882
+ // update
883
+ setSelectedMonth(_date.getMonth());
884
+ setSelectedYear(_date.getFullYear());
618
885
 
619
- return _date;
620
- });
886
+ //
887
+ onChangeMonth?.({
888
+ day: padZero(day),
889
+ month: padZero(_date.getMonth() + 1),
890
+ year: _date.getFullYear().toString()
891
+ });
892
+
893
+
894
+ // restore table grid init status
895
+ restoreTableGridInitStatus();
896
+
897
+
898
+ return _date;
899
+ });
900
+ }
901
+ //########## /MODE: MONTH #############
902
+
903
+
621
904
  }
622
905
  function handleDayChange(e: React.MouseEvent, currentDay: number) {
623
906
  setDate(new Date(year, month, currentDay));
@@ -673,11 +956,27 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
673
956
  year: _now[0]
674
957
  });
675
958
 
959
+ //
960
+ const weekDates: Date[] = getWeekDatesFromMon(0);
961
+ onChangeWeek?.(getCalendarDate(weekDates.at(0) as Date), getCalendarDate(weekDates.at(-1) as Date));
962
+ setWeekOffset(0);
963
+
964
+
676
965
  // restore table grid init status
677
966
  restoreTableGridInitStatus();
678
967
 
679
968
  }
680
969
 
970
+ function handleAppearanceChange(e: React.MouseEvent) {
971
+ const _mode = (e.target as any).dataset.mode;
972
+ setAppearanceMode(_mode);
973
+
974
+ //
975
+ onChangeAppearanceMode?.(_mode);
976
+ }
977
+
978
+
979
+
681
980
 
682
981
  function handleShowWinYear() {
683
982
  setWinYear((prevState: boolean) => !prevState);
@@ -717,64 +1016,42 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
717
1016
  return getCells().map((item: any, j: number) => {
718
1017
 
719
1018
 
720
- const isFirstRow = j === 0;
721
- const isLastRow = j === getCells().length - 1;
722
-
723
- // forward fill
724
- const __forwardFillNum: number[] = getForwardFill();
725
-
726
- // back fill
727
- const __backFillNum: number[] = getBackFill();
728
-
729
-
730
-
731
- return item.col.map((dayIndex: number | null, i: number) => {
1019
+
1020
+ return item.col.map((dayIndex: number, i: number) => {
732
1021
 
733
1022
  colIndex++;
734
1023
 
735
- const d = typeof dayIndex === 'number' ? dayIndex - (startDay - 2) : 0;
736
- const _currentData = eventSourcesData.filter((item: any) => getCalendarDate(item.date as string) === getCalendarDate(`${year}-${month + 1}-${d}`));
737
- const isLastCol = colIndex === 7 * getCells().length;
738
-
739
1024
 
740
1025
  // date
741
- let _dateShow = d > 0 ? `${year}-${month + 1}-${d}` : '';
742
-
743
-
744
- // forward & back
745
- if (isFirstRow && __forwardFillNum && _dateShow === '') {
746
- if (month + 1 === 1) {
747
- _dateShow = `${year - 1}-12-${__forwardFillNum[i]}`;
748
- } else {
749
- _dateShow = `${year}-${month}-${__forwardFillNum[i]}`;
750
- }
751
- }
752
-
753
- if (isLastRow && __backFillNum && _dateShow === '') {
754
- if (month + 1 === 12) {
755
- _dateShow = `${year + 1}-1-${__backFillNum[i - item.col.filter(Boolean).length]}`;
756
- } else {
757
- _dateShow = `${year}-${month + 2}-${__backFillNum[i - item.col.filter(Boolean).length]}`;
758
- }
759
- }
760
-
761
-
762
-
1026
+ const _dateShow = item.dateInfo[i].date;
1027
+ const _dateDayShow = _dateShow.split('-').at(-1);
1028
+
1029
+ // week day
1030
+ const weekDay = item.week[i];
1031
+ const _weekDayStr = SHOW_WEEK ? <span dangerouslySetInnerHTML={{
1032
+ __html: item.weekDisplay[i]
1033
+ }} /> : null;
1034
+
1035
+ // helper
1036
+ const d = parseFloat(_dateDayShow);
1037
+ const _currentData = eventSourcesData.filter((item: any) => getCalendarDate(item.date as string) === _dateShow);
1038
+ const isLastCol = colIndex === 7 * getCells().length;
1039
+ const isInteractive = item.dateInfo[i].validDisplayDate; // The date on which the user interaction can occur, e.g. click, modify
1040
+ const isForward = item.dateInfo[i].firstGroup && !isInteractive;
1041
+ const isBack = item.dateInfo[i].lastGroup && !isInteractive;
1042
+
1043
+
763
1044
  // days
764
1045
  //------
765
1046
  if (!showEvents) {
766
1047
 
767
1048
  const _thContent = () => {
768
1049
 
769
- const isForward = isFirstRow && __forwardFillNum && typeof __forwardFillNum[i] !== 'undefined';
770
- const isBack = isLastRow && __backFillNum && typeof __backFillNum[i - item.col.filter(Boolean).length] !== 'undefined';
771
-
772
-
773
1050
  return <th
774
1051
  className={combinedCls(
775
1052
  'e-cal-timeline-table__cell-cushion-headercontent__container',
776
1053
  {
777
- 'empty': d <= 0,
1054
+ 'empty': !isInteractive,
778
1055
  'today': d === now.getDate(),
779
1056
  'selected': d === day,
780
1057
  'last-cell': isLastCol
@@ -784,12 +1061,14 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
784
1061
  data-index={colIndex - 1}
785
1062
  data-datagrid-col={colIndex - 1}
786
1063
  colSpan={1}
787
- data-date={getCalendarDate(_dateShow)}
788
- data-day={padZero(d)}
789
- data-week={i}
1064
+ data-date={_dateShow}
1065
+ data-day={_dateDayShow}
1066
+ data-week={weekDay}
790
1067
  style={{ minWidth: CELL_MIN_W + 'px' }}
791
- onClick={(e: React.MouseEvent) => {
792
-
1068
+ onMouseEnter={(e: React.MouseEvent) => {
1069
+ onCellMouseEnter?.(e);
1070
+ }}
1071
+ onMouseDown={(e: React.MouseEvent) => {
793
1072
  // update row data
794
1073
  setTableRowNum(-1);
795
1074
 
@@ -800,61 +1079,52 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
800
1079
  _currentData[0].rowData = listSectionData;
801
1080
  }
802
1081
 
1082
+ // reset selection area
1083
+ setSelectedCells([]);
1084
+
803
1085
 
804
1086
  //
805
- if (d > 0) {
1087
+ if (isInteractive) {
806
1088
  handleDayChange(e, d); // update current day
807
1089
 
808
1090
  onChangeDate?.(e, _currentData.length === 0 ? {
809
1091
  rowData: listSectionData,
810
1092
  id: 0,
811
- date: getCalendarDate(`${year}-${month + 1}-${d}`)
1093
+ date: _dateShow
812
1094
  } : _currentData[0]);
813
1095
 
814
1096
  if (EVENTS_ENABLED) {
815
1097
  onModalEditOpen?.(_currentData.length === 0 ? {
816
1098
  rowData: listSectionData,
817
1099
  id: 0,
818
- date: getCalendarDate(`${year}-${month + 1}-${d}`)
1100
+ date: _dateShow
819
1101
  } : _currentData[0], () => setShowEdit(true), 'normal');
820
1102
  }
821
1103
  }
1104
+
1105
+ }}
1106
+ onMouseLeave={(e: React.MouseEvent) => {
1107
+ onCellMouseLeave?.(e);
1108
+ }}
1109
+ onMouseUp={(e: React.MouseEvent) => {
1110
+ onCellMouseUp?.(e, selectedCells);
822
1111
  }}
823
1112
  >
824
1113
 
825
-
826
- {/* forward fill */}
827
- {!FILL_BLANK_DATE_DISABLD && isForward ? <>
828
- <div className="e-cal-timeline-table__cell-cushion e-cal-timeline-table__cell-cushion-headercontent disabled" style={{ width: (CELL_MIN_W - 1) + 'px' }}>
829
- {__forwardFillNum[i]}
830
- </div>
831
- </> : null}
832
-
833
-
834
-
835
- {/* day */}
836
- {d > 0 ? <>
837
- {FILL_BLANK_DATE_DISABLD ? <>
838
- <div className="e-cal-timeline-table__cell-cushion e-cal-timeline-table__cell-cushion-headercontent" style={{ width: (CELL_MIN_W - 1) + 'px' }}>
839
- {d}
840
- {SHOW_WEEK ? <span dangerouslySetInnerHTML={{
841
- __html: WEEK[i]
842
- }} /> : null}
843
- </div>
844
- </> : <>
845
- <div className="e-cal-timeline-table__cell-cushion e-cal-timeline-table__cell-cushion-headercontent" style={{ width: (CELL_MIN_W - 1) + 'px' }}>
846
- {d}
847
- </div>
848
- </>}
849
- </> : null}
850
-
851
- {/* back fill */}
852
- {!FILL_BLANK_DATE_DISABLD && isBack ? <>
853
- <div className="e-cal-timeline-table__cell-cushion e-cal-timeline-table__cell-cushion-headercontent disabled" style={{ width: (CELL_MIN_W - 1) + 'px' }}>
854
- {__backFillNum[i - item.col.filter(Boolean).length]}
855
- </div>
856
- </> : null}
857
-
1114
+
1115
+ {/* forward fill & day & back fill */}
1116
+ <div
1117
+ className={combinedCls(
1118
+ 'e-cal-timeline-table__cell-cushion e-cal-timeline-table__cell-cushion-headercontent',
1119
+ {
1120
+ 'disabled': !isInteractive
1121
+ }
1122
+ )}
1123
+ style={{ width: (CELL_MIN_W - 1) + 'px' }}
1124
+ >
1125
+ {d}
1126
+ {_weekDayStr}
1127
+ </div>
858
1128
 
859
1129
 
860
1130
  </th>;
@@ -863,10 +1133,11 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
863
1133
  if (!FILL_BLANK_DATE_DISABLD) {
864
1134
  return <>{_thContent()}</>;
865
1135
  } else {
866
- return d > 0 && d <= days[month] ? (
1136
+ return isInteractive ? (
867
1137
  <>{_thContent()}</>
868
1138
  ) : null;
869
1139
  }
1140
+
870
1141
  }
871
1142
 
872
1143
 
@@ -910,9 +1181,9 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
910
1181
  key={`cell-item-${rowIndex}-${cellItemIndex}}`}
911
1182
  data-overlay-id={`e-cal-timeline-table__cell-tooltipwrapper-${idRes}`}
912
1183
  data-cell-item-index={cellItemIndex}
913
- data-date={getCalendarDate(_dateShow)}
914
- data-day={padZero(d)}
915
- data-week={i}
1184
+ data-date={_dateShow}
1185
+ data-day={_dateDayShow}
1186
+ data-week={weekDay}
916
1187
  data-row={rowIndex}
917
1188
  onMouseEnter={(e: React.MouseEvent) => {
918
1189
  e.stopPropagation();
@@ -951,7 +1222,7 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
951
1222
 
952
1223
 
953
1224
  //
954
- if (d > 0) {
1225
+ if (isInteractive) {
955
1226
  handleDayChange(e, d); // update current day
956
1227
 
957
1228
 
@@ -970,10 +1241,12 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
970
1241
  <div
971
1242
  className="e-cal-timeline__day__event"
972
1243
  style={typeof cellItem !== 'undefined' && (cellItem as any).eventStyles !== 'undefined' ? cellItem.eventStyles : {}}
973
- dangerouslySetInnerHTML={{
1244
+ dangerouslySetInnerHTML={typeof cellItem.data === 'string' ? {
974
1245
  __html: cellItem.data
975
- }}
976
- ></div>
1246
+ } : undefined}
1247
+ >
1248
+ {React.isValidElement(cellItem.data) ? <>{cellItem.data}</> : null}
1249
+ </div>
977
1250
  {/* /ITEM */}
978
1251
 
979
1252
  {/* DELETE BUTTON */}
@@ -984,9 +1257,9 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
984
1257
  href="#"
985
1258
  tabIndex={-1}
986
1259
  className="align-middle"
987
- data-date={getCalendarDate(_dateShow)}
988
- data-day={padZero(d)}
989
- data-week={i}
1260
+ data-date={_dateShow}
1261
+ data-day={_dateDayShow}
1262
+ data-week={weekDay}
990
1263
  data-row={rowIndex}
991
1264
  onClick={(e: React.MouseEvent) => {
992
1265
  e.preventDefault();
@@ -1005,13 +1278,13 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1005
1278
  }
1006
1279
 
1007
1280
  //
1008
- if (d > 0) {
1281
+ if (isInteractive) {
1009
1282
  handleDayChange(e, d); // update current day
1010
1283
 
1011
1284
  onChangeDate?.(e, {
1012
1285
  rowData: listSectionData,
1013
1286
  id: 0,
1014
- date: getCalendarDate(`${year}-${month + 1}-${d}`)
1287
+ date: _dateShow
1015
1288
  });
1016
1289
 
1017
1290
  if (EVENTS_DELETE_ENABLED) {
@@ -1036,59 +1309,69 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1036
1309
 
1037
1310
  const _tdContent = () => {
1038
1311
 
1039
- const isForward = isFirstRow && __forwardFillNum && typeof __forwardFillNum[i] !== 'undefined';
1040
- const isBack = isLastRow && __backFillNum && typeof __backFillNum[i - item.col.filter(Boolean).length] !== 'undefined';
1041
-
1042
1312
  return <td
1043
1313
  className={combinedCls(
1044
1314
  'e-cal-timeline-table__cell-cushion-content__container e-cal-timeline-table__cell-tooltiptrigger',
1045
1315
  {
1046
1316
  'has-event': eventSourcesData && _currentData.length > 0,
1047
- 'empty': d <= 0,
1317
+ 'empty': !isInteractive,
1048
1318
  'today': d === now.getDate(),
1049
- 'selected': d === day && tableRowNum === rowIndex,
1319
+ 'selected': isCellSelected(rowIndex, dayIndex),
1050
1320
  'last-cell': isLastCol
1051
1321
  }
1052
1322
  )}
1053
1323
  key={"col" + i}
1054
1324
  data-index={colIndex - 1}
1055
1325
  colSpan={1}
1056
- data-date={getCalendarDate(_dateShow)}
1057
- data-day={padZero(d)}
1058
- data-week={i}
1326
+ data-rowinfo={JSON.stringify(val[rowIndex]?.listSection)}
1327
+ data-date={_dateShow}
1328
+ data-day={_dateDayShow}
1329
+ data-week={weekDay}
1059
1330
  data-row={rowIndex}
1060
1331
  onMouseEnter={(e: React.MouseEvent) => {
1061
1332
  onCellMouseEnter?.(e);
1333
+
1334
+ //
1335
+ if (multipleCells) handleTableMainCellMouseEnter(e, rowIndex, dayIndex);
1062
1336
  }}
1063
- onMouseLeave={(e: React.MouseEvent) => {
1064
- onCellMouseLeave?.(e);
1065
- }}
1066
- onClick={(e: React.MouseEvent) => {
1337
+ onMouseDown={(e: React.MouseEvent) => {
1067
1338
  //
1068
- onCellClick?.(e);
1069
-
1070
- if (d > 0) {
1339
+ onCellClick?.(e, {
1340
+ rowData: val[rowIndex]?.listSection,
1341
+ date: _dateShow,
1342
+ row: rowIndex,
1343
+ col: dayIndex
1344
+ });
1345
+
1346
+ if (isInteractive) {
1071
1347
  handleDayChange(e, d); // update current day
1072
1348
  onChangeDate?.(e, null);
1073
1349
  }
1350
+
1351
+ if (multipleCells) handleTableMainCellMouseDown(e, rowIndex, dayIndex);
1352
+ }}
1353
+ onMouseLeave={(e: React.MouseEvent) => {
1354
+ onCellMouseLeave?.(e);
1355
+ }}
1356
+ onMouseUp={(e: React.MouseEvent) => {
1357
+ onCellMouseUp?.(e, selectedCells);
1074
1358
  }}
1075
1359
  >
1076
1360
 
1077
1361
 
1078
- {/* forward fill */}
1079
- {!FILL_BLANK_DATE_DISABLD && isForward ? <>
1080
- <div className="e-cal-timeline-table__cell-cushion e-cal-timeline-table__cell-cushion-content disabled">
1081
- &nbsp;
1082
- </div>
1083
- </> : null}
1084
-
1085
-
1086
-
1087
-
1088
- {/* day */}
1089
- <div className="e-cal-timeline-table__cell-cushion e-cal-timeline-table__cell-cushion-content">
1362
+ {/* forward fill & day & back fill */}
1363
+ <div
1364
+ className={combinedCls(
1365
+ 'e-cal-timeline-table__cell-cushion e-cal-timeline-table__cell-cushion-content',
1366
+ {
1367
+ 'disabled': !isInteractive
1368
+ }
1369
+ )}
1370
+ style={{ width: (CELL_MIN_W - 1) + 'px' }}
1371
+ >
1372
+
1090
1373
  {/*++++++++++++++++ EVENT ++++++++++++++++*/}
1091
- {_eventContent()}
1374
+ {_eventContent() || <><i style={{userSelect: 'none'}}>&nbsp;</i></>}
1092
1375
  {/*++++++++++++++++ /EVENT ++++++++++++++++*/}
1093
1376
 
1094
1377
  {/* ADD BUTTON */}
@@ -1100,9 +1383,9 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1100
1383
  href="#"
1101
1384
  tabIndex={-1}
1102
1385
  className="align-middle"
1103
- data-date={getCalendarDate(_dateShow)}
1104
- data-day={padZero(d)}
1105
- data-week={i}
1386
+ data-date={_dateShow}
1387
+ data-day={_dateDayShow}
1388
+ data-week={weekDay}
1106
1389
  data-row={rowIndex}
1107
1390
  onClick={(e: React.MouseEvent) => {
1108
1391
  e.preventDefault();
@@ -1115,20 +1398,20 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1115
1398
  setTableCellId(-1);
1116
1399
 
1117
1400
  //
1118
- if (d > 0) {
1401
+ if (isInteractive) {
1119
1402
  handleDayChange(e, d); // update current day
1120
1403
 
1121
1404
  onChangeDate?.(e, {
1122
1405
  rowData: listSectionData,
1123
1406
  id: 0,
1124
- date: getCalendarDate(`${year}-${month + 1}-${d}`)
1407
+ date: _dateShow
1125
1408
  });
1126
1409
 
1127
1410
  if (EVENTS_ENABLED) {
1128
1411
  onModalEditOpen?.({
1129
1412
  rowData: listSectionData,
1130
1413
  id: 0,
1131
- date: getCalendarDate(`${year}-${month + 1}-${d}`)
1414
+ date: _dateShow
1132
1415
  }, () => setShowEdit(true), 'new');
1133
1416
  }
1134
1417
  }
@@ -1140,32 +1423,20 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1140
1423
  </div>
1141
1424
  </>}
1142
1425
  {/* /ADD BUTTON */}
1143
-
1144
1426
  </div>
1145
-
1146
-
1147
- {/* back fill */}
1148
- {!FILL_BLANK_DATE_DISABLD && isBack ? <>
1149
- <div className="e-cal-timeline-table__cell-cushion e-cal-timeline-table__cell-cushion-content disabled">
1150
- &nbsp;
1151
- </div>
1152
- </> : null}
1153
-
1154
-
1427
+
1155
1428
 
1156
1429
  </td>;
1157
1430
  };
1158
1431
 
1159
-
1160
1432
  if (!FILL_BLANK_DATE_DISABLD) {
1161
1433
  return <>{_tdContent()}</>;
1162
1434
  } else {
1163
- return d > 0 && d <= days[month] ? (
1435
+ return isInteractive ? (
1164
1436
  <>{_tdContent()}</>
1165
1437
  ) : null;
1166
1438
  }
1167
1439
 
1168
-
1169
1440
  }
1170
1441
 
1171
1442
 
@@ -1177,10 +1448,9 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1177
1448
 
1178
1449
  function generateColUi() {
1179
1450
 
1180
- if (FILL_BLANK_DATE_DISABLD) {
1181
-
1182
- //#######################
1183
- return Array.from({ length: days[month] }).fill(0).map((item: any, i: number) => {
1451
+ {/* //########## MODE: WEEK ############# */}
1452
+ if (appearanceMode === 'week') {
1453
+ return Array.from({ length: 7 }).fill(0).map((item: any, i: number) => {
1184
1454
  return (
1185
1455
  <col
1186
1456
  key={"col-placeholder-" + i}
@@ -1191,37 +1461,67 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1191
1461
  />
1192
1462
  );
1193
1463
  })
1194
- //#######################
1195
-
1196
- } else {
1197
-
1198
- //#######################
1199
- // colIndex
1200
- let colIndex = 0;
1464
+ }
1201
1465
 
1202
- return getCells().map((item: any, j: number) => {
1203
- return item.col.map((dayIndex: number | null, i: number) => {
1466
+ {/* //########## /MODE: WEEK ############# */}
1204
1467
 
1205
- colIndex++;
1206
1468
 
1207
- const d = typeof dayIndex === 'number' ? dayIndex - (startDay - 2) : 0;
1469
+ {/* //########## MODE: MONTH ############# */}
1470
+ if (appearanceMode === 'month') {
1471
+ if (FILL_BLANK_DATE_DISABLD) {
1472
+ return Array.from({ length: days[month] }).fill(0).map((item: any, i: number) => {
1208
1473
  return (
1209
1474
  <col
1210
- className={`${d > 0 ? '' : 'empty'}`}
1211
1475
  key={"col-placeholder-" + i}
1212
- data-index={colIndex - 1}
1213
- data-datagrid-col={colIndex - 1}
1476
+ data-index={i}
1477
+ data-datagrid-col={i}
1214
1478
  style={{ minWidth: CELL_MIN_W + 'px' }}
1215
1479
 
1216
1480
  />
1217
1481
  );
1482
+ })
1218
1483
 
1219
- });
1484
+ } else {
1485
+ // colIndex
1486
+ let colIndex = 0;
1220
1487
 
1488
+ return getCells().map((item: any, j: number) => {
1489
+ return item.col.map((dayIndex: number | null, i: number) => {
1221
1490
 
1222
- })
1223
- //#######################
1491
+ colIndex++;
1492
+
1493
+ // helper
1494
+ const isInteractive = item.dateInfo[i].validDisplayDate; // The date on which the user interaction can occur, e.g. click, modify
1495
+
1496
+ return (
1497
+ <col
1498
+ className={combinedCls(
1499
+ {
1500
+ 'empty': !isInteractive
1501
+ }
1502
+ )}
1503
+ key={"col-placeholder-" + i}
1504
+ data-index={colIndex - 1}
1505
+ data-datagrid-col={colIndex - 1}
1506
+ style={{ minWidth: CELL_MIN_W + 'px' }}
1507
+
1508
+ />
1509
+ );
1510
+
1511
+ });
1512
+
1513
+
1514
+ })
1515
+ }
1224
1516
  }
1517
+ {/* //########## /MODE: MONTH ############# */}
1518
+
1519
+
1520
+
1521
+
1522
+
1523
+
1524
+
1225
1525
 
1226
1526
  }
1227
1527
 
@@ -1269,69 +1569,149 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1269
1569
  }
1270
1570
 
1271
1571
 
1272
- function tableGridInit(scrollBarInit: boolean = true) {
1572
+ function tableGridInitHeadertitle() {
1573
+ //
1574
+ if (tableGridRef.current === null) return;
1575
+
1576
+ const tableGridEl: any = tableGridRef.current;
1577
+
1578
+ // initialize cell height
1579
+ const headerTitleTrElements = tableGridEl.querySelector('.e-cal-timeline-table__datagrid-body__title tbody').getElementsByTagName('tr');
1580
+ const trElements = tableGridEl.querySelector('.e-cal-timeline-table__datagrid-body__content tbody').getElementsByTagName('tr');
1581
+
1582
+ for (let i = 0; i < headerTitleTrElements.length; i++) {
1583
+
1584
+ const targetElement = headerTitleTrElements[i].offsetHeight > trElements[i].offsetHeight ? headerTitleTrElements[i] : trElements[i];
1585
+ const tdOHeight = window.getComputedStyle(targetElement).height;
1586
+ headerTitleTrElements[i].style.height = tdOHeight;
1587
+ trElements[i].style.height = tdOHeight;
1588
+
1589
+ }
1590
+
1591
+ }
1592
+
1593
+
1594
+ function tableGridInit() {
1273
1595
 
1274
1596
  //
1275
1597
  if (tableGridRef.current === null) return;
1276
1598
 
1277
1599
  const tableGridEl: any = tableGridRef.current;
1600
+ let _curCellMinWidth: number = CELL_MIN_W;
1601
+ let _curColCount: number = FILL_BLANK_DATE_DISABLD ? days[month] : 7 * getCells().length;
1278
1602
 
1279
1603
 
1604
+ if (appearanceMode === 'week') {
1605
+ _curColCount = 7;
1606
+ }
1607
+
1608
+
1609
+ //****************
1610
+ // STEP 1-1:
1611
+ //****************
1612
+ // calculate min width (MODE: WEEK)
1613
+ //--------------
1614
+ if (appearanceMode === 'week') {
1615
+ const tableMaxWidth = tableGridEl.clientWidth;
1616
+ const tableHeaderTitleWidth = tableGridEl.querySelector('.e-cal-timeline-table__cell-cushion-headertitle').clientWidth;
1617
+ const tableDividerWidth = tableGridEl.querySelector('.e-cal-timeline-table__timeline-divider').clientWidth;
1618
+ const tableBorderWidth = 4;
1619
+ const scrollMaxWidth = tableMaxWidth - tableHeaderTitleWidth - tableDividerWidth - tableBorderWidth;
1620
+
1621
+ _curCellMinWidth = scrollMaxWidth/7;
1622
+ _curColCount = 7;
1623
+
1624
+ // header
1625
+ tableGridEl.querySelectorAll('.e-cal-timeline-table__cell-cushion-headercontent__container, .e-cal-timeline-table__cell-cushion-content').forEach((node: HTMLDivElement) => {
1626
+ node.style.width = _curCellMinWidth + 'px';
1627
+ });
1628
+
1629
+
1630
+ }
1631
+
1632
+
1633
+
1280
1634
  //****************
1281
- // STEP 1:
1635
+ // STEP 1-2:
1282
1636
  //****************
1283
- // calculate min width
1637
+ // calculate min width (MODE: MONTH)
1284
1638
  //--------------
1285
- const cellMinWidth = CELL_MIN_W;
1286
- const colCount = FILL_BLANK_DATE_DISABLD ? days[month] : 7 * getCells().length;
1639
+ const cellMinWidth = _curCellMinWidth;
1640
+ const colCount = _curColCount;
1287
1641
  const scrollableMinWidth = cellMinWidth * colCount;
1288
1642
 
1643
+
1644
+ //****************
1645
+ // STEP 1-3:
1646
+ //****************
1647
+ // initialize "header & main" cells
1648
+ //--------------
1649
+ const headerThContentContainers: any = tableGridEl.querySelector('.e-cal-timeline-table__datagrid-header__content tbody').getElementsByTagName('th');
1650
+ for (let i = 0; i < headerThContentContainers.length; i++) {
1651
+ const curHeaderThContent = headerThContentContainers[i].querySelector('.e-cal-timeline-table__cell-cushion-headercontent');
1652
+ if (curHeaderThContent !== null) curHeaderThContent.style.width = _curCellMinWidth + 'px';
1653
+ }
1654
+
1655
+
1656
+ const mainTdContentContainers: any = tableGridEl.querySelector('.e-cal-timeline-table__datagrid-body__content tbody').getElementsByTagName('td');
1657
+ for (let i = 0; i < mainTdContentContainers.length; i++) {
1658
+ const curHeaderThContent = mainTdContentContainers[i].querySelector('.e-cal-timeline-table__cell-cushion-content');
1659
+ if (curHeaderThContent !== null) curHeaderThContent.style.width = _curCellMinWidth + 'px';
1660
+ }
1661
+
1662
+ const mainTdContentCols: any = tableGridEl.querySelector('.e-cal-timeline-table__datagrid-body__content colgroup').getElementsByTagName('col')
1663
+ for (let i = 0; i < mainTdContentCols.length; i++) {
1664
+ mainTdContentCols[i].style.minWidth = _curCellMinWidth + 'px';
1665
+ }
1666
+
1667
+
1289
1668
  //****************
1290
1669
  // STEP 2:
1291
1670
  //****************
1292
1671
  // initialize scrollable wrapper (width)
1293
1672
  //--------------
1294
- let _scrollableWrapper: HTMLElement[] = [];
1295
- if (scrollBarInit) {
1296
- _scrollableWrapper = tableGridEl.querySelectorAll('.e-cal-timeline-table__scroller-harness');
1297
- [].slice.call(_scrollableWrapper).forEach((el: any) => {
1298
- const scrollType = el.dataset.scroll;
1299
-
1300
- if (scrollType !== 'list') {
1301
- const _content = el.querySelector('.e-cal-timeline-table__scroller');
1302
- const tableMaxWidth = tableGridEl.clientWidth;
1303
- const tableHeaderTitleWidth = tableGridEl.querySelector('.e-cal-timeline-table__cell-cushion-headertitle').clientWidth;
1304
- const tableDividerWidth = tableGridEl.querySelector('.e-cal-timeline-table__timeline-divider').clientWidth;
1305
- const tableBorderWidth = 4;
1306
- const scrollMaxWidth = tableMaxWidth - tableHeaderTitleWidth - tableDividerWidth - tableBorderWidth;
1673
+ const _scrollableWrapper: HTMLElement[] = tableGridEl.querySelectorAll('.e-cal-timeline-table__scroller-harness');
1674
+ [].slice.call(_scrollableWrapper).forEach((el: any) => {
1675
+ const scrollType = el.dataset.scroll;
1307
1676
 
1677
+ if (appearanceMode === 'week') {
1678
+ el.classList.add('e-cal-timeline-table__scroller-harness--hideX');
1679
+ }
1680
+ if (appearanceMode === 'month') {
1681
+ el.classList.remove('e-cal-timeline-table__scroller-harness--hideX');
1682
+ }
1308
1683
 
1309
- el.dataset.width = scrollMaxWidth;
1310
- el.style.maxWidth = el.dataset.width + 'px';
1311
- _content.style.minWidth = scrollableMinWidth + 'px';
1684
+ if (scrollType !== 'list') {
1685
+ const _content = el.querySelector('.e-cal-timeline-table__scroller');
1686
+ const tableMaxWidth = tableGridEl.clientWidth;
1687
+ const tableHeaderTitleWidth = tableGridEl.querySelector('.e-cal-timeline-table__cell-cushion-headertitle').clientWidth;
1688
+ const tableDividerWidth = tableGridEl.querySelector('.e-cal-timeline-table__timeline-divider').clientWidth;
1689
+ const tableBorderWidth = 4;
1690
+ const scrollMaxWidth = tableMaxWidth - tableHeaderTitleWidth - tableDividerWidth - tableBorderWidth;
1312
1691
 
1313
- }
1314
- });
1315
- }
1692
+ el.dataset.width = scrollMaxWidth;
1693
+ el.style.maxWidth = el.dataset.width + 'px';
1694
+ _content.style.minWidth = scrollableMinWidth + 'px';
1316
1695
 
1696
+ }
1697
+ });
1698
+
1317
1699
 
1318
1700
  //****************
1319
1701
  // STEP 3:
1320
1702
  //****************
1321
1703
  // initialize cell width
1322
1704
  //--------------
1323
- const headerThElements: any = tableGridEl.querySelector('.e-cal-timeline-table__datagrid-header__content tbody').getElementsByTagName('th');
1324
- const colElements: any = tableGridEl.querySelector('.e-cal-timeline-table__datagrid-body__content colgroup').getElementsByTagName('col')
1325
- const tdElements: any = tableGridEl.querySelector('.e-cal-timeline-table__datagrid-body__content tbody').getElementsByTagName('td');
1326
- const tdElementMaxWidth: number = typeof tdElements[0] === 'undefined' ? 0 : parseFloat(window.getComputedStyle(tdElements[0].querySelector('.e-cal-timeline-table__cell-cushion-content')).maxWidth);
1705
+ const tdElementMaxWidth: number = typeof mainTdContentContainers[0] === 'undefined' ? 0 : parseFloat(window.getComputedStyle(mainTdContentContainers[0].querySelector('.e-cal-timeline-table__cell-cushion-content')).maxWidth);
1327
1706
 
1328
1707
 
1329
1708
  if (Array.isArray(eventsValue) && eventsValue.length > 0) {
1330
1709
 
1331
- for (let i = 0; i < headerThElements.length; i++) {
1710
+ for (let i = 0; i < headerThContentContainers.length; i++) {
1332
1711
 
1333
- const curHeaderThElementMaxWidth = parseFloat(window.getComputedStyle(headerThElements[i].querySelector('.e-cal-timeline-table__cell-cushion-headercontent')).width);
1334
- const targetElement = headerThElements[i].offsetWidth > tdElements[i].offsetWidth ? headerThElements[i] : tdElements[i];
1712
+ const curHeaderThContent = headerThContentContainers[i].querySelector('.e-cal-timeline-table__cell-cushion-headercontent');
1713
+ const curHeaderThContentMaxWidth = parseFloat(window.getComputedStyle(curHeaderThContent).width);
1714
+ const targetElement = headerThContentContainers[i].offsetWidth > mainTdContentContainers[i].offsetWidth ? headerThContentContainers[i] : mainTdContentContainers[i];
1335
1715
  let tdOwidth = parseFloat(window.getComputedStyle(targetElement).width);
1336
1716
 
1337
1717
 
@@ -1341,16 +1721,16 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1341
1721
  }
1342
1722
 
1343
1723
  // check header th max width
1344
- if (tdElementMaxWidth > 0 && tdElementMaxWidth < curHeaderThElementMaxWidth) {
1345
- tdOwidth = curHeaderThElementMaxWidth;
1724
+ if (tdElementMaxWidth > 0 && tdElementMaxWidth < curHeaderThContentMaxWidth) {
1725
+ tdOwidth = curHeaderThContentMaxWidth;
1346
1726
  }
1347
1727
 
1348
1728
  // Prevent the width from being +1 each time it is initialized
1349
1729
  tdOwidth = tdOwidth - 1;
1350
1730
 
1351
- headerThElements[i].querySelector('.e-cal-timeline-table__cell-cushion-headercontent').style.width = tdOwidth + 'px';
1352
- tdElements[i].querySelector('.e-cal-timeline-table__cell-cushion-content').style.minWidth = tdOwidth + 'px';
1353
- colElements[i].style.minWidth = tdOwidth + 'px';
1731
+
1732
+ headerThContentContainers[i].querySelector('.e-cal-timeline-table__cell-cushion-headercontent').style.width = tdOwidth + 'px';
1733
+ mainTdContentCols[i].style.minWidth = tdOwidth + 'px';
1354
1734
 
1355
1735
 
1356
1736
  }
@@ -1388,38 +1768,26 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1388
1768
  //****************
1389
1769
  // initialize cell height
1390
1770
  //--------------
1391
- const headerTitleTrElements = tableGridEl.querySelector('.e-cal-timeline-table__datagrid-body__title tbody').getElementsByTagName('tr');
1392
- const trElements = tableGridEl.querySelector('.e-cal-timeline-table__datagrid-body__content tbody').getElementsByTagName('tr');
1393
-
1394
- for (let i = 0; i < headerTitleTrElements.length; i++) {
1395
-
1396
- const targetElement = headerTitleTrElements[i].offsetHeight > trElements[i].offsetHeight ? headerTitleTrElements[i] : trElements[i];
1397
- const tdOHeight = window.getComputedStyle(targetElement).height;
1398
- headerTitleTrElements[i].style.height = tdOHeight;
1399
- trElements[i].style.height = tdOHeight;
1400
-
1401
- }
1771
+ tableGridInitHeadertitle();
1402
1772
 
1403
1773
  //****************
1404
1774
  // STEP 6:
1405
1775
  //****************
1406
1776
  //initialize scrollable wrapper (height)
1407
1777
  //--------------
1408
- if (scrollBarInit) {
1409
- [].slice.call(_scrollableWrapper).forEach((el: any) => {
1410
- const scrollType = el.dataset.scroll;
1411
- const oldHeight = el.clientHeight;
1412
-
1413
- if (scrollType !== 'header') {
1414
- const tableWrapperMaxHeight = window.getComputedStyle(tableGridEl as HTMLElement).height;
1415
- if (oldHeight > parseFloat(tableWrapperMaxHeight)) {
1416
- el.style.height = tableWrapperMaxHeight;
1417
- }
1778
+ [].slice.call(_scrollableWrapper).forEach((el: any) => {
1779
+ const scrollType = el.dataset.scroll;
1780
+ const oldHeight = el.clientHeight;
1781
+
1782
+ if (scrollType !== 'header') {
1783
+ const tableWrapperMaxHeight = window.getComputedStyle(tableGridEl as HTMLElement).height;
1784
+ if (oldHeight > parseFloat(tableWrapperMaxHeight)) {
1785
+ el.style.height = tableWrapperMaxHeight;
1418
1786
  }
1787
+ }
1419
1788
 
1420
- });
1421
- }
1422
-
1789
+ });
1790
+
1423
1791
 
1424
1792
 
1425
1793
  //****************
@@ -1429,12 +1797,37 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1429
1797
  //--------------
1430
1798
  tableGridEl.classList.remove('invisible');
1431
1799
 
1800
+ //****************
1801
+ // STEP 1-1:
1802
+ //****************
1803
+ // calculate min width (MODE: WEEK)
1804
+ //--------------
1805
+ if (appearanceMode === 'week') {
1806
+ const tableMaxWidth = tableGridEl.clientWidth;
1807
+ const tableHeaderTitleWidth = tableGridEl.querySelector('.e-cal-timeline-table__cell-cushion-headertitle').clientWidth;
1808
+ const tableDividerWidth = tableGridEl.querySelector('.e-cal-timeline-table__timeline-divider').clientWidth;
1809
+ const tableBorderWidth = 4;
1810
+ const scrollMaxWidth = tableMaxWidth - tableHeaderTitleWidth - tableDividerWidth - tableBorderWidth;
1811
+
1812
+ _curCellMinWidth = scrollMaxWidth/7;
1813
+ _curColCount = 7;
1814
+
1815
+ // header content
1816
+ tableGridEl.querySelectorAll('.e-cal-timeline-table__cell-cushion-headercontent__container, .e-cal-timeline-table__cell-cushion-headercontent').forEach((node: HTMLDivElement) => {
1817
+ node.style.width = _curCellMinWidth + 'px';
1818
+ });
1819
+
1820
+ // main content
1821
+ tableGridEl.querySelectorAll('.e-cal-timeline-table__cell-cushion-content').forEach((node: HTMLDivElement) => {
1822
+ node.style.width = _curCellMinWidth + 'px';
1823
+ });
1432
1824
 
1825
+ }
1433
1826
 
1434
1827
  }
1435
1828
 
1436
1829
 
1437
- function tableGridReset(scrollBarInit: boolean = true) {
1830
+ function tableGridReset() {
1438
1831
  if (tableGridRef.current === null) return;
1439
1832
 
1440
1833
  const tableGridEl: any = tableGridRef.current;
@@ -1442,17 +1835,15 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1442
1835
 
1443
1836
  // initialize scrollable wrapper (width & height)
1444
1837
  //--------------
1445
- if (scrollBarInit) {
1446
- const _scrollableWrapper = tableGridEl.querySelectorAll('.e-cal-timeline-table__scroller-harness');
1447
- [].slice.call(_scrollableWrapper).forEach((el: any) => {
1448
-
1449
- const _content = el.querySelector('.e-cal-timeline-table__scroller');
1450
- el.removeAttribute('data-width');
1451
- el.removeAttribute('style');
1452
- _content.removeAttribute('style');
1453
- });
1454
- }
1455
-
1838
+ const _scrollableWrapper = tableGridEl.querySelectorAll('.e-cal-timeline-table__scroller-harness');
1839
+ [].slice.call(_scrollableWrapper).forEach((el: any) => {
1840
+
1841
+ const _content = el.querySelector('.e-cal-timeline-table__scroller');
1842
+ el.removeAttribute('data-width');
1843
+ el.removeAttribute('style');
1844
+ _content.removeAttribute('style');
1845
+ });
1846
+
1456
1847
 
1457
1848
  // initialize cell height
1458
1849
  //--------------
@@ -1464,6 +1855,7 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1464
1855
  trElements[i].removeAttribute('style');
1465
1856
  }
1466
1857
 
1858
+
1467
1859
  }
1468
1860
 
1469
1861
 
@@ -1498,10 +1890,19 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1498
1890
  }, [year]);
1499
1891
 
1500
1892
 
1893
+ useEffect(() => {
1894
+ if (typeof appearanceWeekTmpl === 'function') {
1895
+ setDisplayWeekForHeader([getCells().at(0).dateInfo[0].date, getCells().at(-1).dateInfo[0].date]);
1896
+ } else {
1897
+ setDisplayWeekForHeader([formatToEnglishMonthDay(getCells().at(0).dateInfo[0].date), formatToEnglishMonthDay(getCells().at(-1).dateInfo[0].date)]);
1898
+ }
1899
+
1900
+ }, [weekOffset]);
1901
+
1501
1902
  useEffect(() => {
1502
1903
 
1503
1904
  // update events value
1504
- if (Array.isArray(eventsValue)) setVal(eventsValue);
1905
+ if (Array.isArray(eventsValue) && eventsValue.length > 0) setVal(eventsValue);
1505
1906
 
1506
1907
  // update current today
1507
1908
  if (typeof customTodayDate !== 'undefined' && isValidDate(customTodayDate)) {
@@ -1519,7 +1920,7 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1519
1920
  tableGridReset();
1520
1921
  }
1521
1922
 
1522
- }, [eventsValue, customTodayDate]);
1923
+ }, [eventsValue, customTodayDate, appearanceMode]);
1523
1924
 
1524
1925
 
1525
1926
 
@@ -1531,7 +1932,7 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1531
1932
  {/*////////////////////////////////////////////////// */}
1532
1933
 
1533
1934
  <div className={combinedCls(
1534
- "e-cal-timeline__wrapper",
1935
+ `e-cal-timeline__wrapper e-cal-timeline__wrapper--${appearanceMode}`,
1535
1936
  calendarWrapperClassName
1536
1937
  )}>
1537
1938
 
@@ -1542,16 +1943,33 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1542
1943
  <path d="M14.2893 5.70708C13.8988 5.31655 13.2657 5.31655 12.8751 5.70708L7.98768 10.5993C7.20729 11.3805 7.2076 12.6463 7.98837 13.427L12.8787 18.3174C13.2693 18.7079 13.9024 18.7079 14.293 18.3174C14.6835 17.9269 14.6835 17.2937 14.293 16.9032L10.1073 12.7175C9.71678 12.327 9.71678 11.6939 10.1073 11.3033L14.2893 7.12129C14.6799 6.73077 14.6799 6.0976 14.2893 5.70708Z" fill="#000" />
1543
1944
  </svg>
1544
1945
  </button>
1545
- <div className="e-cal-timeline__header__btns">
1546
- <button tabIndex={-1} type="button" className={`e-cal-timeline__btn ${winMonth ? 'active' : ''}`} onClick={handleShowWinMonth}>
1547
- {MONTHS[month]}
1548
- <svg width="12px" height="12px" viewBox="0 0 24 24"><path d="M11.178 19.569a.998.998 0 0 0 1.644 0l9-13A.999.999 0 0 0 21 5H3a1.002 1.002 0 0 0-.822 1.569l9 13z" fill="#000000" /></svg>
1549
- </button>
1550
- <button tabIndex={-1} type="button" className={`e-cal-timeline__btn ${winYear ? 'active' : ''}`} onClick={handleShowWinYear}>
1551
- {year}
1552
- <svg width="12px" height="12px" viewBox="0 0 24 24"><path d="M11.178 19.569a.998.998 0 0 0 1.644 0l9-13A.999.999 0 0 0 21 5H3a1.002 1.002 0 0 0-.822 1.569l9 13z" fill="#000000" /></svg>
1553
- </button>
1554
- </div>
1946
+
1947
+ {/* //########## MODE: WEEK ############# */}
1948
+ {appearanceMode === 'week' ? <>
1949
+ <div className="e-cal-timeline__header__info">
1950
+ {typeof appearanceWeekTmpl === 'function' ? <>{appearanceWeekTmpl(displayWeekForHeader[0], displayWeekForHeader[1])}</> : <>{displayWeekForHeader[0]} - {displayWeekForHeader[1]}</>}
1951
+ </div>
1952
+ </> : null}
1953
+ {/* //########## /MODE: WEEK ############# */}
1954
+
1955
+
1956
+ {/* //########## MODE: MONTH ############# */}
1957
+ {appearanceMode === 'month' ? <>
1958
+ <div className="e-cal-timeline__header__btns">
1959
+ <button tabIndex={-1} type="button" className={`e-cal-timeline__btn ${winMonth ? 'active' : ''}`} onClick={handleShowWinMonth}>
1960
+ {MONTHS[month]}
1961
+ <svg width="12px" height="12px" viewBox="0 0 24 24"><path d="M11.178 19.569a.998.998 0 0 0 1.644 0l9-13A.999.999 0 0 0 21 5H3a1.002 1.002 0 0 0-.822 1.569l9 13z" fill="#000000" /></svg>
1962
+ </button>
1963
+ <button tabIndex={-1} type="button" className={`e-cal-timeline__btn ${winYear ? 'active' : ''}`} onClick={handleShowWinYear}>
1964
+ {year}
1965
+ <svg width="12px" height="12px" viewBox="0 0 24 24"><path d="M11.178 19.569a.998.998 0 0 0 1.644 0l9-13A.999.999 0 0 0 21 5H3a1.002 1.002 0 0 0-.822 1.569l9 13z" fill="#000000" /></svg>
1966
+ </button>
1967
+ </div>
1968
+ </> : null}
1969
+ {/* //########## /MODE: MONTH ############# */}
1970
+
1971
+
1972
+
1555
1973
  <button tabIndex={-1} type="button" className="e-cal-timeline__btn e-cal-timeline__btn--next" onClick={handleNextChange}>
1556
1974
  <svg width="20px" height="20px" viewBox="0 0 24 24" fill="none">
1557
1975
  <path d="M9.71069 18.2929C10.1012 18.6834 10.7344 18.6834 11.1249 18.2929L16.0123 13.4006C16.7927 12.6195 16.7924 11.3537 16.0117 10.5729L11.1213 5.68254C10.7308 5.29202 10.0976 5.29202 9.70708 5.68254C9.31655 6.07307 9.31655 6.70623 9.70708 7.09676L13.8927 11.2824C14.2833 11.6729 14.2833 12.3061 13.8927 12.6966L9.71069 16.8787C9.32016 17.2692 9.32016 17.9023 9.71069 18.2929Z" fill="#000" />
@@ -1609,9 +2027,36 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1609
2027
 
1610
2028
  {/*++++++++++++++++ TODAY SELECTION TAB ++++++++++++++++*/}
1611
2029
  <div className="e-cal-timeline__today-wrapper p-2">
1612
- <button tabIndex={-1} type="button" className="e-cal-timeline__btn e-cal-timeline__btn--today" onClick={handleTodayChange}>
2030
+ <button
2031
+ tabIndex={-1}
2032
+ type="button"
2033
+ className="e-cal-timeline__btn e-cal-timeline__btn--today"
2034
+ onClick={handleTodayChange}
2035
+ >
1613
2036
  {langToday || 'Today'}
1614
2037
  </button>
2038
+
2039
+ {appearanceToggle ? <>
2040
+ <button
2041
+ tabIndex={-1}
2042
+ type="button"
2043
+ className={`e-cal-timeline__btn e-cal-timeline__btn--appearance ${appearanceMode === 'month' ? 'active' : ''}`}
2044
+ data-mode="month"
2045
+ onClick={handleAppearanceChange}
2046
+ >
2047
+ {langAppearanceLabelMonth || 'Month'}
2048
+ </button>
2049
+ <button
2050
+ tabIndex={-1}
2051
+ type="button"
2052
+ className={`e-cal-timeline__btn e-cal-timeline__btn--appearance ${appearanceMode === 'week' ? 'active' : ''}`}
2053
+ data-mode="week"
2054
+ onClick={handleAppearanceChange}
2055
+ >
2056
+ {langAppearanceLabelWeek || 'Week'}
2057
+ </button>
2058
+ </> : null}
2059
+
1615
2060
  </div>
1616
2061
  {/*++++++++++++++++ /TODAY SELECTION TAB ++++++++++++++++*/}
1617
2062
 
@@ -1624,10 +2069,17 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1624
2069
  {/*//////////////////// Table Grid //////////////////// */}
1625
2070
  {/*////////////////////////////////////////////////// */}
1626
2071
  {val.length === 0 ? null : <>
1627
- <div ref={tableGridRef} className={combinedCls(
1628
- "e-cal-timeline-table__timeline-table__wrapper invisible",
1629
- tableWrapperClassName
1630
- )}>
2072
+ <div
2073
+ ref={tableGridRef}
2074
+ className={combinedCls(
2075
+ `e-cal-timeline-table__timeline-table__wrapper e-cal-timeline-table__timeline-table__wrapper--${appearanceMode} invisible`,
2076
+ tableWrapperClassName
2077
+ )}
2078
+ onKeyDown={(e: React.KeyboardEvent<HTMLDivElement>) => {
2079
+ onKeyPressed?.(e, selectedCells);
2080
+ }}
2081
+ tabIndex={-1} // require "tabIndex" attribute
2082
+ >
1631
2083
  <table role="grid" className={combinedCls(
1632
2084
  "e-cal-timeline-table__timeline-table",
1633
2085
  tableClassName
@@ -1781,7 +2233,14 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1781
2233
  <div className="e-cal-timeline-table__scroller">
1782
2234
  {/*<!--///// RESOURCE RIGHT //////-->*/}
1783
2235
  <div className="e-cal-timeline-table__timeline-body">
1784
- <table className="e-cal-timeline-table__datagrid-body__content e-cal-timeline-table__scrollgrid-sync-table">
2236
+ <table
2237
+ className="e-cal-timeline-table__datagrid-body__content e-cal-timeline-table__scrollgrid-sync-table"
2238
+ /* Drag to activate the selection area */
2239
+ onMouseLeave={multipleCells ? handleTableMainMouseUp : undefined}
2240
+ onMouseUp={multipleCells ? handleTableMainMouseUp : undefined}
2241
+
2242
+
2243
+ >
1785
2244
  <colgroup>
1786
2245
  {generateColUi()}
1787
2246
  </colgroup>
@@ -1848,8 +2307,7 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1848
2307
 
1849
2308
  // initialize table grid
1850
2309
  setTimeout(() => {
1851
- tableGridReset(false);
1852
- tableGridInit(false);
2310
+ tableGridInitHeadertitle();
1853
2311
  }, 500);
1854
2312
  });
1855
2313
  }}
@@ -1885,8 +2343,7 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1885
2343
  onModalEditEvent?.(queryItemObj(), closewin, () => {
1886
2344
  // initialize table grid
1887
2345
  setTimeout(() => {
1888
- tableGridReset(false);
1889
- tableGridInit(false);
2346
+ tableGridInitHeadertitle();
1890
2347
  }, 500);
1891
2348
  });
1892
2349