dce-reactkit 4.0.0 → 4.0.2-beta-simple-date-chooser.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,35 +2653,86 @@ 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
- /* ------------------------------ Component ----------------------------- */
2659
+ /* -------------------------------- State ------------------------------- */
2657
2660
  /*------------------------------------------------------------------------*/
2658
- const SimpleDateChooser = (props) => {
2659
- /*------------------------------------------------------------------------*/
2660
- /* -------------------------------- Setup ------------------------------- */
2661
- /*------------------------------------------------------------------------*/
2662
- /* -------------- Props ------------- */
2663
- const { ariaLabel, name, onChange, chooseFromPast, numMonthsToShow = 6, } = props;
2664
- /*------------------------------------------------------------------------*/
2665
- /* ------------------------------- Render ------------------------------- */
2666
- /*------------------------------------------------------------------------*/
2667
- /*----------------------------------------*/
2668
- /* --------------- Main UI -------------- */
2669
- /*----------------------------------------*/
2661
+ /* -------------- Views ------------- */
2662
+ var View;
2663
+ (function (View) {
2664
+ // Date chooser
2665
+ View["DateChooser"] = "DateChooser";
2666
+ // Invalid date
2667
+ View["InvalidDate"] = "InvalidDate";
2668
+ })(View || (View = {}));
2669
+ /* ------------- Actions ------------ */
2670
+ // Types of actions
2671
+ var ActionType$a;
2672
+ (function (ActionType) {
2673
+ // Fix invalid date so it is now in range
2674
+ ActionType["FixInvalidDate"] = "FixInvalidDate";
2675
+ })(ActionType$a || (ActionType$a = {}));
2676
+ /**
2677
+ * Reducer that executes actions
2678
+ * @author Gardenia Liu
2679
+ * @param state current state
2680
+ * @param action action to execute
2681
+ * @returns updated state
2682
+ */
2683
+ const reducer$b = (state, action) => {
2684
+ switch (action.type) {
2685
+ case ActionType$a.FixInvalidDate: {
2686
+ return Object.assign(Object.assign({}, state), { view: View.DateChooser });
2687
+ }
2688
+ default: {
2689
+ return state;
2690
+ }
2691
+ }
2692
+ };
2693
+ /*------------------------------------------------------------------------*/
2694
+ /* --------------------------- Static Helpers --------------------------- */
2695
+ /*------------------------------------------------------------------------*/
2696
+ /**
2697
+ * Get the list of choices in the date chooser given props
2698
+ * @author Gardenia Liu
2699
+ * @author Gabe Abrams
2700
+ * @param opts object containing all arguments
2701
+ * @param opts.numMonthsToShow number of months to show
2702
+ * @param opts.dontAllowPast if true, the user isn't allowed to select dates in the past
2703
+ * @param opts.dontAllowFuture if true, the user isn't allowed to select dates in the future
2704
+ * @returns choices
2705
+ */
2706
+ const getChoices = (opts) => {
2707
+ // Destructure props
2708
+ const { dontAllowFuture, dontAllowPast, numMonthsToShow = 6, } = opts;
2670
2709
  // Determine the set of choices allowed
2671
2710
  const today = getTimeInfoInET();
2672
2711
  const choices = [];
2673
2712
  let startYear = today.year;
2674
2713
  let startMonth = today.month;
2675
- if (chooseFromPast) {
2714
+ // Don't allow past or future dates
2715
+ if (dontAllowPast && dontAllowFuture) {
2716
+ throw new ErrorWithCode('No past or future dates allowed', ReactKitErrorCode$1.SimpleDateChooserInvalidDateRange);
2717
+ }
2718
+ // Require numMonthsToShow to be positive
2719
+ if (numMonthsToShow <= 0) {
2720
+ throw new ErrorWithCode('numMonthsToShow must be positive', ReactKitErrorCode$1.SimpleDateChooserInvalidNumMonths);
2721
+ }
2722
+ // Recalculate startMonth and startYear when allowing past dates
2723
+ if (!dontAllowPast) {
2676
2724
  startMonth -= Math.max(0, numMonthsToShow - 1);
2677
2725
  while (startMonth <= 0) {
2678
2726
  startMonth += 12;
2679
2727
  startYear -= 1;
2680
2728
  }
2681
2729
  }
2682
- for (let i = 0; i < numMonthsToShow; i++) {
2730
+ // Calculate total number of months to show
2731
+ let totalMonthsToShow = numMonthsToShow;
2732
+ if (!dontAllowPast && !dontAllowFuture) {
2733
+ totalMonthsToShow = totalMonthsToShow * 2 - 1;
2734
+ }
2735
+ for (let i = 0; i < totalMonthsToShow; i++) {
2683
2736
  // Get month and year info
2684
2737
  const unmoddedMonth = (startMonth + i);
2685
2738
  let month = unmoddedMonth;
@@ -2698,23 +2751,25 @@ const SimpleDateChooser = (props) => {
2698
2751
  // Figure out which days are allowed
2699
2752
  const days = [];
2700
2753
  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);
2754
+ // Current month
2755
+ if (month === today.month && year === today.year) {
2756
+ // Past selection: add all previous days of the month
2757
+ if (!dontAllowPast) {
2758
+ for (let day = 1; day < today.day; day++) {
2759
+ days.push(day);
2760
+ }
2709
2761
  }
2710
- }
2711
- else {
2762
+ days.push(today.day); // Add current day
2712
2763
  // 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++) {
2764
+ if (!dontAllowFuture) {
2765
+ for (let day = today.day + 1; day <= numDaysInMonth; day++) {
2766
+ days.push(day);
2767
+ }
2768
+ }
2769
+ }
2770
+ else { // Past or future month
2771
+ // Include all days in the month
2772
+ for (let day = 1; day <= numDaysInMonth; day++) {
2718
2773
  days.push(day);
2719
2774
  }
2720
2775
  }
@@ -2725,36 +2780,262 @@ const SimpleDateChooser = (props) => {
2725
2780
  days,
2726
2781
  });
2727
2782
  }
2728
- // Create choice options
2729
- const { month, day, year, } = props;
2730
- const monthOptions = [];
2731
- const dayOptions = [];
2732
- choices.forEach((choice) => {
2733
- // Create month option
2734
- monthOptions.push(React__default["default"].createElement("option", { key: `${choice.year}-${choice.month}`, value: `${choice.month}-${choice.year}`, "aria-label": `choose ${choice.choiceName}`, onSelect: () => {
2735
- onChange(choice.month, choice.days[0], choice.year);
2736
- } }, choice.choiceName));
2737
- if (month === choice.month) {
2738
- // This is the currently selected month
2739
- // Create day options
2740
- choice.days.forEach((dayChoice) => {
2741
- const ordinal = getOrdinal(dayChoice);
2742
- dayOptions.push(React__default["default"].createElement("option", { key: `${choice.year}-${choice.month}-${dayChoice}`, value: dayChoice, "aria-label": `choose date ${dayChoice}` },
2743
- dayChoice,
2744
- ordinal));
2783
+ // Return choices
2784
+ return choices;
2785
+ };
2786
+ /**
2787
+ * Checks whether a given date is outside the valid range of allowed choices
2788
+ * @author Gardenia Liu
2789
+ * @param opts object containing all arguments
2790
+ * @param opts.month 1-indexed month
2791
+ * @param opts.day day of the month
2792
+ * @param opts.year full year
2793
+ * @param opts.choices valid date choices
2794
+ * @returns true if date is out of range
2795
+ */
2796
+ const isDateOutOfRange = (opts) => {
2797
+ const { month, day, year, choices, } = opts;
2798
+ return !choices.some((choice) => {
2799
+ return (choice.month === month
2800
+ && choice.year === year
2801
+ && choice.days.includes(day));
2802
+ });
2803
+ };
2804
+ /*------------------------------------------------------------------------*/
2805
+ /* ------------------------------ Component ----------------------------- */
2806
+ /*------------------------------------------------------------------------*/
2807
+ const SimpleDateChooser = (props) => {
2808
+ /*------------------------------------------------------------------------*/
2809
+ /* -------------------------------- Setup ------------------------------- */
2810
+ /*------------------------------------------------------------------------*/
2811
+ /* -------------- Props ------------- */
2812
+ const { ariaLabel, name, dontAllowPast, dontAllowFuture, numMonthsToShow, onChange, month, day, year, } = props;
2813
+ // Get choices
2814
+ const choices = getChoices({
2815
+ numMonthsToShow,
2816
+ dontAllowPast,
2817
+ dontAllowFuture,
2818
+ });
2819
+ /* -------------- State ------------- */
2820
+ // Check if the currently selected date is out of range
2821
+ const currentSelectedDateOutOfRange = isDateOutOfRange({
2822
+ month,
2823
+ day,
2824
+ year,
2825
+ choices,
2826
+ });
2827
+ // Initial state
2828
+ const initialState = {
2829
+ view: (currentSelectedDateOutOfRange
2830
+ ? View.InvalidDate
2831
+ : View.DateChooser),
2832
+ };
2833
+ // Initialize state
2834
+ const [state, dispatch] = React.useReducer(reducer$b, initialState);
2835
+ // Destructure common state
2836
+ const { view, } = state;
2837
+ /*------------------------------------------------------------------------*/
2838
+ /* ------------------------- Component Functions ------------------------ */
2839
+ /*------------------------------------------------------------------------*/
2840
+ /**
2841
+ * Ask the user if they want to edit an invalid date
2842
+ * @author Gardenia Liu
2843
+ * @author Gabe Abrams
2844
+ */
2845
+ const askToEditInvalidDate = () => __awaiter(void 0, void 0, void 0, function* () {
2846
+ // Ask the user if they want to edit the date
2847
+ const confirmed = yield confirm('Are you sure?', 'The current date is outside the normal range. If you edit it, you\'ll need to choose a new date in the normal range.', {
2848
+ confirmButtonText: 'Edit Date',
2849
+ });
2850
+ // Check if user confirmed
2851
+ if (confirmed) {
2852
+ // Update the date to today
2853
+ const today = getTimeInfoInET();
2854
+ onChange(today.month, today.day, today.year);
2855
+ // Update state
2856
+ dispatch({
2857
+ type: ActionType$a.FixInvalidDate,
2745
2858
  });
2746
2859
  }
2747
2860
  });
2748
- return (React__default["default"].createElement("div", { className: "SimpleDateChooser d-inline-block", "aria-label": `date chooser with selected date: ${month}/${day}/${year}` },
2749
- React__default["default"].createElement("select", { "aria-label": `month for ${ariaLabel}`, className: "custom-select d-inline-block mr-1", style: { width: 'auto' }, id: `SimpleDateChooser-${name}-month`, value: `${month}-${year}`, onChange: (e) => {
2750
- const choice = choices[e.target.selectedIndex];
2751
- // Change day, month, and year
2752
- onChange(choice.month, choice.days[0], choice.year);
2753
- } }, monthOptions),
2754
- React__default["default"].createElement("select", { "aria-label": `day for ${ariaLabel}`, className: "custom-select d-inline-block", style: { width: 'auto' }, id: `SimpleDateChooser-${name}-day`, value: day, onChange: (e) => {
2755
- // Only change the day
2756
- onChange(month, Number.parseInt(e.target.value, 10), year);
2757
- } }, dayOptions)));
2861
+ /*------------------------------------------------------------------------*/
2862
+ /* ------------------------------- Render ------------------------------- */
2863
+ /*------------------------------------------------------------------------*/
2864
+ /*----------------------------------------*/
2865
+ /* ---------------- Views --------------- */
2866
+ /*----------------------------------------*/
2867
+ // Body that will be filled with the current view
2868
+ let body;
2869
+ /* ---------- DateChooser ---------- */
2870
+ if (view === View.DateChooser) {
2871
+ // Create lists of options
2872
+ const monthOptions = [];
2873
+ const dayOptions = [];
2874
+ // Render each option and add it to the list
2875
+ choices.forEach((choice) => {
2876
+ // Create month option
2877
+ monthOptions.push(React__default["default"].createElement("option", { key: `${choice.year}-${choice.month}`, value: `${choice.month}-${choice.year}`, "aria-label": `choose ${choice.choiceName}`, onSelect: () => {
2878
+ onChange(choice.month, choice.days[0], choice.year);
2879
+ } }, choice.choiceName));
2880
+ // This is the currently selected month
2881
+ if (month === choice.month) {
2882
+ // Create day options
2883
+ choice.days.forEach((dayChoice) => {
2884
+ const ordinal = getOrdinal(dayChoice);
2885
+ dayOptions.push(React__default["default"].createElement("option", { key: `${choice.year}-${choice.month}-${dayChoice}`, value: dayChoice, "aria-label": `choose date ${dayChoice}` },
2886
+ dayChoice,
2887
+ ordinal));
2888
+ });
2889
+ }
2890
+ });
2891
+ // Create body
2892
+ body = (React__default["default"].createElement("div", { className: "SimpleDateChooser-inner-container d-inline-block", "aria-label": `date chooser with selected date: ${month}/${day}/${year}` },
2893
+ React__default["default"].createElement("select", { "aria-label": `month for ${ariaLabel}`, className: "custom-select d-inline-block mr-1", style: { width: 'auto' }, id: `SimpleDateChooser-${name}-month`, value: `${month}-${year}`, onChange: (e) => {
2894
+ const choice = choices[e.target.selectedIndex];
2895
+ // Change day, month, and year
2896
+ onChange(choice.month, choice.days[0], choice.year);
2897
+ } }, monthOptions),
2898
+ React__default["default"].createElement("select", { "aria-label": `day for ${ariaLabel}`, className: "custom-select d-inline-block", style: { width: 'auto' }, id: `SimpleDateChooser-${name}-day`, value: day, onChange: (e) => {
2899
+ // Only change the day
2900
+ onChange(month, Number.parseInt(e.target.value, 10), year);
2901
+ } }, dayOptions)));
2902
+ }
2903
+ /* --------- DateOutOfRange --------- */
2904
+ if (view === View.InvalidDate) {
2905
+ body = (React__default["default"].createElement("div", { className: "SimpleDateChooser-inner-container d-inline-block" },
2906
+ React__default["default"].createElement("button", { type: "button", className: "btn btn-light", onClick: askToEditInvalidDate, "aria-label": `edit date for ${ariaLabel}` },
2907
+ getMonthName(month).full,
2908
+ ' ',
2909
+ day,
2910
+ getOrdinal(day),
2911
+ ",",
2912
+ ' ',
2913
+ year),
2914
+ React__default["default"].createElement("button", { type: "button", className: "btn btn-secondary", onClick: askToEditInvalidDate, "aria-label": `edit date for ${ariaLabel}` }, "Edit")));
2915
+ }
2916
+ /*----------------------------------------*/
2917
+ /* --------------- Main UI -------------- */
2918
+ /*----------------------------------------*/
2919
+ return (React__default["default"].createElement("span", { className: "SimpleDateChooser-outer-container" }, body));
2920
+ };
2921
+
2922
+ /**
2923
+ * Pad a number with zeros on the left (e.g. 5 becomes 05 with 2 digit padding)
2924
+ * @author Gabe Abrams
2925
+ * @param num the number to pad
2926
+ * @param numDigits the minimum number of digits before the decimal
2927
+ * @returns padded number
2928
+ */
2929
+ const padZerosLeft = (num, numDigits) => {
2930
+ // Convert to string
2931
+ let out = String(num);
2932
+ // Add zeros
2933
+ while (out.split('.')[0].length < numDigits) {
2934
+ out = `0${out}`;
2935
+ }
2936
+ // Return
2937
+ return out;
2938
+ };
2939
+
2940
+ /**
2941
+ * A very simple, lightweight time chooser
2942
+ * @author Gardenia Liu
2943
+ */
2944
+ /*------------------------------------------------------------------------*/
2945
+ /* ------------------------------ Constants ----------------------------- */
2946
+ /*------------------------------------------------------------------------*/
2947
+ // Allowed intervals between options
2948
+ const ALLOWED_INTERVALS = [15, 30, 60]; // min
2949
+ // Default interval to use if an unsupported interval is passed in
2950
+ const DEFAULT_INTERVAL = ALLOWED_INTERVALS[0]; // min
2951
+ /*------------------------------------------------------------------------*/
2952
+ /* ------------------------------ Component ----------------------------- */
2953
+ /*------------------------------------------------------------------------*/
2954
+ const SimpleTimeChooser = (props) => {
2955
+ /*------------------------------------------------------------------------*/
2956
+ /* -------------------------------- Setup ------------------------------- */
2957
+ /*------------------------------------------------------------------------*/
2958
+ /* -------------- Props ------------- */
2959
+ const { ariaLabel, name, hour, minute, onChange, } = props;
2960
+ let { intervalMin = DEFAULT_INTERVAL, } = props;
2961
+ // Use default interval if not supported
2962
+ if (!ALLOWED_INTERVALS.includes(intervalMin)) {
2963
+ intervalMin = DEFAULT_INTERVAL;
2964
+ }
2965
+ /*------------------------------------------------------------------------*/
2966
+ /* ------------------------- Component Functions ------------------------ */
2967
+ /*------------------------------------------------------------------------*/
2968
+ /**
2969
+ * Convert number of minutes since midnight into 24hour and minute format
2970
+ * @author Gabe Abrams
2971
+ * @param minSinceMidnight total minutes since midnight
2972
+ * @returns hours (24) and minutes
2973
+ */
2974
+ const convertMinSinceMidnightToHoursAndMin = (minSinceMidnight) => {
2975
+ return {
2976
+ hours: Math.floor(minSinceMidnight / 60),
2977
+ minutes: minSinceMidnight % 60,
2978
+ };
2979
+ };
2980
+ /**
2981
+ * Convert time in minutes into HH:MM format
2982
+ * @author Gardenia Liu
2983
+ * @param totalMinutes total minutes since midnight
2984
+ * @returns formatted time string
2985
+ */
2986
+ const formatTime = (totalMinutes) => {
2987
+ // Handle special cases
2988
+ if (totalMinutes === 0) {
2989
+ return '12:00 Midnight';
2990
+ }
2991
+ if (totalMinutes === 12 * 60) {
2992
+ return '12:00 Noon';
2993
+ }
2994
+ // All normal cases:
2995
+ const timeInfo = convertMinSinceMidnightToHoursAndMin(totalMinutes);
2996
+ let { hours } = timeInfo;
2997
+ const { minutes } = timeInfo;
2998
+ // Process 24hr -> 12hr
2999
+ const isAM = (hours < 12);
3000
+ if (hours === 0) {
3001
+ hours = 12;
3002
+ }
3003
+ else if (hours > 12) {
3004
+ hours %= 12;
3005
+ }
3006
+ // Pad with zeros
3007
+ const paddedMinutes = padZerosLeft(minutes, 2);
3008
+ // Assemble time string
3009
+ return `${hours}:${paddedMinutes} ${isAM ? 'AM' : 'PM'}`;
3010
+ };
3011
+ /*------------------------------------------------------------------------*/
3012
+ /* ------------------------------- Render ------------------------------- */
3013
+ /*------------------------------------------------------------------------*/
3014
+ /*----------------------------------------*/
3015
+ /* --------------- Main UI -------------- */
3016
+ /*----------------------------------------*/
3017
+ // Generate list of time options
3018
+ const times = [];
3019
+ for (let time = 0; time < 24 * 60; time += intervalMin) {
3020
+ times.push(formatTime(time));
3021
+ }
3022
+ // Currently selected time in minutes since midnight
3023
+ const selectedTimeMin = hour * 60 + minute;
3024
+ // Create choice options
3025
+ const timeOptions = times.map((timeString, timeIndex) => {
3026
+ const numMinutesForChoice = timeIndex * intervalMin;
3027
+ // Render the option
3028
+ return (React__default["default"].createElement("option", { key: numMinutesForChoice, value: numMinutesForChoice, "aria-label": `choose ${timeString}` }, timeString));
3029
+ });
3030
+ return (React__default["default"].createElement("div", { className: "SimpleTimeChooser-container", "aria-label": `time chooser with selected time: ${formatTime(selectedTimeMin)}` },
3031
+ 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) => {
3032
+ // Parse selector value (string)
3033
+ const newTime = Number.parseInt(e.target.value, 10);
3034
+ // Convert minutes since midnight to hour and minute
3035
+ const timeInfo = convertMinSinceMidnightToHoursAndMin(newTime);
3036
+ // Notify parent
3037
+ onChange(timeInfo.hours, timeInfo.minutes);
3038
+ } }, timeOptions)));
2758
3039
  };
2759
3040
 
2760
3041
  /**
@@ -4851,14 +5132,14 @@ const LogReviewer = (props) => {
4851
5132
  if (expandedFilterDrawer) {
4852
5133
  if (expandedFilterDrawer === FilterDrawer.Date) {
4853
5134
  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) => {
5135
+ 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
5136
  dateFilterState.startDate = { month, day, year };
4856
5137
  handleDateRangeUpdated(dateFilterState);
4857
5138
  } }),
4858
5139
  ' ',
4859
5140
  "to",
4860
5141
  ' ',
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) => {
5142
+ 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
5143
  if (year < dateFilterState.startDate.year
4863
5144
  || (year === dateFilterState.startDate.year
4864
5145
  && month < dateFilterState.startDate.month)
@@ -15338,24 +15619,6 @@ const padDecimalZeros = (num, numDigits) => {
15338
15619
  return out;
15339
15620
  };
15340
15621
 
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
15622
  /**
15360
15623
  * Stub a server endpoint response
15361
15624
  * @author Gabe Abrams
@@ -16268,6 +16531,7 @@ exports.PopSuccessMark = PopSuccessMark;
16268
16531
  exports.RadioButton = RadioButton;
16269
16532
  exports.ReactKitErrorCode = ReactKitErrorCode$1;
16270
16533
  exports.SimpleDateChooser = SimpleDateChooser;
16534
+ exports.SimpleTimeChooser = SimpleTimeChooser;
16271
16535
  exports.TabBox = TabBox;
16272
16536
  exports.ToggleSwitch = ToggleSwitch;
16273
16537
  exports.Tooltip = Tooltip;