dce-reactkit 4.0.0 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -55,7 +55,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
55
55
  });
56
56
  }
57
57
 
58
- // Highest error code = DRK34
58
+ // Highest error code = DRK36
59
59
  /**
60
60
  * List of error codes built into the react kit
61
61
  * @author Gabe Abrams
@@ -66,6 +66,8 @@ var ReactKitErrorCode;
66
66
  ReactKitErrorCode["NoCode"] = "DRK2";
67
67
  ReactKitErrorCode["SessionExpired"] = "DRK3";
68
68
  ReactKitErrorCode["NoCACCLSendRequestFunction"] = "DRK7";
69
+ ReactKitErrorCode["SimpleDateChooserInvalidDateRange"] = "DRK35";
70
+ ReactKitErrorCode["SimpleDateChooserInvalidNumMonths"] = "DRK36";
69
71
  })(ReactKitErrorCode || (ReactKitErrorCode = {}));
70
72
  var ReactKitErrorCode$1 = ReactKitErrorCode;
71
73
 
@@ -2547,6 +2549,19 @@ const ButtonInputGroup = (props) => {
2547
2549
  : children))));
2548
2550
  };
2549
2551
 
2552
+ // Constants
2553
+ const ORDINALS = ['th', 'st', 'nd', 'rd'];
2554
+ /**
2555
+ * Get a number's ordinal
2556
+ * @author Gabe Abrams
2557
+ * @param num the number being analyzed
2558
+ * @returns ordinal
2559
+ */
2560
+ const getOrdinal = (num) => {
2561
+ var _a, _b;
2562
+ return ((_b = (_a = ORDINALS[(num - 20) % 10]) !== null && _a !== void 0 ? _a : ORDINALS[num]) !== null && _b !== void 0 ? _b : ORDINALS[0]);
2563
+ };
2564
+
2550
2565
  const monthNames = [
2551
2566
  { short: 'Jan', full: 'January' },
2552
2567
  { short: 'Feb', full: 'February' },
@@ -2575,19 +2590,6 @@ const getMonthName = (month) => {
2575
2590
  return ((_a = monthNames[month - 1]) !== null && _a !== void 0 ? _a : monthNames[0]);
2576
2591
  };
2577
2592
 
2578
- // Constants
2579
- const ORDINALS = ['th', 'st', 'nd', 'rd'];
2580
- /**
2581
- * Get a number's ordinal
2582
- * @author Gabe Abrams
2583
- * @param num the number being analyzed
2584
- * @returns ordinal
2585
- */
2586
- const getOrdinal = (num) => {
2587
- var _a, _b;
2588
- return ((_b = (_a = ORDINALS[(num - 20) % 10]) !== null && _a !== void 0 ? _a : ORDINALS[num]) !== null && _b !== void 0 ? _b : ORDINALS[0]);
2589
- };
2590
-
2591
2593
  /**
2592
2594
  * Get current time info in US Boston Eastern Time, independent of machine
2593
2595
  * timezone
@@ -2651,6 +2653,7 @@ const getTimeInfoInET = (dateOrTimestamp) => {
2651
2653
  /**
2652
2654
  * A very simple, lightweight date chooser
2653
2655
  * @author Gabe Abrams
2656
+ * @author Gardenia Liu
2654
2657
  */
2655
2658
  /*------------------------------------------------------------------------*/
2656
2659
  /* ------------------------------ Component ----------------------------- */
@@ -2660,7 +2663,7 @@ const SimpleDateChooser = (props) => {
2660
2663
  /* -------------------------------- Setup ------------------------------- */
2661
2664
  /*------------------------------------------------------------------------*/
2662
2665
  /* -------------- Props ------------- */
2663
- const { ariaLabel, name, onChange, chooseFromPast, numMonthsToShow = 6, } = props;
2666
+ const { ariaLabel, name, onChange, numMonthsToShow = 6, dontAllowFuture, dontAllowPast, } = props;
2664
2667
  /*------------------------------------------------------------------------*/
2665
2668
  /* ------------------------------- Render ------------------------------- */
2666
2669
  /*------------------------------------------------------------------------*/
@@ -2672,14 +2675,28 @@ const SimpleDateChooser = (props) => {
2672
2675
  const choices = [];
2673
2676
  let startYear = today.year;
2674
2677
  let startMonth = today.month;
2675
- if (chooseFromPast) {
2678
+ // Don't allow past or future dates
2679
+ if (dontAllowPast && dontAllowFuture) {
2680
+ throw new ErrorWithCode('No past or future dates allowed', ReactKitErrorCode$1.SimpleDateChooserInvalidDateRange);
2681
+ }
2682
+ // Require numMonthsToShow to be positive
2683
+ if (numMonthsToShow <= 0) {
2684
+ throw new ErrorWithCode('numMonthsToShow must be positive', ReactKitErrorCode$1.SimpleDateChooserInvalidNumMonths);
2685
+ }
2686
+ // Recalculate startMonth and startYear when allowing past dates
2687
+ if (!dontAllowPast) {
2676
2688
  startMonth -= Math.max(0, numMonthsToShow - 1);
2677
2689
  while (startMonth <= 0) {
2678
2690
  startMonth += 12;
2679
2691
  startYear -= 1;
2680
2692
  }
2681
2693
  }
2682
- for (let i = 0; i < numMonthsToShow; i++) {
2694
+ // Calculate total number of months to show
2695
+ let totalMonthsToShow = numMonthsToShow;
2696
+ if (!dontAllowPast && !dontAllowFuture) {
2697
+ totalMonthsToShow = totalMonthsToShow * 2 - 1;
2698
+ }
2699
+ for (let i = 0; i < totalMonthsToShow; i++) {
2683
2700
  // Get month and year info
2684
2701
  const unmoddedMonth = (startMonth + i);
2685
2702
  let month = unmoddedMonth;
@@ -2698,23 +2715,25 @@ const SimpleDateChooser = (props) => {
2698
2715
  // Figure out which days are allowed
2699
2716
  const days = [];
2700
2717
  const numDaysInMonth = (new Date(year, month, 0)).getDate();
2701
- if (chooseFromPast) {
2702
- // Past selection
2703
- const numDaysToAdd = ((month === today.month)
2704
- ? today.day // Current month, only add up to today
2705
- : numDaysInMonth // Past month, add all days
2706
- );
2707
- for (let day = 1; day <= numDaysToAdd; day++) {
2708
- days.push(day);
2718
+ // Current month
2719
+ if (month === today.month && year === today.year) {
2720
+ // Past selection: add all previous days of the month
2721
+ if (!dontAllowPast) {
2722
+ for (let day = 1; day < today.day; day++) {
2723
+ days.push(day);
2724
+ }
2709
2725
  }
2710
- }
2711
- else {
2726
+ days.push(today.day); // Add current day
2712
2727
  // Future selection: add all remaining days of the month
2713
- const firstDay = (month === today.month
2714
- ? today.day // Current month: start at current date
2715
- : 1 // Future month: start at beginning of month
2716
- );
2717
- for (let day = firstDay; day <= numDaysInMonth; day++) {
2728
+ if (!dontAllowFuture) {
2729
+ for (let day = today.day + 1; day <= numDaysInMonth; day++) {
2730
+ days.push(day);
2731
+ }
2732
+ }
2733
+ }
2734
+ else { // Past or future month
2735
+ // Include all days in the month
2736
+ for (let day = 1; day <= numDaysInMonth; day++) {
2718
2737
  days.push(day);
2719
2738
  }
2720
2739
  }
@@ -2734,8 +2753,8 @@ const SimpleDateChooser = (props) => {
2734
2753
  monthOptions.push(React__default["default"].createElement("option", { key: `${choice.year}-${choice.month}`, value: `${choice.month}-${choice.year}`, "aria-label": `choose ${choice.choiceName}`, onSelect: () => {
2735
2754
  onChange(choice.month, choice.days[0], choice.year);
2736
2755
  } }, choice.choiceName));
2756
+ // This is the currently selected month
2737
2757
  if (month === choice.month) {
2738
- // This is the currently selected month
2739
2758
  // Create day options
2740
2759
  choice.days.forEach((dayChoice) => {
2741
2760
  const ordinal = getOrdinal(dayChoice);
@@ -2757,6 +2776,125 @@ const SimpleDateChooser = (props) => {
2757
2776
  } }, dayOptions)));
2758
2777
  };
2759
2778
 
2779
+ /**
2780
+ * Pad a number with zeros on the left (e.g. 5 becomes 05 with 2 digit padding)
2781
+ * @author Gabe Abrams
2782
+ * @param num the number to pad
2783
+ * @param numDigits the minimum number of digits before the decimal
2784
+ * @returns padded number
2785
+ */
2786
+ const padZerosLeft = (num, numDigits) => {
2787
+ // Convert to string
2788
+ let out = String(num);
2789
+ // Add zeros
2790
+ while (out.split('.')[0].length < numDigits) {
2791
+ out = `0${out}`;
2792
+ }
2793
+ // Return
2794
+ return out;
2795
+ };
2796
+
2797
+ /**
2798
+ * A very simple, lightweight time chooser
2799
+ * @author Gardenia Liu
2800
+ */
2801
+ /*------------------------------------------------------------------------*/
2802
+ /* ------------------------------ Constants ----------------------------- */
2803
+ /*------------------------------------------------------------------------*/
2804
+ // Allowed intervals between options
2805
+ const ALLOWED_INTERVALS = [15, 30, 60]; // min
2806
+ // Default interval to use if an unsupported interval is passed in
2807
+ const DEFAULT_INTERVAL = ALLOWED_INTERVALS[0]; // min
2808
+ /*------------------------------------------------------------------------*/
2809
+ /* ------------------------------ Component ----------------------------- */
2810
+ /*------------------------------------------------------------------------*/
2811
+ const SimpleTimeChooser = (props) => {
2812
+ /*------------------------------------------------------------------------*/
2813
+ /* -------------------------------- Setup ------------------------------- */
2814
+ /*------------------------------------------------------------------------*/
2815
+ /* -------------- Props ------------- */
2816
+ const { ariaLabel, name, hour, minute, onChange, } = props;
2817
+ let { intervalMin = DEFAULT_INTERVAL, } = props;
2818
+ // Use default interval if not supported
2819
+ if (!ALLOWED_INTERVALS.includes(intervalMin)) {
2820
+ intervalMin = DEFAULT_INTERVAL;
2821
+ }
2822
+ /*------------------------------------------------------------------------*/
2823
+ /* ------------------------- Component Functions ------------------------ */
2824
+ /*------------------------------------------------------------------------*/
2825
+ /**
2826
+ * Convert number of minutes since midnight into 24hour and minute format
2827
+ * @author Gabe Abrams
2828
+ * @param minSinceMidnight total minutes since midnight
2829
+ * @returns hours (24) and minutes
2830
+ */
2831
+ const convertMinSinceMidnightToHoursAndMin = (minSinceMidnight) => {
2832
+ return {
2833
+ hours: Math.floor(minSinceMidnight / 60),
2834
+ minutes: minSinceMidnight % 60,
2835
+ };
2836
+ };
2837
+ /**
2838
+ * Convert time in minutes into HH:MM format
2839
+ * @author Gardenia Liu
2840
+ * @param totalMinutes total minutes since midnight
2841
+ * @returns formatted time string
2842
+ */
2843
+ const formatTime = (totalMinutes) => {
2844
+ // Handle special cases
2845
+ if (totalMinutes === 0) {
2846
+ return '12:00 Midnight';
2847
+ }
2848
+ if (totalMinutes === 12 * 60) {
2849
+ return '12:00 Noon';
2850
+ }
2851
+ // All normal cases:
2852
+ const timeInfo = convertMinSinceMidnightToHoursAndMin(totalMinutes);
2853
+ let { hours } = timeInfo;
2854
+ const { minutes } = timeInfo;
2855
+ // Process 24hr -> 12hr
2856
+ const isAM = (hours < 12);
2857
+ if (hours === 0) {
2858
+ hours = 12;
2859
+ }
2860
+ else if (hours > 12) {
2861
+ hours %= 12;
2862
+ }
2863
+ // Pad with zeros
2864
+ const paddedMinutes = padZerosLeft(minutes, 2);
2865
+ // Assemble time string
2866
+ return `${hours}:${paddedMinutes} ${isAM ? 'AM' : 'PM'}`;
2867
+ };
2868
+ /*------------------------------------------------------------------------*/
2869
+ /* ------------------------------- Render ------------------------------- */
2870
+ /*------------------------------------------------------------------------*/
2871
+ /*----------------------------------------*/
2872
+ /* --------------- Main UI -------------- */
2873
+ /*----------------------------------------*/
2874
+ // Generate list of time options
2875
+ const times = [];
2876
+ for (let time = 0; time < 24 * 60; time += intervalMin) {
2877
+ times.push(formatTime(time));
2878
+ }
2879
+ // Currently selected time in minutes since midnight
2880
+ const selectedTimeMin = hour * 60 + minute;
2881
+ // Create choice options
2882
+ const timeOptions = times.map((timeString, timeIndex) => {
2883
+ const numMinutesForChoice = timeIndex * intervalMin;
2884
+ // Render the option
2885
+ return (React__default["default"].createElement("option", { key: numMinutesForChoice, value: numMinutesForChoice, "aria-label": `choose ${timeString}` }, timeString));
2886
+ });
2887
+ return (React__default["default"].createElement("div", { className: "SimpleTimeChooser-container", "aria-label": `time chooser with selected time: ${formatTime(selectedTimeMin)}` },
2888
+ React__default["default"].createElement("select", { "aria-label": `time for ${ariaLabel}`, className: "custom-select d-inline-block", style: { width: 'auto' }, id: `SimpleTimeChooser-${name}-time`, value: selectedTimeMin, onChange: (e) => {
2889
+ // Parse selector value (string)
2890
+ const newTime = Number.parseInt(e.target.value, 10);
2891
+ // Convert minutes since midnight to hour and minute
2892
+ const timeInfo = convertMinSinceMidnightToHoursAndMin(newTime);
2893
+ // Notify parent
2894
+ onChange(timeInfo.hours, timeInfo.minutes);
2895
+ } }, timeOptions)));
2896
+ };
2897
+
2760
2898
  /**
2761
2899
  * Drawer container
2762
2900
  * @author Gabe Abrams
@@ -4851,14 +4989,14 @@ const LogReviewer = (props) => {
4851
4989
  if (expandedFilterDrawer) {
4852
4990
  if (expandedFilterDrawer === FilterDrawer.Date) {
4853
4991
  filterDrawer = (React__default["default"].createElement(TabBox, { title: "Date" },
4854
- React__default["default"].createElement(SimpleDateChooser, { ariaLabel: "filter start date", name: "filter-start-date", year: dateFilterState.startDate.year, month: dateFilterState.startDate.month, day: dateFilterState.startDate.day, chooseFromPast: true, numMonthsToShow: 36, onChange: (month, day, year) => {
4992
+ React__default["default"].createElement(SimpleDateChooser, { ariaLabel: "filter start date", name: "filter-start-date", year: dateFilterState.startDate.year, month: dateFilterState.startDate.month, day: dateFilterState.startDate.day, dontAllowFuture: true, numMonthsToShow: 36, onChange: (month, day, year) => {
4855
4993
  dateFilterState.startDate = { month, day, year };
4856
4994
  handleDateRangeUpdated(dateFilterState);
4857
4995
  } }),
4858
4996
  ' ',
4859
4997
  "to",
4860
4998
  ' ',
4861
- React__default["default"].createElement(SimpleDateChooser, { ariaLabel: "filter end date", name: "filter-end-date", year: dateFilterState.endDate.year, month: dateFilterState.endDate.month, day: dateFilterState.endDate.day, chooseFromPast: true, numMonthsToShow: 12, onChange: (month, day, year) => {
4999
+ React__default["default"].createElement(SimpleDateChooser, { ariaLabel: "filter end date", name: "filter-end-date", year: dateFilterState.endDate.year, month: dateFilterState.endDate.month, day: dateFilterState.endDate.day, dontAllowFuture: true, numMonthsToShow: 12, onChange: (month, day, year) => {
4862
5000
  if (year < dateFilterState.startDate.year
4863
5001
  || (year === dateFilterState.startDate.year
4864
5002
  && month < dateFilterState.startDate.month)
@@ -15338,24 +15476,6 @@ const padDecimalZeros = (num, numDigits) => {
15338
15476
  return out;
15339
15477
  };
15340
15478
 
15341
- /**
15342
- * Pad a number with zeros on the left (e.g. 5 becomes 05 with 2 digit padding)
15343
- * @author Gabe Abrams
15344
- * @param num the number to pad
15345
- * @param numDigits the minimum number of digits before the decimal
15346
- * @returns padded number
15347
- */
15348
- const padZerosLeft = (num, numDigits) => {
15349
- // Convert to string
15350
- let out = String(num);
15351
- // Add zeros
15352
- while (out.split('.')[0].length < numDigits) {
15353
- out = `0${out}`;
15354
- }
15355
- // Return
15356
- return out;
15357
- };
15358
-
15359
15479
  /**
15360
15480
  * Stub a server endpoint response
15361
15481
  * @author Gabe Abrams
@@ -16268,6 +16388,7 @@ exports.PopSuccessMark = PopSuccessMark;
16268
16388
  exports.RadioButton = RadioButton;
16269
16389
  exports.ReactKitErrorCode = ReactKitErrorCode$1;
16270
16390
  exports.SimpleDateChooser = SimpleDateChooser;
16391
+ exports.SimpleTimeChooser = SimpleTimeChooser;
16271
16392
  exports.TabBox = TabBox;
16272
16393
  exports.ToggleSwitch = ToggleSwitch;
16273
16394
  exports.Tooltip = Tooltip;