dce-reactkit 3.8.3 → 3.8.4

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.
@@ -0,0 +1,32 @@
1
+ /**
2
+ * A simple dropdown menu
3
+ * @author Alessandra De Lucas
4
+ * @author Gabe Abrams
5
+ * @author Yuen Ler Chow
6
+ */
7
+ import React from 'react';
8
+ import Variant from '../types/Variant';
9
+ import DropdownItemType from '../types/DropdownItemType';
10
+ type Props = {
11
+ items: DropdownItem[];
12
+ variant?: Variant;
13
+ dropdownButton: {
14
+ ariaLabel: string;
15
+ id: string;
16
+ content?: React.ReactNode;
17
+ };
18
+ };
19
+ type DropdownItem = ({
20
+ type: DropdownItemType.Header;
21
+ content: React.ReactNode;
22
+ } | {
23
+ type: DropdownItemType.Divider;
24
+ } | {
25
+ type: DropdownItemType.Item;
26
+ content: React.ReactNode;
27
+ ariaLabel: string;
28
+ id: string;
29
+ onClick: () => void;
30
+ });
31
+ declare const Dropdown: React.FC<Props>;
32
+ export default Dropdown;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * This function converts a string to title case based on Chicago Title Case
3
+ * Style rules.
4
+ * @author Leisha Bhandari
5
+ * @param input: The input string that needs to be converted to Chicago title
6
+ * case.
7
+ * @returns Input string converted to title case
8
+ */
9
+ declare const chicagoTitleCase: (input: string) => string;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * This function checks if a given input string is a valid URL.
3
+ * @author Leisha Bhandari
4
+ * @param URL: The input string that needs checked as a URL or not.
5
+ * @returns A true boolean value if the input string is a valid URL, and a false
6
+ * boolean value if the input string is a invalid URL
7
+ */
8
+ declare function isValid(url: string): boolean;
@@ -0,0 +1,6 @@
1
+ declare enum DropdownItemType {
2
+ Header = "Header",
3
+ Divider = "Divider",
4
+ Item = "Item"
5
+ }
6
+ export default DropdownItemType;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * A simple dropdown menu
3
+ * @author Alessandra De Lucas
4
+ * @author Gabe Abrams
5
+ * @author Yuen Ler Chow
6
+ */
7
+ import React from 'react';
8
+ import Variant from '../types/Variant';
9
+ import DropdownItemType from '../types/DropdownItemType';
10
+ type Props = {
11
+ items: DropdownItem[];
12
+ variant?: Variant;
13
+ dropdownButton: {
14
+ ariaLabel: string;
15
+ id: string;
16
+ content?: React.ReactNode;
17
+ };
18
+ };
19
+ type DropdownItem = ({
20
+ type: DropdownItemType.Header;
21
+ content: React.ReactNode;
22
+ } | {
23
+ type: DropdownItemType.Divider;
24
+ } | {
25
+ type: DropdownItemType.Item;
26
+ content: React.ReactNode;
27
+ ariaLabel: string;
28
+ id: string;
29
+ onClick: () => void;
30
+ });
31
+ declare const Dropdown: React.FC<Props>;
32
+ export default Dropdown;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * This function converts a string to title case based on Chicago Title Case
3
+ * Style rules.
4
+ * @author Leisha Bhandari
5
+ * @param input: The input string that needs to be converted to Chicago title
6
+ * case.
7
+ * @returns Input string converted to title case
8
+ */
9
+ declare const chicagoTitleCase: (input: string) => string;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * This function checks if a given input string is a valid URL.
3
+ * @author Leisha Bhandari
4
+ * @param URL: The input string that needs checked as a URL or not.
5
+ * @returns A true boolean value if the input string is a valid URL, and a false
6
+ * boolean value if the input string is a invalid URL
7
+ */
8
+ declare function isValid(url: string): boolean;
@@ -0,0 +1,6 @@
1
+ declare enum DropdownItemType {
2
+ Header = "Header",
3
+ Divider = "Divider",
4
+ Item = "Item"
5
+ }
6
+ export default DropdownItemType;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dce-reactkit",
3
- "version": "3.8.3",
3
+ "version": "3.8.4",
4
4
  "description": "Shared components for Harvard DCE apps",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -0,0 +1,308 @@
1
+ /**
2
+ * A simple dropdown menu
3
+ * @author Alessandra De Lucas
4
+ * @author Gabe Abrams
5
+ * @author Yuen Ler Chow
6
+ */
7
+
8
+ // Import React
9
+ import React, { useEffect, useReducer, useRef } from 'react';
10
+
11
+ // Import helpers
12
+ import combineClassNames from '../helpers/combineClassNames';
13
+
14
+ // Import shared types
15
+ import Variant from '../types/Variant';
16
+ import DropdownItemType from '../types/DropdownItemType';
17
+
18
+ /*------------------------------------------------------------------------*/
19
+ /* -------------------------------- Types ------------------------------- */
20
+ /*------------------------------------------------------------------------*/
21
+
22
+ // Props definition
23
+ type Props = {
24
+ // List of items in the dropdown menu
25
+ items: DropdownItem[],
26
+ // If true, dropdown variant is displayed
27
+ variant?: Variant,
28
+ // Information about the dropdown button
29
+ dropdownButton: {
30
+ // Aria label for accessibility
31
+ ariaLabel: string,
32
+ // Unique ID
33
+ id: string,
34
+ // Button content
35
+ content?: React.ReactNode,
36
+ },
37
+ // If true, no arrow shows in dropdown
38
+ // noArrow?: boolean,
39
+ // Size of dropdown
40
+ // size?: DropdownSize,
41
+ // Direction of dropdown
42
+ // direction?: DropdownDirection,
43
+ };
44
+
45
+ // Details about a dropdown item
46
+ type DropdownItem = (
47
+ | {
48
+ // Header element
49
+ type: DropdownItemType.Header,
50
+ // Header content
51
+ content: React.ReactNode,
52
+ }
53
+ | {
54
+ // Divider element
55
+ type: DropdownItemType.Divider,
56
+ }
57
+ | {
58
+ // Item from dropdown menu
59
+ type: DropdownItemType.Item,
60
+ // Item content
61
+ content: React.ReactNode,
62
+ // Item aria label
63
+ ariaLabel: string,
64
+ // Unique item ID
65
+ id: string,
66
+ // Click function for dropdown item
67
+ onClick: () => void,
68
+ }
69
+ );
70
+
71
+ // Dropdown menu sizes
72
+ // enum DropdownSize {
73
+ // // Small dropdown size
74
+ // Small = 'Small',
75
+ // // Medium dropdown size
76
+ // Medium = 'Medium',
77
+ // // Large dropdown size
78
+ // Large = 'Large',
79
+ // }
80
+
81
+ // Dropdown menu direction
82
+ // enum DropdownDirection {
83
+ // // Dropdown menu appears centered
84
+ // Centered = 'Centered',
85
+ // // Dropdown menu appears to right of button
86
+ // Right = 'Right',
87
+ // // Dropdown menu appears to left of button
88
+ // Left = 'Left',
89
+ // // Dropdown menu appears above the button
90
+ // Up = 'Up',
91
+ // // Dropdown menu appears below the button
92
+ // Down = 'Down',
93
+ // }
94
+
95
+ /*------------------------------------------------------------------------*/
96
+ /* -------------------------------- State ------------------------------- */
97
+ /*------------------------------------------------------------------------*/
98
+
99
+ /* -------- State Definition -------- */
100
+
101
+ type State = {
102
+ // If true, the dropdown menu is open
103
+ isDropdownOpen: boolean,
104
+ };
105
+
106
+ /* ------------- Actions ------------ */
107
+
108
+ // Types of actions
109
+ enum ActionType {
110
+ // Toggle opening the dropdown menu
111
+ ToggleDropdown = 'ToggleDropdown',
112
+ // Close the dropdown menu
113
+ CloseDropdown = 'CloseDropdown',
114
+ }
115
+
116
+ // Action definitions
117
+ type Action = (
118
+ | {
119
+ type: ActionType.ToggleDropdown,
120
+ }
121
+ | {
122
+ type: ActionType.CloseDropdown,
123
+ }
124
+ );
125
+
126
+ /**
127
+ * Reducer that executes actions
128
+ * @author Alessandra De Lucas
129
+ * @param state current state
130
+ * @param action action to execute
131
+ */
132
+ const reducer = (state: State, action: Action): State => {
133
+ switch (action.type) {
134
+ case ActionType.ToggleDropdown: {
135
+ return {
136
+ ...state,
137
+ isDropdownOpen: !state.isDropdownOpen,
138
+ };
139
+ }
140
+ case ActionType.CloseDropdown: {
141
+ return {
142
+ ...state,
143
+ isDropdownOpen: false,
144
+ };
145
+ }
146
+ default: {
147
+ return state;
148
+ }
149
+ }
150
+ };
151
+
152
+ /*------------------------------------------------------------------------*/
153
+ /* ------------------------------ Component ----------------------------- */
154
+ /*------------------------------------------------------------------------*/
155
+
156
+ const Dropdown: React.FC<Props> = (props) => {
157
+ /*------------------------------------------------------------------------*/
158
+ /* -------------------------------- Setup ------------------------------- */
159
+ /*------------------------------------------------------------------------*/
160
+
161
+ /* -------------- Props ------------- */
162
+
163
+ // Destructure all props
164
+ const {
165
+ dropdownButton,
166
+ items,
167
+ variant = Variant.Secondary,
168
+ } = props;
169
+
170
+ /* -------------- State ------------- */
171
+
172
+ // Initial state
173
+ const initialState: State = {
174
+ isDropdownOpen: false,
175
+ };
176
+
177
+ // Initialize state
178
+ const [state, dispatch] = useReducer(reducer, initialState);
179
+
180
+ // Destructure common state
181
+ const {
182
+ isDropdownOpen,
183
+ } = state;
184
+
185
+ /* -------------- Refs -------------- */
186
+
187
+ // Initialize refs
188
+ const dropdownRef = useRef<HTMLDivElement>(null);
189
+
190
+ /*------------------------------------------------------------------------*/
191
+ /* ------------------------- Component Functions ------------------------ */
192
+ /*------------------------------------------------------------------------*/
193
+
194
+ /**
195
+ * Handle clicking outside of the dropdown menu to close it
196
+ * @author Yuen Ler Chow
197
+ * @param event the mouse event
198
+ */
199
+ const handleClickOutside = (event: MouseEvent) => {
200
+ if (
201
+ dropdownRef.current && !dropdownRef.current.contains(event.target as Node)
202
+ ) {
203
+ dispatch({ type: ActionType.CloseDropdown });
204
+ }
205
+ };
206
+
207
+ /*------------------------------------------------------------------------*/
208
+ /* ------------------------- Lifecycle Functions ------------------------ */
209
+ /*------------------------------------------------------------------------*/
210
+
211
+ /**
212
+ * Mount
213
+ * @author Yuen Ler Chow
214
+ */
215
+ useEffect(() => {
216
+ // Add event listener to close dropdown when clicking outside
217
+ document.addEventListener('mousedown', handleClickOutside);
218
+
219
+ // Cleanup
220
+ return () => {
221
+ document.removeEventListener('mousedown', handleClickOutside);
222
+ };
223
+ }, []);
224
+
225
+ /*----------------------------------------*/
226
+ /* --------------- Main UI -------------- */
227
+ /*----------------------------------------*/
228
+
229
+ return (
230
+ <div className="dropdown" ref={dropdownRef}>
231
+ <button
232
+ className={
233
+ combineClassNames([
234
+ 'btn dropdown-toggle border',
235
+ isDropdownOpen && 'show',
236
+ `btn-${variant}`,
237
+ variant === Variant.Light && 'text-dark',
238
+ ])
239
+ }
240
+ type="button"
241
+ id={dropdownButton.id}
242
+ aria-expanded={isDropdownOpen}
243
+ aria-label={dropdownButton.ariaLabel}
244
+ onClick={() => {
245
+ dispatch({
246
+ type: ActionType.ToggleDropdown,
247
+ });
248
+ }}
249
+ >
250
+ {
251
+ dropdownButton.content
252
+ }
253
+ </button>
254
+ <ul className={
255
+ combineClassNames([
256
+ 'dropdown-menu',
257
+ `dropdown-menu-${variant}`,
258
+ isDropdownOpen && 'show',
259
+ ])
260
+ }
261
+ >
262
+ {Object.values(items).map((item) => {
263
+ if (item.type === DropdownItemType.Header) {
264
+ return (
265
+ // TODO: Implement header
266
+ <span />
267
+ );
268
+ }
269
+ if (item.type === DropdownItemType.Divider) {
270
+ return (
271
+ // TODO: Implement divider
272
+ <span />
273
+ );
274
+ }
275
+ return (
276
+ <li
277
+ key={item.id}
278
+ >
279
+ <button
280
+ type="button"
281
+ aria-label={item.ariaLabel}
282
+ className="dropdown-item"
283
+ onClick={(e) => {
284
+ e.preventDefault();
285
+ dispatch({
286
+ type: ActionType.CloseDropdown,
287
+ });
288
+ item.onClick();
289
+ }}
290
+ >
291
+ {
292
+ item.content
293
+ }
294
+ </button>
295
+ </li>
296
+ );
297
+ })}
298
+ </ul>
299
+ </div>
300
+ );
301
+ };
302
+
303
+ /*------------------------------------------------------------------------*/
304
+ /* ------------------------------- Wrap Up ------------------------------ */
305
+ /*------------------------------------------------------------------------*/
306
+
307
+ // Export component
308
+ export default Dropdown;
@@ -0,0 +1,85 @@
1
+ // Importing the testing function
2
+ // import chicagoTitleCase from './chicagoTitleCase';
3
+
4
+ // // Import constants
5
+ // import { INVALID_STRING_ERRORS, INVALID_REGEX_ERROR } from './shared/constants/ERROR_MESSAGES';
6
+
7
+ // /*------------------------------------------------------------------------*/
8
+ // /* ---------------------------- Valid Tests --------------------------- */
9
+ // /*------------------------------------------------------------------------*/
10
+
11
+ // const validTests: { input: string, expected: string }[] = [
12
+ // {
13
+ // input: 'this is the american language',
14
+ // expected: 'This the American language',
15
+ // },
16
+ // {
17
+ // input: 'to kill a mockingbird',
18
+ // expected: 'To Kill a Mockingbird',
19
+ // },
20
+ // {
21
+ // input: 'the lord of the rings',
22
+ // expected: 'The Lord of the Rings',
23
+ // },
24
+ // {
25
+ // input: 'pride and prejudice',
26
+ // expected: 'Pride and Prejudice',
27
+ // },
28
+ // {
29
+ // input: 'the road not taken',
30
+ // expected: 'The Road Not Taken',
31
+ // },
32
+ // ];
33
+
34
+ // test(
35
+ // 'Converts strings to Chicago title case correctly.',
36
+ // async () => {
37
+ // validTests.forEach(({ input, expected }) => {
38
+ // expect(chicagoTitleCase(input)).toBe(expected);
39
+ // });
40
+ // },
41
+ // );
42
+
43
+ // /*------------------------------------------------------------------------*/
44
+ // /* ---------------------------- Edge Cases ---------------------------- */
45
+ // /*------------------------------------------------------------------------*/
46
+
47
+ // const edgeCases: { input: string, expected: string }[] = [
48
+ // {
49
+ // input: 'x',
50
+ // expected: 'X',
51
+ // },
52
+ // {
53
+ // input: ' ',
54
+ // expected: ' ',
55
+ // },
56
+ // {
57
+ // input: '',
58
+ // expected: '',
59
+ // },
60
+ // {
61
+ // input: 'the',
62
+ // expected: 'The',
63
+ // },
64
+ // {
65
+ // input: 'THE ROAD NOT TAKEN',
66
+ // expected: 'The Road Not Taken',
67
+ // },
68
+ // {
69
+ // input: 'tO kiLL A mOckingBirD',
70
+ // expected: 'To Kill a Mockingbird',
71
+ // },
72
+ // {
73
+ // input: 'pRiDe And pReduJiCe',
74
+ // expected: 'Pride and Prejudice',
75
+ // },
76
+ // ];
77
+
78
+ // test(
79
+ // 'Handles the edge cases for the function that converts a string to Chicago Title Case.',
80
+ // async () => {
81
+ // edgeCases.forEach(({ input, expected }) => {
82
+ // expect(chicagoTitleCase(input)).toBe(expected);
83
+ // });
84
+ // },
85
+ // );
@@ -0,0 +1,32 @@
1
+ /**
2
+ * This function converts a string to title case based on Chicago Title Case
3
+ * Style rules.
4
+ * @author Leisha Bhandari
5
+ * @param input: The input string that needs to be converted to Chicago title
6
+ * case.
7
+ * @returns Input string converted to title case
8
+ */
9
+
10
+
11
+ const chicagoTitleCase = (input: string): string => {
12
+ // List of lowercase words according to Chicago Manual of Style
13
+ const lowerCaseWords: string[] = [
14
+ 'in', 'nor', 'of', 'on', 'or', 'as', 'at', 'but', 'by',
15
+ 'for', 'if', 'so', 'the', 'a', 'an', 'and', 'to', 'up',
16
+ 'yet'
17
+ ];
18
+
19
+ return input
20
+ // Converts given input string to lowercase
21
+ .toLowerCase()
22
+ // Splits the given string into separate words
23
+ .split(' ')
24
+ .map((word, index, words) =>
25
+ // Capitalize the first word, last word, and the words that aren't
26
+ // in lowerCaseWords
27
+ index === 0 || !lowerCaseWords.includes(word) || index === words.length - 1
28
+ ? `${word.charAt(0).toUpperCase()}${word.slice(1)}` // Capitalize the first letter
29
+ : word // Nothing happens to the word
30
+ )
31
+ .join(' '); // Joins the words back
32
+ };
@@ -0,0 +1,83 @@
1
+ // Import the function to be tested
2
+ // import findURLs from './findURL';
3
+
4
+ // // Import constants
5
+ // import { INVALID_STRING_ERRORS, INVALID_REGEX_ERROR } from './shared/constants/ERROR_MESSAGES';
6
+
7
+ // /*------------------------------------------------------------------------*/
8
+ // /* ---------------------------- Valid Tests --------------------------- */
9
+ // /*------------------------------------------------------------------------*/
10
+
11
+ // const validTests: { block: string, expected: { start: number, end: number }[] }[] = [
12
+ // {
13
+ // block: 'Visit http://example.com for more information.',
14
+ // expected: [{ start: 6, end: 23 }],
15
+ // },
16
+ // {
17
+ // block: 'Multiple URLs: http://one.com and http://two.com.',
18
+ // expected: [
19
+ // { start: 15, end: 29 },
20
+ // { start: 34, end: 48 },
21
+ // ],
22
+ // },
23
+ // {
24
+ // block: 'Localhost URLs: http://localhost and http://127.0.0.1.',
25
+ // expected: [
26
+ // { start: 16, end: 31 },
27
+ // { start: 36, end: 52 },
28
+ // ],
29
+ // },
30
+ // {
31
+ // block: 'Embedded URL: text https://embedded-url.com?query=1&value=2.',
32
+ // expected: [{ start: 13, end: 51 }],
33
+ // },
34
+ // {
35
+ // block: 'Secure site: https://secure-site.com/path?query=string#fragment',
36
+ // expected: [{ start: 13, end: 58 }],
37
+ // },
38
+ // ];
39
+
40
+ // test(
41
+ // 'Returns correct start and end indices for valid URLs within a string.',
42
+ // async () => {
43
+ // validTests.forEach(({ block, expected }) => {
44
+ // expect(findURLs(block)).toStrictEqual(expected);
45
+ // });
46
+ // },
47
+ // );
48
+
49
+ // /*------------------------------------------------------------------------*/
50
+ // /* ---------------------------- Invalid Tests --------------------------- */
51
+ // /*------------------------------------------------------------------------*/
52
+
53
+ // const invalidTests: { block: string, expected: { start: number, end: number }[] }[] = [
54
+ // {
55
+ // block: 'No URL.',
56
+ // expected: [],
57
+ // },
58
+ // {
59
+ // block: 'URL format is wrong: http:/example.com and htt://example.com.',
60
+ // expected: [],
61
+ // },
62
+ // {
63
+ // block: 'Any punctuation after the URL http://example.com, should not count.',
64
+ // expected: [{ start: 20, end: 37 }],
65
+ // },
66
+ // {
67
+ // block: 'Starting punctuation ,http://example.com should not count.',
68
+ // expected: [{ start: 22, end: 39 }],
69
+ // },
70
+ // {
71
+ // block: 'Spaces in the middle http://exa mple.com is invalid.',
72
+ // expected: [],
73
+ // },
74
+ // ];
75
+
76
+ // test(
77
+ // 'Returns empty array for strings without valid URLs.',
78
+ // async () => {
79
+ // invalidTests.forEach(({ block, expected }) => {
80
+ // expect(findURLs(block)).toStrictEqual(expected);
81
+ // });
82
+ // },
83
+ // );
@@ -0,0 +1,43 @@
1
+ // /**
2
+ // * This function finds URLs within a given string and returns an array of
3
+ // * their locations.
4
+ // * @author Leisha Bhandari
5
+ // * @param block: The block of text to search for URLs
6
+ // * @returns Arrays where each of them contain the start and end index of the URL
7
+ // */
8
+ // function findURLs(block: string): { start: number, end: number }[] {
9
+ // // Expression representing the skeleton of a URL to help match and find the
10
+ // // URLs within the block of text (Also takes care of Unicode characters)
11
+ // const urlSkeleton = /(https?:\/\/[^\s\u0000-\u001F.,]+[^\s\u0000-\u001F.,]?(?:\?[^\s\u0000-\u001F]+)?(?:#[^\s\u0000-\u001F]+)?)/g;
12
+ // const found: { start: number, end: number }[] = [];
13
+ // let match: RegExpExecArray | null;
14
+
15
+ // // While loop to find the URLs in the given block of texts using the URL
16
+ // // skeleton
17
+ // while ((match === urlSkeleton.exec(block))
18
+ // && match !== null) {
19
+ // // To find the beginning index of the URL
20
+ // let start = match.index;
21
+ // // To find the last index of the URL
22
+ // let end = match.index + match[0].length;
23
+
24
+ // // If statements to check whether the URL is followed by some kind of
25
+ // // punctuation mark
26
+ // if (block.charAt(end) === '.' || /[,;:!?"]/.test(block.charAt(end))) {
27
+ // end--;
28
+ // }
29
+
30
+ // // While statement to make sure that the URL does not start with a
31
+ // // punctuation mark
32
+ // while (start > 0 && /[.,:;!?]/.test(block.charAt(start - 1))) {
33
+ // start--;
34
+ // }
35
+
36
+ // // The object with start and end index of the URL is found and pushed to
37
+ // // the found array
38
+ // found.push({ start, end });
39
+ // }
40
+
41
+ // // Returns the array of the found URLs location
42
+ // return found;
43
+ // }
@@ -0,0 +1,90 @@
1
+
2
+ // Import the function to be tested
3
+ // import isValid from './validURL';
4
+
5
+ // // Import constants
6
+ // import { INVALID_STRING_ERRORS, INVALID_REGEX_ERROR } from './shared/constants/ERROR_MESSAGES';
7
+
8
+ // /*------------------------------------------------------------------------*/
9
+ // /* ---------------------------- Valid Tests --------------------------- */
10
+ // /*------------------------------------------------------------------------*/
11
+
12
+ // const validUrls: string[] = [
13
+ // 'http://example.com',
14
+ // 'https://example.com',
15
+ // 'http://www.example.com',
16
+ // 'https://www.example.com',
17
+ // 'https://example.com/path',
18
+ // 'http://example.com/path',
19
+ // 'https://example.com?query=string',
20
+ // 'http://example.com?query=string',
21
+ // 'https://example.com#fragment',
22
+ // 'http://example.com#fragment',
23
+ // 'http://localhost',
24
+ // 'https://localhost:3000',
25
+ // 'http://localhost:3000',
26
+ // 'http://127.0.0.1',
27
+ // 'http://127.0.0.1:3000',
28
+ // 'ftp://example.com/path',
29
+ // 'ftp://example.com',
30
+ // 'https://127.0.0.1:3000',
31
+ // 'file:///C:/path/to/file'
32
+ // ];
33
+
34
+ // test(
35
+ // 'Returns true for a given valid URL.',
36
+ // async () => {
37
+ // validUrls.forEach((url) => {
38
+ // expect(isValid(url)).toBe(true);
39
+ // });
40
+ // },
41
+ // );
42
+
43
+ // /*------------------------------------------------------------------------*/
44
+ // /* ---------------------------- Invalid Tests --------------------------- */
45
+ // /*------------------------------------------------------------------------*/
46
+
47
+ // const invalidUrls: string[] = [
48
+ // '',
49
+ // ' ',
50
+ // 'example',
51
+ // 'http://',
52
+ // 'http://.',
53
+ // 'http://..',
54
+ // 'http://##/',
55
+ // 'http://../',
56
+ // 'http://??/',
57
+ // 'http://#',
58
+ // 'http://##',
59
+ // '//',
60
+ // '//a',
61
+ // '///a',
62
+ // '///',
63
+ // 'http:///a',
64
+ // 'http://www.foo.bar./',
65
+ // 'http://foo.bar/foo(bar)baz quux',
66
+ // 'http://3628126748',
67
+ // 'http://.www.foo.bar/',
68
+ // 'http://.www.foo.bar./',
69
+ // 'http://123.123.123',
70
+ // 'http://1.1.1.1.1',
71
+ // 'http://example.com:99999',
72
+ // 'http://example.com:80:80',
73
+ // 'http://example.com::80',
74
+ // 'http://example.com:-80',
75
+ // 'http://-example.com',
76
+ // 'http://example.com-',
77
+ // 'http://example.com_',
78
+ // 'http://example..com',
79
+ // 'http://example.com.',
80
+ // 'http://.example.com'
81
+ // ];
82
+
83
+ // test(
84
+ // 'Returns false for a given invalid URL.',
85
+ // async () => {
86
+ // invalidUrls.forEach((url) => {
87
+ // expect(isValid(url)).toBe(false);
88
+ // });
89
+ // },
90
+ // );
@@ -0,0 +1,18 @@
1
+ /**
2
+ * This function checks if a given input string is a valid URL.
3
+ * @author Leisha Bhandari
4
+ * @param URL: The input string that needs checked as a URL or not.
5
+ * @returns A true boolean value if the input string is a valid URL, and a false
6
+ * boolean value if the input string is a invalid URL
7
+ */
8
+ function isValid(url: string): boolean {
9
+ // Uses the input URL to create a URL object
10
+ try {
11
+ new URL(url);
12
+ // URL constructor does not throw an error, so input URL is valid
13
+ return true;
14
+ } catch (err) {
15
+ // URL constructor throws an error, so input URL is invalid
16
+ return false;
17
+ }
18
+ }
@@ -0,0 +1,11 @@
1
+ // Types of dropdown items
2
+ enum DropdownItemType {
3
+ // Dropdown header
4
+ Header = 'Header',
5
+ // Dropdown divider
6
+ Divider = 'Divider',
7
+ // Dropdown item
8
+ Item = 'Item',
9
+ }
10
+
11
+ export default DropdownItemType;