dce-reactkit 4.0.0-beta-date-and-time.1 → 4.0.0-beta.2
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/.vscode/settings.json +1 -3
- package/README.md +20 -0
- package/dist/cjs/index.js +167 -392
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/components/ItemPicker/index.d.ts +0 -1
- package/dist/cjs/types/components/Modal/ModalProps.d.ts +0 -2
- package/dist/cjs/types/components/SimpleDateChooser.d.ts +1 -3
- package/dist/cjs/types/components/TabBox.d.ts +0 -1
- package/dist/cjs/types/index.d.ts +1 -3
- package/dist/cjs/types/types/ReactKitErrorCode.d.ts +1 -3
- package/dist/esm/index.js +169 -392
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/components/ItemPicker/index.d.ts +0 -1
- package/dist/esm/types/components/Modal/ModalProps.d.ts +0 -2
- package/dist/esm/types/components/SimpleDateChooser.d.ts +1 -3
- package/dist/esm/types/components/TabBox.d.ts +0 -1
- package/dist/esm/types/index.d.ts +1 -3
- package/dist/esm/types/types/ReactKitErrorCode.d.ts +1 -3
- package/dist/index.d.ts +17 -55
- package/package.json +2 -2
- package/src/components/IntelliTable.tsx +1 -1
- package/src/components/ItemPicker/NestableItemList.tsx +0 -1
- package/src/components/ItemPicker/index.tsx +0 -96
- package/src/components/LogReviewer.tsx +2 -2
- package/src/components/Modal/ModalProps.ts +0 -4
- package/src/components/Modal/index.tsx +20 -59
- package/src/components/SimpleDateChooser.tsx +26 -62
- package/src/components/TabBox.tsx +9 -27
- package/src/index.ts +0 -4
- package/src/types/ReactKitErrorCode.tsx +1 -3
- package/dist/cjs/types/components/SimpleTimeChooser.d.ts +0 -20
- package/dist/cjs/types/helpers/getWordCount.d.ts +0 -10
- package/dist/esm/types/components/SimpleTimeChooser.d.ts +0 -20
- package/dist/esm/types/helpers/getWordCount.d.ts +0 -10
- package/src/components/SimpleTimeChooser.tsx +0 -195
- package/src/helpers/getWordCount.ts +0 -26
|
@@ -1,23 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A very simple, lightweight date chooser
|
|
3
3
|
* @author Gabe Abrams
|
|
4
|
-
* @author Gardeniu Liu
|
|
5
4
|
*/
|
|
6
5
|
|
|
7
6
|
// Import React
|
|
8
7
|
import React from 'react';
|
|
8
|
+
import getMonthName from '../helpers/getMonthName';
|
|
9
9
|
|
|
10
10
|
// Import helpers
|
|
11
11
|
import getOrdinal from '../helpers/getOrdinal';
|
|
12
|
-
import getMonthName from '../helpers/getMonthName';
|
|
13
12
|
import getTimeInfoInET from '../helpers/getTimeInfoInET';
|
|
14
13
|
|
|
15
|
-
// Import classes
|
|
16
|
-
import ErrorWithCode from '../errors/ErrorWithCode';
|
|
17
|
-
|
|
18
|
-
// Import types
|
|
19
|
-
import ReactKitErrorCode from '../types/ReactKitErrorCode';
|
|
20
|
-
|
|
21
14
|
/*------------------------------------------------------------------------*/
|
|
22
15
|
/* -------------------------------- Types ------------------------------- */
|
|
23
16
|
/*------------------------------------------------------------------------*/
|
|
@@ -40,14 +33,12 @@ type Props = {
|
|
|
40
33
|
* @param year new full year number
|
|
41
34
|
*/
|
|
42
35
|
onChange: (month: number, day: number, year: number) => void,
|
|
43
|
-
// Number of months
|
|
44
|
-
//
|
|
45
|
-
// (max is 12, default is 6 in the past and 6 in the future)
|
|
36
|
+
// Number of months to allow the user to choose from
|
|
37
|
+
// (max is 12, default is 6)
|
|
46
38
|
numMonthsToShow?: number,
|
|
47
|
-
// If true,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
dontAllowFuture?: boolean,
|
|
39
|
+
// If true, instead of showing numMonthsToShow months into the future,
|
|
40
|
+
// show numMonthsToShow months into the past
|
|
41
|
+
chooseFromPast?: boolean,
|
|
51
42
|
};
|
|
52
43
|
|
|
53
44
|
/*------------------------------------------------------------------------*/
|
|
@@ -65,9 +56,8 @@ const SimpleDateChooser: React.FC<Props> = (props) => {
|
|
|
65
56
|
ariaLabel,
|
|
66
57
|
name,
|
|
67
58
|
onChange,
|
|
59
|
+
chooseFromPast,
|
|
68
60
|
numMonthsToShow = 6,
|
|
69
|
-
dontAllowFuture,
|
|
70
|
-
dontAllowPast,
|
|
71
61
|
} = props;
|
|
72
62
|
|
|
73
63
|
/*------------------------------------------------------------------------*/
|
|
@@ -86,41 +76,16 @@ const SimpleDateChooser: React.FC<Props> = (props) => {
|
|
|
86
76
|
days: number[],
|
|
87
77
|
year: number,
|
|
88
78
|
}[] = [];
|
|
89
|
-
|
|
90
79
|
let startYear = today.year;
|
|
91
80
|
let startMonth = today.month;
|
|
92
|
-
|
|
93
|
-
// Don't allow past or future dates
|
|
94
|
-
if (dontAllowPast && dontAllowFuture) {
|
|
95
|
-
throw new ErrorWithCode(
|
|
96
|
-
'No past or future dates allowed',
|
|
97
|
-
ReactKitErrorCode.SimpleDateChooserInvalidDateRange,
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Require numMonthsToShow to be positive
|
|
102
|
-
if (numMonthsToShow <= 0) {
|
|
103
|
-
throw new ErrorWithCode(
|
|
104
|
-
'numMonthsToShow must be positive',
|
|
105
|
-
ReactKitErrorCode.SimpleDateChooserInvalidNumMonths,
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Recalculate startMonth and startYear when allowing past dates
|
|
110
|
-
if (!dontAllowPast) {
|
|
81
|
+
if (chooseFromPast) {
|
|
111
82
|
startMonth -= Math.max(0, numMonthsToShow - 1);
|
|
112
83
|
while (startMonth <= 0) {
|
|
113
84
|
startMonth += 12;
|
|
114
85
|
startYear -= 1;
|
|
115
86
|
}
|
|
116
87
|
}
|
|
117
|
-
|
|
118
|
-
let totalMonthsToShow = numMonthsToShow;
|
|
119
|
-
if (!dontAllowPast && !dontAllowFuture) {
|
|
120
|
-
totalMonthsToShow = totalMonthsToShow * 2 - 1;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
for (let i = 0; i < totalMonthsToShow; i++) {
|
|
88
|
+
for (let i = 0; i < numMonthsToShow; i++) {
|
|
124
89
|
// Get month and year info
|
|
125
90
|
const unmoddedMonth = (startMonth + i);
|
|
126
91
|
let month = unmoddedMonth;
|
|
@@ -140,25 +105,24 @@ const SimpleDateChooser: React.FC<Props> = (props) => {
|
|
|
140
105
|
// Figure out which days are allowed
|
|
141
106
|
const days = [];
|
|
142
107
|
const numDaysInMonth = (new Date(year, month, 0)).getDate();
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
108
|
+
if (chooseFromPast) {
|
|
109
|
+
// Past selection
|
|
110
|
+
const numDaysToAdd = (
|
|
111
|
+
(month === today.month)
|
|
112
|
+
? today.day // Current month, only add up to today
|
|
113
|
+
: numDaysInMonth // Past month, add all days
|
|
114
|
+
);
|
|
115
|
+
for (let day = 1; day <= numDaysToAdd; day++) {
|
|
116
|
+
days.push(day);
|
|
151
117
|
}
|
|
152
|
-
|
|
118
|
+
} else {
|
|
153
119
|
// Future selection: add all remaining days of the month
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
// Include all days in the month
|
|
161
|
-
for (let day = 1; day <= numDaysInMonth; day++) {
|
|
120
|
+
const firstDay = (
|
|
121
|
+
month === today.month
|
|
122
|
+
? today.day // Current month: start at current date
|
|
123
|
+
: 1 // Future month: start at beginning of month
|
|
124
|
+
);
|
|
125
|
+
for (let day = firstDay; day <= numDaysInMonth; day++) {
|
|
162
126
|
days.push(day);
|
|
163
127
|
}
|
|
164
128
|
}
|
|
@@ -194,8 +158,8 @@ const SimpleDateChooser: React.FC<Props> = (props) => {
|
|
|
194
158
|
</option>,
|
|
195
159
|
);
|
|
196
160
|
|
|
197
|
-
// This is the currently selected month
|
|
198
161
|
if (month === choice.month) {
|
|
162
|
+
// This is the currently selected month
|
|
199
163
|
// Create day options
|
|
200
164
|
choice.days.forEach((dayChoice) => {
|
|
201
165
|
const ordinal = getOrdinal(dayChoice);
|
|
@@ -15,8 +15,6 @@ type Props = {
|
|
|
15
15
|
title: React.ReactNode,
|
|
16
16
|
// Children/contents inside the box
|
|
17
17
|
children: React.ReactNode,
|
|
18
|
-
// Children to display on the top right of the tab box
|
|
19
|
-
topRightChildren?: React.ReactNode,
|
|
20
18
|
// If true, don't add margin below the tab box
|
|
21
19
|
noBottomMargin?: boolean,
|
|
22
20
|
// If true, don't add padding to bottom of tab box
|
|
@@ -51,9 +49,7 @@ const style = `
|
|
|
51
49
|
|
|
52
50
|
/* Container for Title */
|
|
53
51
|
.TabBox-title-container {
|
|
54
|
-
|
|
55
|
-
justify-content: space-between;
|
|
56
|
-
align-items: center;
|
|
52
|
+
/* Place on Left */
|
|
57
53
|
position: relative;
|
|
58
54
|
left: 0;
|
|
59
55
|
text-align: left;
|
|
@@ -86,19 +82,6 @@ const style = `
|
|
|
86
82
|
background: #fdfdfd;
|
|
87
83
|
}
|
|
88
84
|
|
|
89
|
-
.TabBox-title-right-container {
|
|
90
|
-
display: flex;
|
|
91
|
-
flex-direction: row;
|
|
92
|
-
align-items: bottom;
|
|
93
|
-
height: 2.4rem;
|
|
94
|
-
overflow: visible;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
.TabBox-title-right-contents {
|
|
98
|
-
margin-right: 0.5rem;
|
|
99
|
-
margin-bottom: 0.2rem;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
85
|
/* Make the TabBox's Children Appear Above Title if Overlap Occurs */
|
|
103
86
|
.TabBox-children {
|
|
104
87
|
position: relative;
|
|
@@ -115,10 +98,11 @@ const TabBox: React.FC<Props> = (props) => {
|
|
|
115
98
|
/* -------------------------------- Setup ------------------------------- */
|
|
116
99
|
/*------------------------------------------------------------------------*/
|
|
117
100
|
|
|
101
|
+
/* -------------- Props ------------- */
|
|
102
|
+
|
|
118
103
|
const {
|
|
119
104
|
title,
|
|
120
105
|
children,
|
|
121
|
-
topRightChildren,
|
|
122
106
|
noBottomPadding,
|
|
123
107
|
noBottomMargin,
|
|
124
108
|
} = props;
|
|
@@ -127,23 +111,21 @@ const TabBox: React.FC<Props> = (props) => {
|
|
|
127
111
|
/* ------------------------------- Render ------------------------------- */
|
|
128
112
|
/*------------------------------------------------------------------------*/
|
|
129
113
|
|
|
114
|
+
/*----------------------------------------*/
|
|
115
|
+
/* --------------- Main UI -------------- */
|
|
116
|
+
/*----------------------------------------*/
|
|
117
|
+
|
|
118
|
+
// Full UI
|
|
130
119
|
return (
|
|
131
120
|
<div className={`TabBox-container ${noBottomMargin ? '' : 'mb-2'}`}>
|
|
132
121
|
{/* Style */}
|
|
133
122
|
<style>{style}</style>
|
|
134
123
|
|
|
135
|
-
{/* Title
|
|
124
|
+
{/* Title */}
|
|
136
125
|
<div className="TabBox-title-container">
|
|
137
126
|
<div className="TabBox-title">
|
|
138
127
|
{title}
|
|
139
128
|
</div>
|
|
140
|
-
{topRightChildren && (
|
|
141
|
-
<div className="TabBox-title-right-container">
|
|
142
|
-
<div className="TabBox-title-right-contents">
|
|
143
|
-
{topRightChildren}
|
|
144
|
-
</div>
|
|
145
|
-
</div>
|
|
146
|
-
)}
|
|
147
129
|
</div>
|
|
148
130
|
|
|
149
131
|
{/* Contents */}
|
package/src/index.ts
CHANGED
|
@@ -15,7 +15,6 @@ import RadioButton from './components/RadioButton';
|
|
|
15
15
|
import CheckboxButton from './components/CheckboxButton';
|
|
16
16
|
import ButtonInputGroup from './components/ButtonInputGroup';
|
|
17
17
|
import SimpleDateChooser from './components/SimpleDateChooser';
|
|
18
|
-
import SimpleTimeChooser from './components/SimpleTimeChooser';
|
|
19
18
|
import Drawer from './components/Drawer';
|
|
20
19
|
import PopSuccessMark from './components/PopSuccessMark';
|
|
21
20
|
import PopFailureMark from './components/PopFailureMark';
|
|
@@ -92,7 +91,6 @@ import mapAsync from './helpers/asyncArrayFunctions/mapAsync';
|
|
|
92
91
|
import someAsync from './helpers/asyncArrayFunctions/someAsync';
|
|
93
92
|
import capitalize from './helpers/capitalize';
|
|
94
93
|
import shuffleArray from './helpers/shuffleArray';
|
|
95
|
-
import getWordCount from './helpers/getWordCount';
|
|
96
94
|
|
|
97
95
|
// Import types
|
|
98
96
|
import ParamType from './types/ParamType';
|
|
@@ -134,7 +132,6 @@ export {
|
|
|
134
132
|
CheckboxButton,
|
|
135
133
|
ButtonInputGroup,
|
|
136
134
|
SimpleDateChooser,
|
|
137
|
-
SimpleTimeChooser,
|
|
138
135
|
Drawer,
|
|
139
136
|
PopSuccessMark,
|
|
140
137
|
PopFailureMark,
|
|
@@ -207,7 +204,6 @@ export {
|
|
|
207
204
|
someAsync,
|
|
208
205
|
capitalize,
|
|
209
206
|
shuffleArray,
|
|
210
|
-
getWordCount,
|
|
211
207
|
// Client helpers
|
|
212
208
|
initClient,
|
|
213
209
|
visitServerEndpoint,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Highest error code =
|
|
1
|
+
// Highest error code = DRK34
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* List of error codes built into the react kit
|
|
@@ -9,8 +9,6 @@ enum ReactKitErrorCode {
|
|
|
9
9
|
NoCode = 'DRK2',
|
|
10
10
|
SessionExpired = 'DRK3',
|
|
11
11
|
NoCACCLSendRequestFunction = 'DRK7',
|
|
12
|
-
SimpleDateChooserInvalidDateRange = 'DRK35',
|
|
13
|
-
SimpleDateChooserInvalidNumMonths = 'DRK36',
|
|
14
12
|
}
|
|
15
13
|
|
|
16
14
|
export default ReactKitErrorCode;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A very simple, lightweight time chooser
|
|
3
|
-
* @author Gardenia Liu
|
|
4
|
-
*/
|
|
5
|
-
import React from 'react';
|
|
6
|
-
type Props = {
|
|
7
|
-
ariaLabel: string;
|
|
8
|
-
name: string;
|
|
9
|
-
hour: number;
|
|
10
|
-
minute: number;
|
|
11
|
-
/**
|
|
12
|
-
* Handler for when time changes
|
|
13
|
-
* @param hour new 24hr hour number
|
|
14
|
-
* @param minute new minute number
|
|
15
|
-
*/
|
|
16
|
-
onChange: (hour: number, minute: number) => void;
|
|
17
|
-
intervalMin?: number;
|
|
18
|
-
};
|
|
19
|
-
declare const SimpleTimeChooser: React.FC<Props>;
|
|
20
|
-
export default SimpleTimeChooser;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Get number of words in string
|
|
3
|
-
* @author Gardenia Liu
|
|
4
|
-
* @author Allison Zhang
|
|
5
|
-
* @author Gabe Abrams
|
|
6
|
-
* @param text the string to check
|
|
7
|
-
* @returns number of words in the string
|
|
8
|
-
*/
|
|
9
|
-
declare const getWordCount: (text: string) => number;
|
|
10
|
-
export default getWordCount;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A very simple, lightweight time chooser
|
|
3
|
-
* @author Gardenia Liu
|
|
4
|
-
*/
|
|
5
|
-
import React from 'react';
|
|
6
|
-
type Props = {
|
|
7
|
-
ariaLabel: string;
|
|
8
|
-
name: string;
|
|
9
|
-
hour: number;
|
|
10
|
-
minute: number;
|
|
11
|
-
/**
|
|
12
|
-
* Handler for when time changes
|
|
13
|
-
* @param hour new 24hr hour number
|
|
14
|
-
* @param minute new minute number
|
|
15
|
-
*/
|
|
16
|
-
onChange: (hour: number, minute: number) => void;
|
|
17
|
-
intervalMin?: number;
|
|
18
|
-
};
|
|
19
|
-
declare const SimpleTimeChooser: React.FC<Props>;
|
|
20
|
-
export default SimpleTimeChooser;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Get number of words in string
|
|
3
|
-
* @author Gardenia Liu
|
|
4
|
-
* @author Allison Zhang
|
|
5
|
-
* @author Gabe Abrams
|
|
6
|
-
* @param text the string to check
|
|
7
|
-
* @returns number of words in the string
|
|
8
|
-
*/
|
|
9
|
-
declare const getWordCount: (text: string) => number;
|
|
10
|
-
export default getWordCount;
|
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A very simple, lightweight time chooser
|
|
3
|
-
* @author Gardenia Liu
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// Import React
|
|
7
|
-
import React from 'react';
|
|
8
|
-
|
|
9
|
-
// Import helpers
|
|
10
|
-
import padZerosLeft from '../helpers/padZerosLeft';
|
|
11
|
-
|
|
12
|
-
/*------------------------------------------------------------------------*/
|
|
13
|
-
/* -------------------------------- Types ------------------------------- */
|
|
14
|
-
/*------------------------------------------------------------------------*/
|
|
15
|
-
|
|
16
|
-
type Props = {
|
|
17
|
-
// Aria label
|
|
18
|
-
ariaLabel: string,
|
|
19
|
-
// Name of the chooser (machine-readable, hyphenated)
|
|
20
|
-
name: string,
|
|
21
|
-
// Currently selected hour of the day (24hr)
|
|
22
|
-
hour: number,
|
|
23
|
-
// Currently selected minute within the hour
|
|
24
|
-
minute: number,
|
|
25
|
-
/**
|
|
26
|
-
* Handler for when time changes
|
|
27
|
-
* @param hour new 24hr hour number
|
|
28
|
-
* @param minute new minute number
|
|
29
|
-
*/
|
|
30
|
-
onChange: (hour: number, minute: number) => void,
|
|
31
|
-
// Interval in minutes between each choice
|
|
32
|
-
// Allowed options: 15, 30, 60, defaults to 15
|
|
33
|
-
// If an unsupported interval is passed in, it will default to 15
|
|
34
|
-
intervalMin?: number,
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
/*------------------------------------------------------------------------*/
|
|
38
|
-
/* ------------------------------ Constants ----------------------------- */
|
|
39
|
-
/*------------------------------------------------------------------------*/
|
|
40
|
-
|
|
41
|
-
// Allowed intervals between options
|
|
42
|
-
const ALLOWED_INTERVALS = [15, 30, 60]; // min
|
|
43
|
-
|
|
44
|
-
// Default interval to use if an unsupported interval is passed in
|
|
45
|
-
const DEFAULT_INTERVAL = ALLOWED_INTERVALS[0]; // min
|
|
46
|
-
|
|
47
|
-
/*------------------------------------------------------------------------*/
|
|
48
|
-
/* ------------------------------ Component ----------------------------- */
|
|
49
|
-
/*------------------------------------------------------------------------*/
|
|
50
|
-
|
|
51
|
-
const SimpleTimeChooser: React.FC<Props> = (props) => {
|
|
52
|
-
/*------------------------------------------------------------------------*/
|
|
53
|
-
/* -------------------------------- Setup ------------------------------- */
|
|
54
|
-
/*------------------------------------------------------------------------*/
|
|
55
|
-
|
|
56
|
-
/* -------------- Props ------------- */
|
|
57
|
-
|
|
58
|
-
const {
|
|
59
|
-
ariaLabel,
|
|
60
|
-
name,
|
|
61
|
-
hour,
|
|
62
|
-
minute,
|
|
63
|
-
onChange,
|
|
64
|
-
} = props;
|
|
65
|
-
let {
|
|
66
|
-
intervalMin = DEFAULT_INTERVAL,
|
|
67
|
-
} = props;
|
|
68
|
-
|
|
69
|
-
// Use default interval if not supported
|
|
70
|
-
if (ALLOWED_INTERVALS.includes(intervalMin)) {
|
|
71
|
-
intervalMin = DEFAULT_INTERVAL;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/*------------------------------------------------------------------------*/
|
|
75
|
-
/* ------------------------- Component Functions ------------------------ */
|
|
76
|
-
/*------------------------------------------------------------------------*/
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Convert number of minutes since midnight into 24hour and minute format
|
|
80
|
-
* @author Gabe Abrams
|
|
81
|
-
* @param minSinceMidnight total minutes since midnight
|
|
82
|
-
* @returns hours (24) and minutes
|
|
83
|
-
*/
|
|
84
|
-
const convertMinSinceMidnightToHoursAndMin = (minSinceMidnight: number): {
|
|
85
|
-
hours: number,
|
|
86
|
-
minutes: number,
|
|
87
|
-
} => {
|
|
88
|
-
return {
|
|
89
|
-
hours: Math.floor(minSinceMidnight / 60),
|
|
90
|
-
minutes: minSinceMidnight % 60,
|
|
91
|
-
};
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Convert time in minutes into HH:MM format
|
|
96
|
-
* @author Gardenia Liu
|
|
97
|
-
* @param totalMinutes total minutes since midnight
|
|
98
|
-
* @returns formatted time string
|
|
99
|
-
*/
|
|
100
|
-
const formatTime = (totalMinutes: number): string => {
|
|
101
|
-
// Handle special cases
|
|
102
|
-
if (totalMinutes === 0) {
|
|
103
|
-
return '12:00 Midnight';
|
|
104
|
-
}
|
|
105
|
-
if (totalMinutes === 12 * 60) {
|
|
106
|
-
return '12:00 Noon';
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// All normal cases:
|
|
110
|
-
const timeInfo = convertMinSinceMidnightToHoursAndMin(totalMinutes);
|
|
111
|
-
let { hours } = timeInfo;
|
|
112
|
-
const { minutes } = timeInfo;
|
|
113
|
-
|
|
114
|
-
// Process 24hr -> 12hr
|
|
115
|
-
const isAM = (hours < 12);
|
|
116
|
-
if (hours === 0) {
|
|
117
|
-
hours = 12;
|
|
118
|
-
} else if (hours > 12) {
|
|
119
|
-
hours %= 12;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Pad with zeros
|
|
123
|
-
const paddedMinutes = padZerosLeft(minutes, 2);
|
|
124
|
-
|
|
125
|
-
// Assemble time string
|
|
126
|
-
return `${hours}:${paddedMinutes} ${isAM ? 'AM' : 'PM'}`;
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
/*------------------------------------------------------------------------*/
|
|
130
|
-
/* ------------------------------- Render ------------------------------- */
|
|
131
|
-
/*------------------------------------------------------------------------*/
|
|
132
|
-
|
|
133
|
-
/*----------------------------------------*/
|
|
134
|
-
/* --------------- Main UI -------------- */
|
|
135
|
-
/*----------------------------------------*/
|
|
136
|
-
|
|
137
|
-
// Generate list of time options
|
|
138
|
-
const times: string[] = [];
|
|
139
|
-
for (let time = 0; time < 24 * 60; time += intervalMin) {
|
|
140
|
-
times.push(formatTime(time));
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Create choice options
|
|
144
|
-
const selectedTimeMin = hour * 60 + minute; // minutes since midnight
|
|
145
|
-
const timeOptions: React.ReactNode[] = times.map((timeString, timeIndex) => {
|
|
146
|
-
// Create time option
|
|
147
|
-
const numMinutesForChoice = timeIndex * intervalMin;
|
|
148
|
-
|
|
149
|
-
// Render the option
|
|
150
|
-
return (
|
|
151
|
-
<option
|
|
152
|
-
key={numMinutesForChoice}
|
|
153
|
-
value={numMinutesForChoice}
|
|
154
|
-
aria-label={`choose ${timeString}`}
|
|
155
|
-
>
|
|
156
|
-
{timeString}
|
|
157
|
-
</option>
|
|
158
|
-
);
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
return (
|
|
162
|
-
<div
|
|
163
|
-
className="SimpleTimeChooser-container"
|
|
164
|
-
aria-label={`time chooser with selected time: ${formatTime(selectedTimeMin)}`}
|
|
165
|
-
>
|
|
166
|
-
{/* Time Chooser */}
|
|
167
|
-
<select
|
|
168
|
-
aria-label={`time for ${ariaLabel}`}
|
|
169
|
-
className="custom-select d-inline-block"
|
|
170
|
-
style={{ width: 'auto' }}
|
|
171
|
-
id={`SimpleTimeChooser-${name}-time`}
|
|
172
|
-
value={selectedTimeMin}
|
|
173
|
-
onChange={(e) => {
|
|
174
|
-
// Parse selector value (string)
|
|
175
|
-
const newTime = Number.parseInt(e.target.value, 10);
|
|
176
|
-
|
|
177
|
-
// Convert minutes since midnight to hour and minute
|
|
178
|
-
const timeInfo = convertMinSinceMidnightToHoursAndMin(newTime);
|
|
179
|
-
|
|
180
|
-
// Notify parent of change
|
|
181
|
-
onChange(timeInfo.hours, timeInfo.minutes);
|
|
182
|
-
}}
|
|
183
|
-
>
|
|
184
|
-
{timeOptions}
|
|
185
|
-
</select>
|
|
186
|
-
</div>
|
|
187
|
-
);
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
/*------------------------------------------------------------------------*/
|
|
191
|
-
/* ------------------------------- Wrap Up ------------------------------ */
|
|
192
|
-
/*------------------------------------------------------------------------*/
|
|
193
|
-
|
|
194
|
-
// Export component
|
|
195
|
-
export default SimpleTimeChooser;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
const punctuationRegex = /[!@#$%^&*(),.?\/;:'"\-\[\]]/g;
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Get number of words in string
|
|
5
|
-
* @author Gardenia Liu
|
|
6
|
-
* @author Allison Zhang
|
|
7
|
-
* @author Gabe Abrams
|
|
8
|
-
* @param text the string to check
|
|
9
|
-
* @returns number of words in the string
|
|
10
|
-
*/
|
|
11
|
-
const getWordCount = (text: string): number => {
|
|
12
|
-
const trimmedTextWithoutPunctuation = (
|
|
13
|
-
text
|
|
14
|
-
// Remove leading and trailing whitespace
|
|
15
|
-
.trim()
|
|
16
|
-
// Remove punctuation
|
|
17
|
-
.replace(punctuationRegex, '')
|
|
18
|
-
);
|
|
19
|
-
if (trimmedTextWithoutPunctuation.length === 0) {
|
|
20
|
-
return 0;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return trimmedTextWithoutPunctuation.split(/\s+/g).length;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export default getWordCount;
|