funda-ui 4.7.740 → 4.7.750

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.
@@ -13,8 +13,6 @@ import { getTodayDate, getCalendarDate, isValidDate, padZero, getDateDetails, ge
13
13
  import { clsWrite, combinedCls } from 'funda-utils/dist/cjs/cls';
14
14
  import getOs from 'funda-utils//dist/cjs/os';
15
15
 
16
-
17
-
18
16
  export interface EventsValueConfig {
19
17
  id: string | number;
20
18
  date: string,
@@ -324,6 +322,8 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
324
322
  return tableCellMinWidth;
325
323
  }, [tableCellMinWidth, appearanceMode, headerShowWeek]);
326
324
 
325
+
326
+
327
327
  const findMondayAndTruncate = (dates: string[]) => {
328
328
  const _res = dates.map((s: string) => new Date(s));
329
329
  // Find the first Monday in the sequence
@@ -389,7 +389,45 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
389
389
  //================================================================
390
390
  // Weekly calendar
391
391
  //================================================================
392
+ const hasInitializedRef = useRef<boolean>(false);
393
+
394
+ // Helper function to calculate offset from a specific date
395
+ const calculateWeekOffset = (targetDate?: Date) => {
396
+ const _curDate = typeof targetDate === 'undefined' ? date : targetDate;
397
+
398
+ // 1. Get the current selected date (from customTodayDate or user selection)
399
+ const selected = new Date(_curDate.getFullYear(), _curDate.getMonth(), _curDate.getDate());
400
+
401
+ // 2. Get the reference Monday of the "actual current week" (offset 0)
402
+ const currentWeekDates = getWeekDatesFromMon(0);
403
+ const currentMonday = new Date(currentWeekDates[0]);
404
+ currentMonday.setHours(0, 0, 0, 0);
405
+
406
+ // 3. Calculate the difference in days
407
+ const diffTime = selected.getTime() - currentMonday.getTime();
408
+ const diffDays = Math.round(diffTime / (1000 * 60 * 60 * 24));
409
+
410
+ // 4. Update the week offset automatically
411
+ const offset = Math.floor(diffDays / 7);
412
+ setWeekOffset(offset);
413
+ }
414
+ // Initialize weekOffset based on customTodayDate instead of default 0
392
415
  const [weekOffset, setWeekOffset] = useState<number>(0);
416
+
417
+ // Sync weekOffset whenever date changes or mode switches to 'week'
418
+ useEffect(() => {
419
+ if (!hasInitializedRef.current) {
420
+ const customDateValid = isValidDate(customTodayDate as never);
421
+ if (customDateValid) {
422
+ calculateWeekOffset(new Date(customTodayDate as string));
423
+ setDate(new Date(customTodayDate as string));
424
+ hasInitializedRef.current = true;
425
+ }
426
+ }
427
+ }, [date, appearanceMode, customTodayDate]);
428
+
429
+
430
+
393
431
  const handleNextWeek = () => {
394
432
  setWeekOffset(weekOffset + 1);
395
433
  return weekOffset + 1;
@@ -1169,7 +1207,7 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1169
1207
 
1170
1208
 
1171
1209
  }
1172
- function handleDayChange(e: React.MouseEvent, currentDay: number) {
1210
+ function handleDayChange(e: React.MouseEvent | null, currentDay: number) {
1173
1211
  // Avoid triggering a full table re-render when the clicked cell is already
1174
1212
  // the active day; this becomes expensive with large datasets.
1175
1213
  if (
@@ -1260,14 +1298,14 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1260
1298
  function handleAppearanceChange(e: React.MouseEvent) {
1261
1299
  const _mode = (e.target as any).dataset.mode;
1262
1300
  setAppearanceMode(_mode);
1263
-
1264
- //
1301
+
1302
+ // The useEffect above will handle the weekOffset calculation
1303
+ // as soon as appearanceMode becomes 'week'
1265
1304
  onChangeAppearanceMode?.(_mode);
1266
1305
  }
1267
1306
 
1268
1307
 
1269
1308
 
1270
-
1271
1309
  function handleShowWinYear() {
1272
1310
  setWinYear((prevState: boolean) => !prevState);
1273
1311
  }
@@ -1356,7 +1394,9 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1356
1394
  data-date={_dateShow}
1357
1395
  data-day={_dateDayShow}
1358
1396
  data-week={weekDay}
1359
- style={{ minWidth: CELL_MIN_W + 'px' }}
1397
+
1398
+ // FIX: In 'week' mode, we don't want a hardcoded minWidth
1399
+ style={appearanceMode === 'week' ? undefined : { minWidth: CELL_MIN_W + 'px' }}
1360
1400
  onMouseEnter={(e: React.MouseEvent) => {
1361
1401
  onCellMouseEnter?.(e);
1362
1402
  }}
@@ -2242,6 +2282,7 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
2242
2282
 
2243
2283
  }
2244
2284
 
2285
+
2245
2286
  // Dual RAF survival test
2246
2287
  /*
2247
2288
  A single RAF only guarantees "moving to the next frame."
@@ -2304,15 +2345,30 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
2304
2345
  }, [date]);
2305
2346
 
2306
2347
 
2348
+ // Guaranteed year change triggered by the next/prev buttons
2349
+ const isFirstRenderRef = useRef<boolean>(true);
2350
+ const prevYearRef = useRef<number>(year); // Record the year of the last occurrence.
2307
2351
  useEffect(() => {
2308
- // Guaranteed year change triggered by the front and rear buttons
2309
- onChangeYear?.({
2310
- day: padZero(day),
2311
- month: padZero(month + 1),
2312
- year: year.toString()
2313
- });
2314
- }, [year]);
2352
+ // 1. Intercept the first render (Mount)
2353
+ if (isFirstRenderRef.current) {
2354
+ isFirstRenderRef.current = false;
2355
+ return;
2356
+ }
2357
+
2358
+ // 2. It only triggers when the year actually changes
2359
+ if (year !== prevYearRef.current) {
2360
+ onChangeYear?.({
2361
+ day: padZero(day),
2362
+ month: padZero(month + 1),
2363
+ year: year.toString()
2364
+ });
2315
2365
 
2366
+ // Update the old year ref for next comparison
2367
+ prevYearRef.current = year;
2368
+ }
2369
+ }, [year, month, day, onChangeYear]);
2370
+
2371
+
2316
2372
 
2317
2373
  useEffect(() => {
2318
2374
 
@@ -1,3 +1,47 @@
1
+
2
+ /**
3
+ * Get the Sunday of the week of the specific date, and return to the
4
+ * end of January next year if it is New Year's Eve
5
+ * @param {Date | String} v
6
+ * @returns {String} yyyy-MM-dd
7
+ *
8
+ * @example
9
+ * getSpecialDateEnd('2025-12-29'); // 2026-01-31
10
+ * getSpecialDateEnd('2025-12-17'); // 2025-12-31
11
+ */
12
+ /**
13
+ * Calculates a special end date based on the week and month logic.
14
+ * @param v - The input date (Date object, string, or timestamp)
15
+ * @returns A formatted date string (YYYY-MM-DD)
16
+ */
17
+ function getSpecialDateEnd(v: Date | string | number): string {
18
+ // Assuming dateFormat returns a Date object based on your logic
19
+ const date: Date = new Date(v);
20
+
21
+ // getWeekDatesByDate should return Date[]
22
+ const weekDates: Date[] = getWeekDatesByDate(v);
23
+ const sunday: Date = weekDates[6]; // Sunday of that week
24
+
25
+ // If Sunday of this week rolls into the next year
26
+ if (sunday.getFullYear() > date.getFullYear()) {
27
+ const year = sunday.getFullYear();
28
+
29
+ // Get the last day of January of that new year
30
+ // Note: month 1 in 'new Date' is February, day 0 gives the last day of Jan
31
+ const lastDay = new Date(year, 1, 0).getDate();
32
+
33
+ // Using template literals for the return string
34
+ return `${year}-01-${lastDay.toString().padStart(2, '0')}`;
35
+ }
36
+
37
+ // Default: Return the last day of the current month
38
+ // We create a date for the "0th" day of the next month to get the end of current month
39
+ const endOfCurrentMonth = new Date(date.getFullYear(), date.getMonth() + 1, 0);
40
+
41
+ return getCalendarDate(endOfCurrentMonth);
42
+ }
43
+
44
+
1
45
  /**
2
46
  * The check string contains only hours, minutes, and seconds
3
47
  * @returns {Boolean}
@@ -497,20 +541,44 @@ function getMonthDates(year: number, month: number) {
497
541
  return dates;
498
542
  }
499
543
 
544
+
500
545
  /**
501
- * Get the date of the specified week (From Sunday)
502
- * @param {Number} weekOffset
503
- * @returns {Array<Date>}
546
+ * Get all 7 dates for a specific week starting from Sunday.
547
+ * * @param {Number} weekOffset - The offset of weeks from the current week.
548
+ * 0: Current week
549
+ * -1: Previous week
550
+ * 1: Next week
551
+ * @returns {Array<Date>} - An array containing 7 Date objects from Sunday to Saturday.
504
552
  */
505
- function getWeekDatesFromSun(weekOffset: number) {
506
- const dates: Array<Date> = [];
507
- const currentDate = new Date();
553
+ /*
554
+ // Demo 1: Get dates for the current week (Sunday Start)
555
+ const currentWeekSun = getWeekDatesFromSun(0);
556
+ console.log('Sunday (Start):', currentWeekSun[0].toLocaleDateString());
557
+ console.log('Saturday (End):', currentWeekSun[6].toLocaleDateString());
508
558
 
509
- // Calculate the date of Sunday
510
- const dayOfWeek = currentDate.getDay(); // 0 is Sunday
511
- currentDate.setDate(currentDate.getDate() - dayOfWeek + weekOffset * 7);
559
+ // Demo 2: Get the date range for the previous week
560
+ const lastWeek = getWeekDatesFromSun(-1);
561
+ const rangeStart = lastWeek[0].toISOString().split('T')[0];
562
+ const rangeEnd = lastWeek[6].toISOString().split('T')[0];
563
+ console.log(`Previous Week Range: ${rangeStart} to ${rangeEnd}`);
564
+
565
+ // Demo 3: Checking for Month/Year transitions
566
+ const transitionWeek = getWeekDatesFromSun(0).map(d => d.toDateString());
567
+ console.log('Transition Week Dates:', transitionWeek);
568
+
569
+ */
570
+ function getWeekDatesFromSun(weekOffset: number): Date[] {
571
+ const dates: Date[] = [];
572
+ // Start with a clean date (midnight) to avoid timezone/DST shifts during calculation
573
+ const currentDate: Date = new Date();
574
+ currentDate.setHours(0, 0, 0, 0);
575
+
576
+ const dayOfWeek: number = currentDate.getDay();
577
+
578
+ // Move to the Sunday of the current week, then apply the week offset
579
+ // Formula: Current Date - Current Day Index + (Offset * 7)
580
+ currentDate.setDate(currentDate.getDate() - dayOfWeek + (weekOffset * 7));
512
581
 
513
- // Get the date of the week
514
582
  for (let i = 0; i < 7; i++) {
515
583
  const date = new Date(currentDate);
516
584
  date.setDate(currentDate.getDate() + i);
@@ -520,21 +588,48 @@ function getWeekDatesFromSun(weekOffset: number) {
520
588
  return dates;
521
589
  }
522
590
 
591
+
523
592
  /**
524
- * Get the date of the specified week (From Monday)
525
- * @param {Number} weekOffset
526
- * @returns {Array<Date>}
593
+ * Get all 7 dates for a specific week starting from Monday.
594
+ * * @param {Number} weekOffset - The offset of weeks from the current week.
595
+ * 0: Current week
596
+ * -1: Previous week
597
+ * 1: Next week
598
+ * @returns {Array<Date>} - An array containing 7 Date objects from Monday to Sunday.
527
599
  */
528
- function getWeekDatesFromMon(weekOffset: number) {
529
- const dates: Array<Date> = [];
530
- const currentDate = new Date();
600
+ /*
601
+ // Demo 1: Get dates for the current week
602
+ const currentWeek = getWeekDatesFromMon(0);
603
+ console.log('Monday of this week:', currentWeek[0].toLocaleDateString());
604
+ console.log('Sunday of this week:', currentWeek[6].toLocaleDateString());
605
+
606
+ // Demo 2: Get dates for the next week
607
+ const nextWeek = getWeekDatesFromMon(1);
608
+ console.log('Monday of next week:', nextWeek[0].toLocaleDateString());
609
+
610
+ // Demo 3: Format the output as YYYY-MM-DD
611
+ const formattedWeek = getWeekDatesFromMon(0).map(date => {
612
+ const y = date.getFullYear();
613
+ const m = String(date.getMonth() + 1).padStart(2, '0');
614
+ const d = String(date.getDate()).padStart(2, '0');
615
+ return `${y}-${m}-${d}`;
616
+ });
617
+ console.log('Formatted Week Array:', formattedWeek);
618
+ // Result: ["2025-12-29", "2025-12-30", ..., "2026-01-04"]
619
+ */
620
+ function getWeekDatesFromMon(weekOffset: number): Date[] {
621
+ const dates: Date[] = [];
622
+ const currentDate: Date = new Date();
531
623
 
532
- // Set the date to Monday
624
+ // Calculate the difference to get to Monday of the current week
625
+ // If today is Sunday (0), we go back 6 days. Otherwise, go to (1 - currentDay).
533
626
  const dayOfWeek = currentDate.getDay();
534
627
  const diffToMonday = dayOfWeek === 0 ? -6 : 1 - dayOfWeek;
535
- currentDate.setDate(currentDate.getDate() + diffToMonday + weekOffset * 7);
628
+
629
+ // Apply the Monday offset and the week offset (7 days per week)
630
+ currentDate.setDate(currentDate.getDate() + diffToMonday + (weekOffset * 7));
536
631
 
537
- // Get the date of the week
632
+ // Generate the 7 days of the week
538
633
  for (let i = 0; i < 7; i++) {
539
634
  const date = new Date(currentDate);
540
635
  date.setDate(currentDate.getDate() + i);
@@ -544,7 +639,42 @@ function getWeekDatesFromMon(weekOffset: number) {
544
639
  return dates;
545
640
  }
546
641
 
642
+ /**
643
+ * Get the date list of the week for the specified date (starting from Monday)
644
+ * @param {Date | String} v - The specified date
645
+ * @returns {Array<Date>} - An array containing 7 Date objects
646
+ */
647
+ function getWeekDatesByDate(v: Date | string | number): Date[] {
648
+ const dates: Date[] = [];
649
+
650
+ // Ensure we are working with a Date object.
651
+ // If 'dateFormat' was a custom utility in your JS, replace 'new Date(v)' with that utility.
652
+ const currentDate = new Date(v);
653
+
654
+ // Get the day of the week (0 for Sunday, 1 for Monday, ..., 6 for Saturday)
655
+ const dayOfWeek = currentDate.getDay();
656
+
657
+ // Calculate difference to Monday: if Sunday (0) subtract 6 days, otherwise subtract (day - 1)
658
+ const diffToMonday = dayOfWeek === 0 ? -6 : 1 - dayOfWeek;
659
+
660
+ // Create the Monday starting point
661
+ const monday = new Date(currentDate);
662
+ monday.setDate(currentDate.getDate() + diffToMonday);
663
+
664
+ // Generate the 7 days of the week
665
+ for (let i = 0; i < 7; i++) {
666
+ const date = new Date(monday);
667
+ date.setDate(monday.getDate() + i);
668
+ dates.push(date);
669
+ }
670
+
671
+ return dates;
672
+ }
673
+
547
674
  export {
675
+ getSpecialDateEnd,
676
+
677
+ //
548
678
  isTimeString,
549
679
  getNow,
550
680
  padZero,
@@ -594,5 +724,6 @@ export {
594
724
  // get dates list
595
725
  getMonthDates,
596
726
  getWeekDatesFromSun,
597
- getWeekDatesFromMon
598
- }
727
+ getWeekDatesFromMon,
728
+ getWeekDatesByDate
729
+ }
package/package.json CHANGED
@@ -1 +1 @@
1
- {"author":"UIUX Lab","email":"uiuxlab@gmail.com","name":"funda-ui","version":"4.7.740","description":"React components using pure Bootstrap 5+ which does not contain any external style and script libraries.","repository":{"type":"git","url":"git+https://github.com/xizon/funda-ui.git"},"scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"keywords":["bootstrap","react-bootstrap","react-components","components","components-react","react-bootstrap-components","react","funda-ui","fundaui","uikit","ui-kit","ui-components"],"bugs":{"url":"https://github.com/xizon/funda-ui/issues"},"homepage":"https://github.com/xizon/funda-ui#readme","main":"all.js","license":"MIT","dependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"types":"all.d.ts","publishConfig":{"directory":"lib"},"directories":{"lib":"lib"}}
1
+ {"author":"UIUX Lab","email":"uiuxlab@gmail.com","name":"funda-ui","version":"4.7.750","description":"React components using pure Bootstrap 5+ which does not contain any external style and script libraries.","repository":{"type":"git","url":"git+https://github.com/xizon/funda-ui.git"},"scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"keywords":["bootstrap","react-bootstrap","react-components","components","components-react","react-bootstrap-components","react","funda-ui","fundaui","uikit","ui-kit","ui-components"],"bugs":{"url":"https://github.com/xizon/funda-ui/issues"},"homepage":"https://github.com/xizon/funda-ui#readme","main":"all.js","license":"MIT","dependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"types":"all.d.ts","publishConfig":{"directory":"lib"},"directories":{"lib":"lib"}}